swagger-autogen: How to add multiple servers? - swagger

How to add multiple servers to swagger with swagger-autogen?
the documentation is providing only one host here
I want to do something like that:
const doc = {
.
.
hosts: ['localhost:3000', 'localhost:5000'],
.
.
};
but when I did it, the base URL became http://localhost:3000localhost:5000/
is there any way to add multiple servers to swagger-autogen?

yes, there is a way:
Enable the OpenAPI v3 in the options here
const swaggerAutogen = require('swagger-autogen')({openapi: '3.0.0'});
Remove host, basePath, and schemes from object doc
Add the following array instead:
const doc = {
.
.
servers: [
{
url: "http://localhost:3000/",
description: "main server"
},
{
url: "http://localhost:5000/",
description: "the other server"
}
],
.
.
};
it didn't exist in the documentation, but it works since the object doc is converted into a JSON object inside the file named swagger-output.json

Related

Open Api swagger docs with service names of the format ***-service

I have a java spring boot service mesh of services.
I am using open api for swagger documentation.
When I run my spring cloud gateway and access http://localhost:{my-port}/swagger-ui.html, it works fine and loads the swagger ui which mentions /v3/api-docs in the "Explore" title bar.
Also, when I add the service name to the url like so /v3/api-docs/my-service, it works fine.
However, I want to try a list of dropdown services instead of manually appending the service name for each service. I have tried this grouping code in my gateway:
#Bean
fun apis(): List<GroupedOpenApi> {
val groups = ArrayList<GroupedOpenApi>()
val definitions = locator!!.routeDefinitions.collectList().block()
definitions!!.stream().filter { routeDefinition -> routeDefinition.id.matches(".*-service".toRegex()) }.forEach { routeDefinition ->
val name = routeDefinition.id.replace("-service".toRegex(), "")
GroupedOpenApi.builder().pathsToMatch("/$name/**").setGroup(name).build()
}
return groups
}
Now, after this when I access http://localhost:{my-port}/swagger-ui.html, it shows a drop down list of all the service with the "-service" removed. But after selection, the docs don't show up.
Although, if I access it in a separate tab with http://localhost:{my-port}/v3/api-docs/my-service, it shows me the json of all the paths and works fine. Just doesn't load in the swagger ui.
Here's gateway route for one of the service and openapi:
- id: my-service
uri: lb://my-service
predicates:
- Path=/api/v1/my/**
filters:
- name: CircuitBreaker
args:
name: my-service
fallbackuri: forward:/myServiceFallBack

Changing swagger-ui server variable at runtime

Using an openapi v3 configuration I have a server variable called 'hostname' that is used to build the url, like:
...
servers:
- url: http://{hostname}/api
variables:
hostname:
"default": "some default here"
....
At runtime I'd like to be able to change the 'hostname' server variable. I've found the UI element on the page,
<input type="text" value="some default here" data-variable="hostname">
Changing the variable by editing the input field works fine, but changing the input field via jQuery isn't working, even when triggering the "change" event after setting the value, the value reverts when expanding one of the api sections. I also tried triggering the keyup/keydown and focusin/focusout events to better simulate how a user would change the field.
Is there a more swagger-ui approach to changing this value through an exposed call? I've looked through window.ui but its kind of cryptic.
I have an api.yaml file hosted on different IoT devices. Each device will have a different hostname based on its configuration. When the page is loaded I'm trying to use javascript to set the 'hostname' server variable to be window.location.hostname, for example via javascript.
You can simply specify a relative server url – it will be resolved relative to the location of the OpenAPI definition file.
For example, if you have
servers:
- url: /api
and the API definition file is at
http://foobar/spec/api.yaml
then the base url for API calls will be resolved to
http://foobar/api
You can alter the spec json before it render by writing a plugin
const ui = SwaggerUI({
// ...
plugins: [
// add a plugin to alter spec before it rendered
{
statePlugins: {
spec: {
wrapActions: {
updateJsonSpec: function(oriAction, system) {
return (spec) => {
// change spec.servers here to add new entry, use concat to put it as the first & default one
spec.servers = [{url: someDynamicUrlInRuntime}].concat(spec.servers || [])
return oriAction(spec)
}
}
}
}
}
}
]
// ...
})
Adapting the answer from nevermind for use with SwaggerUIBundle as used in the index.html from swagger-ui:
plugins: [
SwaggerUIBundle.plugins.DownloadUrl,
// Custom plugin that replaces the server list with the current url
function() {
return {
statePlugins: {
spec: {
wrapActions: {
updateJsonSpec: function(oriAction, system) {
return (spec) => {
spec.servers = [{url: window.location.origin}]
return oriAction(spec)
}
}
}
}
}
}
}
],
This way the index.html can be served from the backend service itself and will refer only on its own url.

How to access swagger yaml defined objects from javascript

I used Swagger Yaml to describe an endpoint and generate the mock server. The existing endpoint (that I'm mocking) doesn't follow RESTful principles 100%, so I simply want to overwrite the response that is returned by the mock server. The simple server code is shown below:
var swagger = require('swagger-server');
var server = swagger('map-cache.yaml');
var port = 7072;
server.post('/map-qa_trunk/v2/getData', function(req, res, next) {
var foo = {
err : 123,
msg : "error message"
};
res.json(foo);
});
server.listen(port, function() {
console.log('Map Cache Mock Server is now running at http://localhost:' + port);
});
In the Yaml definition, there is an object defined called MapResponseData, how do I create an instance of this object so that I can populate it as needed and return in the res.json()? Something similar to below:
var response = getMapResponseData(); // don't know what this call should be
response.fieldA = 123;
res.json(response);
I am guessing this should be possible, since Swagger parsed the YAML file and is aware of all definitions that were specified.
Try outputting the request object to console.log to see if you can find reference to the swagger definition. Another option would be to pull the parsed swagger definition from the yaml file (using js-yaml for example) and extracting from there.
However, my best advice is to use swagger-tools instead of swagger-server. The swagger-server package is alpha version and has fewer downloads, revisions, and users than swagger-tools. Benefit of swagger-tools is that it will be actively maintained and there is a larger community that can support you. To convert your project to swagger-tools, use swagger.io > Swagger Editor > Online Editor > Paste yaml in left pane > Generate Server > Node.js
In swagger-tools the entire Swagger Yaml definition is contained in each request object:
req.swagger.swaggerObject
and you can pull the response object definitions from that as needed.

Swagger UI - reading JSON specs from editor into UI without hosting

I'm attempting to document my API using Swagger by writing the documentation in the Swagger editor and then loading it into the Swagger UI. I used the editor and downloaded my JSON file and then changed the /dist/index.html file within the UI to point to my local file using:
var spec = "file:///Users/user1/Desktop/swagger.json";
if (url && url.length > 1) {
url = decodeURIComponent(url[1]);
} else {
url = "http://petstore.swagger.io/v2/swagger.json";
}
// Pre load translate...
if(window.SwaggerTranslator) {
window.SwaggerTranslator.translate();
}
window.swaggerUi = new SwaggerUi({
url: url,
spec: spec,
The only thing I changed within the file is the use of the spec var to point to my JSON file, however when I open the UI, it displays a blank UI page with the message "Finished Loading Resource Information. Rendering Swagger UI..." I would just like to display the documentation I created in the editor in the UI without having to host the specs, is there something I'm missing?
Accordign to the Documentation, spec value must be an JSON Object, so you have to do something like:
window.swaggerUi = new SwaggerUi({
spec: JSON.parse('{ "swagger": "2.0", ...')
where
{ "swagger": "2.0", ...
is the content for your file:///Users/user1/Desktop/swagger.json file

best way to tell swaggerui where the host is

When I build my swagger.json file I do not know which host to use. However I can work it out when my page that hosts swaggerui loads (in fact I might want to offer the user a choice). I hoped to see an options.host on the config for the swaggerUI object - I dont see one. Is there an existing way of doing this that I cant find or do I simply have to hack my way through the code and add this capability (pointers to the best place to do it would be welcome)
Swagger has a built-in json definition for host config, or can accept multiple inputs.
{
"swagger": "2.0",
"info": {
"title": "Why API",
"description": "Don't make that mistake again",
"version": "0.0.1"
},
"host": "127.0.0.1:3000",
"schemes": [
"https"
]
}
Or
"host": "test.mydomain.com:3000",
"schemes": [
"https"
],
Or you can have a dynamic host by defining a var and calling a hostname or machine name or other environment variables.
dynamic example
if (typeof this.host === 'undefined' || this.host === '') {
this.host = location.host;
}
if (location.port) {
this.host = this.host + ':' + location.port;
}
Here is what I do, since the loaded in document is just a JSON object:
var swaggerDoc = require('./api/swagger.json');
if (process.env.NODE_ENV === 'development') {
swaggerDoc.host="localhost:" + process.env.PORT
}
// Initialize the Swagger middleware
swaggerTools.initializeMiddleware(swaggerDoc, function (middleware) {
// Other initialization
}
This way you don't pollute your API specification with development environment configuration.
In recent versions of Swagger UI it's possible to do this, for example in onComplete:
window.swaggerUi.api.setHost("your.host:4242");
If you are hosting it on same app server, just remove the host key from the json and provide relative path in key "basePath". as -
"basePath": "/rest/createcampaign".
two ways
One modify swagger.js so that it accepts host option. swagger-UI passes options to swagger-js so that works. I submitted a pull to swagger-js with this fix
Second choice is that swagger-UI accepts a 'spec' parameter. This means that the hosting page can load the swagger.json file, JSON.parse it , set 'host' in it and then pass to swaggerUi constructor. This is harder for the caller but doesn't require code changes to swagger
There are 2 ways which you can follow:
Load the index.html and replace the https://petstore.swagger.io/v2/swagger.json with the url where your swagger.json is hosting.
you can expose the local swagger.json on the same server.
When you follow this approach make sure you include static files in the end of above steps.
If you don't want to expose swagger.json as an API, copy the sawgger.json in the dist folder of swagger. The index.html and swagger.json must be in same repository for this. It is inside the index.html of dist folder of swagger-ui-dist.
const ui = SwaggerUIBundle({
spec: location.host,
url: "swagger.json",
dom_id: "#swagger-ui",
deepLinking: true,
presets: [SwaggerUIBundle.presets.apis, SwaggerUIStandalonePreset],
plugins: [SwaggerUIBundle.plugins.DownloadUrl],
layout: "StandaloneLayout"
});
// End Swagger UI call region
window.ui = ui;
};
Second way, host parameter in the swagger.yaml/swagger.json either make it empty
"host":""
or omit host parameter.
Swagger take the server's host as host where the swagger ui is hosted.
This is how I did this using the Java client:
DefaultApi api = new DefaultApi();
api.getApiClient().setBasePath("http://localhost:8080");
//call the API
if you use OpenApi 3.0
Variables can have arbitrary values, or may be restricted to an enum. In any case, a default value is required, which will be used if the client does not supply a value.
swagger doc
In the swagger-ui there will be the default value but the field is an input field so it is possible to customize it at runtime.
Swagger UI express itself is giving the following snippet it's getting the current host and publish dynamic with host
app.use('/api-docs', function(req, res, next){
swaggerDocument.host = req.get('host');
req.swaggerDoc = swaggerDocument;
next();
}, swaggerUi.serve, swaggerUi.setup());

Resources