I would like to host my Swagger API documents in AWS S3 as a static website.
There are two layers of API categories:
Versions: I have different versions for all my APIs. Say, version1 and version2.
Groups: I have different groups of APIs for each version. Say, user APIs as a group1 and account APIs as group2. Each group of APIs has its own YAML file.
I would like to be able to:
first select version
and then under the version, I can select group
In this post (Swagger UI with Multiple Urls), I was only able to select the version using an array of URLs for different versions.
window.onload = function() {
// Build a system
const ui = SwaggerUIBundle({
urls: [
{url: "https://path/to/user_api_v1.yaml", name: "V1"},
{url: "https://path/to/user_api_v2.yaml", name: "V2"},
],
"urls.primaryName": "V1" // default document (if other than the first)
...
})
Is there a way that I can select different groups under each version? (Another dropdown list) Does Swagger UI support this?
Related
I'm using the CDK to deploy several stacks, and one of the roles used is shared across multiple stacks. The constructs (e.g. CodeBuildAction) which use the role frequently attach necessary permissions as an inline policy. However, despite knowing that it is an "imported" role, the inline policy name that is generated is not unique across stacks, and therefore both CloudFormation stacks contain the same Policy resource, and fight over the contents. (Neither stack contains the Role resource.)
import * as cdk from "#aws-cdk/core";
import * as iam from "#aws-cdk/aws-iam";
const sharedRoleArn = "arn:aws:iam::1111111111:role/MyLambdaRole";
const app = new cdk.App();
const stackOne = new cdk.Stack(app, "StackOne");
const roleRefOne = iam.Role.fromRoleArn(stackOne, "SharedRole", sharedRoleArn);
// Under normal circumstances, this is called inside constructs defined by AWS
// (like a CodeBuildAction that grants permission to access Artifact S3 buckets, etc)
roleRefOne.addToPrincipalPolicy(new iam.PolicyStatement({
actions: ["s3:ListBucket"],
resources: ["*"],
effect: iam.Effect.ALLOW,
}));
const stackTwo = new cdk.Stack(app, "StackTwo");
const roleRefTwo = iam.Role.fromRoleArn(stackTwo, "SharedRole", sharedRoleArn);
roleRefTwo.addToPrincipalPolicy(new iam.PolicyStatement({
actions: ["dynamodb:List*"],
resources: ["*"],
effect: iam.Effect.ALLOW,
}));
The following are fragments of the cloud assembly generated for the two stacks:
SharedRolePolicyA1DDBB1E:
Type: AWS::IAM::Policy
Properties:
PolicyDocument:
Statement:
- Action: s3:ListBucket
Effect: Allow
Resource: "*"
Version: "2012-10-17"
PolicyName: SharedRolePolicyA1DDBB1E
Roles:
- MyLambdaRole
Metadata:
aws:cdk:path: StackOne/SharedRole/Policy/Resource
SharedRolePolicyA1DDBB1E:
Type: AWS::IAM::Policy
Properties:
PolicyDocument:
Statement:
- Action: dynamodb:List*
Effect: Allow
Resource: "*"
Version: "2012-10-17"
PolicyName: SharedRolePolicyA1DDBB1E
Roles:
- MyLambdaRole
Metadata:
aws:cdk:path: StackTwo/SharedRole/Policy/Resource
You can see above that the aws:cdk:paths for two policies are different, but they end up with the same name (SharedRolePolicyA1DDBB1E). That is used as the physical name of the inline policy attached to the MySharedRole role. (The same behavior occurs for stacks in separate "Apps" as well.)
There's no affordance for setting the PolicyName for the "default policy" generated for a role (or which policies a construct attaches permissions to). I could also make the shared role immutable (using { mutable: false } on fromRoleArn, but then I need to reconstruct the potentially complicated Policies a set of constructs would have given the role, and attache it myself.
I was able to work around the issue by templating the stack name into the imported role's "id", as in:
const stack = cdk.Stack.of(scope)
const role = iam.Role.fromRoleArn(scope, `${stack.stackName}SharedRole`, sharedRoleArn);
where I construct my role.
Is this expected behavior? Do I misunderstand something about imported resources with CDK? Is there a better alternative? (My understanding with the construct ids is that they are only intended to need to be unique within a given scope.)
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
I am versioning my API and I would like to display the newest API version in Swagger as the default. For example, my API has 2 versions, when someone chooses to display the Swagger, the version that appears first is the V1.0. The user has to manually choose the newest version to display.
In the image below we can see that the default version that appears to the user when the application starts is the V1.0.
I would like to know if it is possible to display the newest API version to the user by default.
Thanks!
First I added the IApiVersionDescriptionProvider in the Configure class in Startup.cs as shown below:
After that, I had to reverse the list that contained the versions available for the api in the app.UseSwaggerUI().
The order in which you configure Swagger UI in Startup.cs Configure method determines the dropdown list order.
app.UseSwaggerUI(c =>
{
foreach (var description in apiVersionDescriptionProvider.ApiVersionDescriptions.Reverse())
{
// Create the Swagger endpoints for each version
c.SwaggerEndpoint($"/swagger/" +
$"LibraryOpenAPISpecification{description.GroupName}/swagger.json",
description.GroupName.ToUpperInvariant());
}
c.RoutePrefix = ""; // swagger UI at the root index.html
});
The following answer by #Bob Ash was very helpful - How can i specify the default opening version of swagger?
By doing so, I successfully have now the V2.0 displayed as the default version for the api:
The solution for me was to add an OrderByDescending clause into the following block of code:
// build a swagger document and endpoint for each discovered API version
c.MultipleApiVersions(
(apiDescription, version) => apiDescription.GetGroupName() == version,
info =>
{
foreach (var group in apiExplorer.ApiDescriptions.OrderByDescending(p => p.ApiVersion))
{
var description = "My Company API";
info.Version(group.Name, $"My Company API {group.ApiVersion}")
.Contact(ca => ca.Name("My Company).Email("info#mycompany.com"))
.Description(description)
.License(l => l.Name("My Company").Url("https://mycompany.com"))
.TermsOfService("");
}
});
On my case, I also use that iteration to apply some UI specifics, according to my needs.
I've seen both in samples I've found and haven't seen how they are different. Is the bundle needed if you are using this in an HTML page only (not using a single-page-app) or is that the one to use if you are using a single-page-app?
The Swagger UI docs discuss two ways to deploy swagger-ui.
traditional npm - swagger-ui
dependency-free module - swagger-ui-dist
I've seen examples like this one where SwaggerUIBundle is used on what appears to be a web page hosted in tomcat (python, or some other web server) example.
<script src="./swagger-ui-bundle.js"> </script>
// later
<script>
window.onload = function() {
// Build a system
const ui = SwaggerUIBundle({
url: "https://petstore.swagger.io/v2/swagger.json",
But also seen examples like this one that use SwaggerUi.
window.swaggerUi = new SwaggerUi({
url: "http://petstore.swagger.wordnik.com/api/api-docs",
dom_id: "swagger-ui-container",
A search returns things like:
swagger-ui-bundle.js - https://github.com/swagger-api/swagger-ui/issues/3978
SwaggerUi - https://stackoverflow.com/a/29497301/3281336
SwaggerUIBundle - https://github.com/swagger-api/swagger-ui/wiki/FAQ
This page Installation Distribution Channels NPM Registry says:
SwaggerUIBundle is equivalent to SwaggerUI.
But then explains the differences. So they are functionally equivalent but the one you choose will depend on how your webserver/website is serving up the swagger user interface page.
The first example with const ui = SwaggerUIBundle(... is for Swagger UI 3.x, which is the current version of Swagger UI. The second example with window.swaggerUi = new SwaggerUi(... is for the old Swagger UI 2.x. Credit #Helen for this info in this answer)
For more details read on...
SwaggerUI Explained
SwaggerUI is used in apps that can import npm modules. This includes React, Angular or other single-page-apps (SPAs) that include the webpack-like tooling to package the resources for delivery to the browser.
The webpage says this:
import SwaggerUI from 'swagger-ui'
swagger-ui is meant for consumption by JavaScript web projects that include module bundlers, such as Webpack, Browserify, and Rollup.
Here's an example of using the npm intalled module swagger-ui.
import SwaggerUI from 'swagger-ui'
// or use require, if you prefer
const SwaggerUI = require('swagger-ui')
SwaggerUI({
dom_id: '#myDomId'
})
SwaggerUIBundle Explained
SwaggerUIBundle is used when your app does not support importing npm modules (e.g., a java webapp).
The swagger user interface can be loaded by using the swagger index.html page (included in the swagger-ui-bundle) or by your own personal html page that includes the bundle file and uses the Javascript shown below:
The following comes from the website and is edited to highlight my above statements:
The [...] dist folder [has] swagger-ui-bundle.js, which is a build of Swagger-UI that includes all the code it needs to run in one file. The folder also has an index.html asset, to make it easy to serve Swagger-UI...
An example of how to use the SwaggerUIBundle is:
var SwaggerUIBundle = require('swagger-ui-dist').SwaggerUIBundle
const ui = SwaggerUIBundle({
url: "https://petstore.swagger.io/v2/swagger.json",
dom_id: '#swagger-ui',
presets: [
SwaggerUIBundle.presets.apis,
SwaggerUIBundle.SwaggerUIStandalonePreset
],
layout: "StandaloneLayout"
})
The SwaggerUIBundle example is confusing
It is confusing because it says:
if you're in a JavaScript project that can't handle a traditional npm module, you could do something like this:
var SwaggerUIBundle = require('swagger-ui-dist').SwaggerUIBundle
which uses require() which is an npm module way of including the bundle.
A less confusing way to explain this would be to say:
If you are using Swagger in a non-module environment then you need to somehow get the swagger bundle javascript loaded into the browser page and then use the SwaggerUIBundle as shown below to make the swagger user interface render at the dom_id specified (in the example below it is swagger-ui).
const ui = SwaggerUIBundle({
url: "https://petstore.swagger.io/v2/swagger.json",
dom_id: '#swagger-ui',
presets: [
SwaggerUIBundle.presets.apis,
SwaggerUIBundle.SwaggerUIStandalonePreset
],
layout: "StandaloneLayout"
})
The way you load the swagger-ui-bundle onto your page will depend on the technologies you are using. If you want you can load the page using a <script src="bundle.js"></script>. See https://github.com/swagger-api/swagger-ui/blob/master/dist/index.html (which is in swagger-ui/dist/index.html).
If you are in a NodeJS express application you could load the swagger bundle onto the page using:
var SwaggerUIBundle = require('swagger-ui-dist').SwaggerUIBundle
How you get the swagger bundle javscript onto the page is up to you.
The first example with const ui = SwaggerUIBundle(... is for Swagger UI 3.x, which is the current version of Swagger UI.
The second example with window.swaggerUi = new SwaggerUi(... is for the old Swagger UI 2.x.
See here for the differences between 3.x and 2.x.
Good afternoon my dear rails developers.Well i am Clement, a ruby on rails beginer and i just started working on my first project which is creating an online business platform.My problem was about how to add a stock chart to my app but fortunately for me i discovered the quandl gem which i heard was very good to work with .But my only problem now is how to get the gem working in the app by creating view, controller and configuring it to render the stock charts can any one help me with the codes for the procedures and walk me through the part with a quick tutorials from how to configure the gem to how to get the feeds rendered in your view. Your help will be appreciated..Below is the github repository for the
Quandl Ruby Client Build Status
The official ruby gem for all your data needs! The Quandl client can be used to interact with the latest version of the Quandl RESTful API.
Deprecation of old package
With the release of our v3 API we are officially deprecating version 2 of the quandl_client ruby gem. We have re-written the package from the ground up and will be moving forward with a 1.x.x package with the name of quandl that will rely on version 3 of our restful api. During this transitional period you can continue to use the old package here:
https://rubygems.org/gems/quandl_client
Installation
gem 'quandl'
Configuration
Option Explanation Example
api_key Your access key tEsTkEy123456789
api_version The version you wish to access the api with 2015-04-09
require 'quandl'
Quandl::ApiConfig.api_key = 'tEsTkEy123456789'
Quandl::ApiConfig.api_version = '2015-04-09'
Retrieving Data
Dataset
Retrieving dataset data can be done in a similar way to Databases. For example to retrieve a dataset use its full code:
require 'quandl'
Quandl::Dataset.get('WIKI/AAPL')
=> ... dataset ...
You can also retrieve a list of datasets associated to a database by using the Database helper method:
Quandl::Database.get('WIKI').datasets
=> ... datasets results ...
By default, each list query will return page 1 of the first 100 results (Please see the API Documentation for more detail)
Data
Dataset data can be queried through a dataset. For example:
require 'quandl'
Quandl::Dataset.get('WIKI/AAPL').data
=> ... data ...
you can access the data much like you would other lists. In addition all the data column fields are mapped to their column_names for convenience:
Quandl::Dataset.get('WIKI/AAPL').data.first.date
=> ... date ...
Database
To retrieve a database simply use its code with the get parameter:
require 'quandl'
Quandl::Database.get('WIKI')
=> ... wiki database ...
You can also retrieve a list of databases by using:
Quandl::Database.all
=> ... results ...
Download Entire Database (Bulk Download)
To get the url for downloading all dataset data of a database:
require 'quandl'
Quandl::ApiConfig.api_key = 'tEsTkEy123456789'
Quandl::Database.get('ZEA').bulk_download_url
=> "https://www.quandl.com/api/v3/databases/ZEA/data?api_key=tEsTkEy123456789"
To bulk download all dataset data of a database:
Quandl::ApiConfig.api_key = 'tEsTkEy123456789'
Quandl::Database.get('ZEA').bulk_download_to_file('/path/to/destination/file_or_folder')
The file or folder path can either be specified as a string or as a File.
For bulk download of premium databases, please ensure that a valid api_key is set, as authentication is required.
For both bulk_download_url and bulk_download_to_file, an optional download_type query parameter can be passed in:
Quandl::Database.get('ZEA').bulk_download_to_file('.', params: {download_type: 'partial'})
If download_type is not specified, a complete bulk download will be performed. Please see the API Documentation for more detail.
Working with results
Instance
All data once retrieved is abstracted into custom classes. You can get a list of the fields in each class by using the data_fields method.
require 'quandl'
database = Quandl::Database.get('WIKI')
database.data_fields
=> ["id", "name", "database_code", "description", "datasets_count", "downloads", "premium", "image"]
You can then uses these methods in your code. Additionally you can access the data by using the hash equalivalent lookup.
database = Quandl::Database.get('WIKI')
database.database_code
=> 'WIKI'
database['database_code']
=> 'WIKI'
In some cases name of the fields returned by the API may not be compatible with the ruby language syntax. These will be converted into compatible field names.
data = Quandl::Dataset.get('WIKI/AAPL').data(params: { limit: 1 }).first
data.column_names
=> ["Date", "Open", "High", "Low", "Close", "Volume", "Ex-Dividend", "Split Ratio", "Adj. Open", "Adj. High", "Adj. Low", "Adj. Close", "Adj. Volume"]
data.data_fields
=> ["date", "open", "high", "low", "close", "volume", "ex_dividend", "split_ratio", "adj_open", "adj_high", "adj_low", "adj_close", "adj_volume"]
List
Most list queries will return a paginated list of results. You can check whether the resulting list has more data by using the more_results? method. By default, each list query will return page 1 of the first 100 results (Please see the API Documentation for more detail). Depending on its results you can pass additional params to filter the data:
require 'quandl'
databases = Quandl::Database.all
=> ... results ...
databases.more_results?
=> true
Quandl::Database.all(params: { page: 2 })
=> ... more results ...
Lists also function as arrays and can be iterated through. Note however that using these features will only work on the current page of data you have locally. You will need to continue to fetch results and iterate again to loop through the full result set.
databases = Quandl::Database.all
databases.each { |d| puts d.database_code }
=> ... print database codes ...
databases.more_results?
=> true
Quandl::Database.all(params: { page: 2 }).each { |d| puts d.database_code }
=> ... print more database codes ...
Lists also return metadata associated with the request. This can include things like the current page, total results, etc. Each of these fields can be accessed through a hash or convenience method.
Quandl::Database.all.current_page
=> 1
Quandl::Database.all['current_page']
=> 1
As a convenience method lists can also return their data in CSV form. To do this simply issue the .to_csv method on a list:
databases = Quandl::Database.all.to_csv
=> "Id,Name,Database Code,Description,Datasets Count,Downloads,Premium,Image,Bundle Ids,Plan ...
Additional Links
Quandl
Quandl Tools
API Docs
License