Today i got into swagger and swagger-ui to create the documentation of our API.
We are using AWS API Gateway with a Lambda function, since AWS is comming with an in-built option for documentation we are going with it.
Sadly, I am pretty limited with this option or I am doing it wrong.
As an example
responses:
'200':
description: 200 response
schema:
$ref: '#/definitions/Empty'
I can´t create an alternative schema, nor im able to edit the existing /Empty schema.
Is there a solution for my problem?
For example
... to not use an schema and just write the whole response in there?
... to show me how to create an alternative schema?
EDIT
For me it seems like an AWS problem, not my swagger file in generall. If someone reads over this i added more informations.
It doesnt matter if i use "create Documetation Part" --> Type = Response (Body) or i go to Ressources --> Method which i want to set the Response (Body) --> Method Response and set the Respone Body to an Modell.
My Modell looks like this
{
{
"$schema": "http://json-schema.org/draft-04/schema#",
"description" : "Example Promotion",
"title" : "Promotion",
"type" : "object",
"properties" : {
"Status" : { "type" : "string"}
}
}
}
It gives me no error, but if i go to "Publish Documentation" it seems to no put the Respone (Body) i set into the swagger.json on the Method Response part, nor on the Defenitions at the end of the file and set the schema path right.
I found it easier to not use $ref when I was starting out. After you have the knack how to write requests or response definitions, you can easily transition to referencing schemas using $ref.
What comes after schema statement? That depends on what you expect to be returned -- text, an array, a JSON object, or an array of JSON objects, etc. Typically it's the later two. So here is an example of each.
schema:
type: object
description: This is a JSON object
properties:
fullName:
type: string
age:
type: number
which defines: { fullName: "Jane Smith", age: 30 }
schema:
type: array
description: This is an array of JSON object
items:
type: object
properties:
carMake:
type: string
carModel:
type: string
which defines: [{ carMake: "Ford", carModel: "Mustang" } ... ]
Clone github's swagger-ui onto your computer and run it as a local server. Or you have free use of the SwaggerHub if you don't mind the API definition to be public (or, after a trial period, pay for your APIs to be private).
The specification has changed over the years, so its important to know whether you are dealing with swagger v2 or openapi v3. www.swagger.io has a good multi-page tutorial. And you can find several public API examples at the SwaggerHub website. I do not work for Smartbear, the originators of both the original swagger spec and swaggerhub tooling, but I've found them to be very helpful in the past. Some of their staff monitor this website and answer questions.
Good luck!
Related
I'm currently using a Contentful webhook to automatically update Algolia when a Contentful entry is published.
My content model on Contentful looks something like this:
MOVIE:
{ title: string,
director: reference }
DIRECTOR:
{ name: string }
I am sending content to Algolia via the Contentful webhook. Currently, the data I'm sending looks like this:
title: "Vertigo",
director: {
sys: {
type: "Link",
linkType: "Entry",
id: 123456789
}
}
Instead, I would like it to be:
title: "Vertigo",
director: {
name: "Alfred Hitchcock"
}
How can I include the full data from the linked entry, rather than just the ID? For the record, I'm using a custom webhook payload, which looks basically like this:
{
"title": "{ /payload/fields/title/en-US }",
"director": "{ /payload/fields/director }"
}
Per the documentation, to follow links, you're going to have to move beyond the out-of-the-box webhook and write your own connection.
Inclusion of referenced item data in webhooks Depending on your use
case you might want to index an entry and all the data that it links
because it it is a composition of different Contentful entities.
Reference entry data is not available in the webhook payload and it’s
recommended to write your own logic to feed Algolia then. The
Contentful client libraries provide a way to retrieve linked data.
Source: https://www.contentful.com/developers/docs/tutorials/general/enhancing-search-experience-with-algolia/
Consider HTML. You write a tag <img src="http://example.com/image.png"/> and the browser retrieves the image at the location specified. I'm designing my API to use a similar mechanism where it's up to the server where any secondary resources and it supplies the location of those resources in the form of a URL.
I'm writing an OpenAPI document to describe all the JSON structures that are sent up to and returned by the server. It works great except I don't know how to express the relationship between the URL inside the response to the first resource to the second resource.
openapi: 3.0.3
info:
title: Minimal Spec for Question.
version: 0.0.0
paths:
/firstRefToSecond:
get:
description: Gets some data including a reference to a secondary resource.
responses:
'200':
description: Successful operation
content:
application/json:
schema:
type: object
properties:
RefToSecond:
type: string
description: The URL to the second resource.
example: "http://example.org/second"
/secondResourceExampleUrlNotActuallyThisUrl:
get:
description:
The second resource.
Found at the URL pointed to by RefToSecond.
responses:
'200':
description: Successful operation
content:
application/json:
schema:
type: object
properties:
Data:
type: integer
description: The data.
example: 12
Here, the second "path" is simply a placeholder for the second URL. I would prefer not to have that placeholder at all and instead substitute the path for wherever that URL points.
Is there a way in OpenAPI to express this relationship between the "refToSecond" URL property and the requirements of what that secondary interaction would look like, without linking it to an explicit URL set in advance?
Is there a way in OpenAPI to express this relationship between the "refToSecond" URL property and the requirements of what that secondary interaction would look like, without linking it to an explicit URL set in advance?
It is possible to formally express a relationship between the response of an operation and another request URL: See the Link feature. The section "Runtime Expression Syntax" is apparently helpful for your case. (Disclaimer: I have never seen this feature being used anywhere in practice so far.)
But this only allows to express the relation to the operation that is available at the server-defined URL. You cannot specify dynamic endpoints in OpenAPI, so you cannot provide a detailed description of the request and response (except in the way you showed in the question).
I have some schema definitions created with fastify as in below, where I have used 'title' to give meaningful name of my models.
fastify.addSchema({
$id: 'persistence-query-params',
title: "PersistenceQueryParams", // Here
type: 'object',
description: 'Persistence Service GET API URL query specification. Applicable for GET API only.',
properties: {
...........
},
});
However when I am looking at the json generated from the swagger (I am using fastify-swagger: 4.8.4 and fastify: 3.20.1), I am seeing this
def-7: ## Here
title: PersistenceQueryParams
type: object
description: >-
Persistence Service GET API URL query specification. Applicable for GET
API only.
properties:
This is coming up in the OpenAPI 2.0 https://editor.swagger.io/, when loading the json generated out of that schema.
I have tried out adding the name field also:
name: "PersistenceQueryParams",
However no luck.
How can I create meaningful names, instead of def-0, def-1 etc in OpenAPI 2.0?
Thanks,
Pradip
I'm designing a new website. Before i start to code, i'm learning a lot about api and nosql database (as i'm used to sql but i want to try with mongoDB).
In mongoDB, i'll have a 'user' document like that :
{
firstname: 'xxxxxxx',
lastname: 'xxxxxxx',
projects: [
{
name: 'project xxxxxxx',
participants: [], // array of friends into this project
operations: [
{ title: 'Title OP xxxxxxx', contributors: [] },
{ title: 'Title OP xxxxxxx', contributors: [] },
{ title: 'Title OP xxxxxxx', contributors: [] }
]
}
]
}
I was wondering two things :
Should projects.participantsand projects.operations.contributors be references to other users ?
For the API, should i do something like :
GET /users/:id_user
GET /users/:id_user/projects/:id_project
GET /users/:id_user/projects/:id_project/operations/:id_operation
(should my API always start with users ?)
If you ever have a better solution I will be glad to know.
Thanks
EDIT 1 : I'll work on NodeJS with Express and i would like to have a REST API.
yes, projects.participants and projects.operations.contributors can be reference to other documents in the same collection. Each of these should refer to valid _id in the same collection.
can you please put some more light on how exactly are you creating your APIs? I mean which framework you are using as a wrapper to access mongoDB? May be then I can try to help more.
ok great!!!
So, users is your collection name. Its absolutely not necessary to start your API name with users. In node.js you can create a router, which will route your request to a particular js file and you can name it anything you want. Example:
use case: You want to expose 3 API
1. To access all the users. (exposed using url - /getallusers)
2. To access all the participants of the project.(exposed using url - /getparticipantsbyproject)
3. To access all the contributors in the operations.(exposed using url - /getcontributorsbyproject).
You can write all these APIs in your file called myapi and expose them.
Now, you can very well call these APIs from browser using below urls:
http://host:port/myapi/getallusers
http://host:port/myapi/getparticipantsbyproject
http://host:port/myapi/getcontributorsbyproject
Its about RESTful API only. I mentioned 3 urls above which are nothing but RESTful API exposing different functionalities.
I was wondering if there were any features hidden in Angular or exposed by some 3rd-party libraries to easily create HATEOAS-compliant Restful clients.
On backend side, I am using Spring Data/REST to produce an HATEOAS JSON API.
Consuming it, though, is quite another story.
For instance, I've got those 3 entities:
Company {name, address}
Employee {firstName, lastName, employer[Company]}
Activity {rate, day, employee[Employee], client[Company]}
and requesting an activity (the most complex entity of the model) produces something like this:
{
links: [],
content: [{
rate: 456,
day: 1366754400000,
links: [{
rel: "self",
href: "http://localhost:8080/api/activities/1"
},
{
rel: "activities.activity.client",
href: "http://localhost:8080/api/activities/1/client"
},
{
rel: "activities.activity.employee",
href: "http://localhost:8080/api/activities/1/employee"
}]
}]
}
My API talks in terms of REST (resources identified by links).
An Activity has an Employee for instance. What I really want to use is : {rate: 456, day: 1366754400000, employee: {firstName:"xxx", lastName:"xxx" ...}}.
However, as you can see in the first output, my Activity only contains a link to the employee, not its data. Is there anything in Angular or in a 3rd-party library to resolve those links and embed the resulting data instead?
Any input on this?
Thanks in advance!
Checkout angular-hateoas. ITs an AngularJS module for using $resource with a HATEOAS-enabled REST API.
You could write a Response Transformation that would inspect your returned object, check for links, and resolve them before returning the response. See the section "Transforming Requests and Responses" in the $http service documentation.
Something like this:
transformResponse: function(rawData) {
var json = JSON.parse( rawData );
forEach( json.content.links, function(link) {
// resolve link...
});
return json;
}
Since the "resolve link" step is itself an $http call, sub-references would also be resolved. HOWEVER, since these are asynchronous, you would likely return a promise instead of the real value; I don't know if the transform function is allowed to do this.
As #charlietfl pointed out, however, please note that this will result in several HTTP calls to return a single entity. Even though I like the concept of HATEOAS, this will likely result in sluggishness if too many calls are made. I'd suggest that your server return the data, or some of it, directly, PLUS the link for details.
Based on your comment about wanting to work with data as against links on the client, I think Restangular would be a good fit.
I've been using angular-hal for one of my projects. It was a Spring HATEOAS backend. And I didn't run into any issues. It handles parametrized resources. I suspect it only supports HAL so since you're using Spring Data Rest you probably have to configure it to generate HAL compliant responses.
I think the confusion may be that you are asking for an Angular solution, when what you really want to do is have Spring Data send a more complete JSON response. I.e, you really just want the server to return the employee data as part of the response JSON, rather than having the client perform extra steps to look it up. I don't know what data store you are using in Spring Data, but the general solution would be to add public getEmployee() method to your Activity class and then annotate the method with #RelatedTo and #Fetch (this would be the setup for Neo4J -- may be different annotations for your flavor of Spring Data). This should cause Spring HATEOAS to include the Employee record within the response for /activity. Hope this helps.