Describe generic dynamic behaviour using openAPI - openapi

Let's say I have an API that creates me a resource say /create/my-resource/<resource-id>. I want the consumers of the api to know that the response will always have an id field matching the one passed in the url, namely: <resource-id>.
I know I can use api examples to demonstrate this for a given id, say 2. But is there a way of describing that generically, purely using open-api? The idea is to use the said behaviour when mocking.

OpenAPI does not have syntax for that. You can only document such behavior in the description or using custom x- extensions.
Feel free to propose an enhancement for OpenAPI syntax here:
https://github.com/OAI/OpenAPI-Specification/issues

Related

RESTful API endpoint for custom response data

I am building a RESTful API where I have a resource named solar_systems. solar_sytems has id(int), system_size(int), system_cost(int) columns with many other columns.
I understand that API endpoints will be-
/v1/solar-systems - for all systems
/v1/solar-systems/{id} - for a single system
And I have to pass query params for filter, search, sorting etc.
But what will be the best practice for API endpoints if I need some kind of custom data like if I need average system_cost for each system_size.
Will it be silly, if I use - /v1/solar-systems/average-system-cost?
Please I need your opinion from your experience.
It is not silly at all to use /v1/solar-systems/average-system-cost
It is easy to get caught up in the fact that technically the average-system-cost is not a resource. But it is a piece of data that is useful to retrieve. Ultimately the goal of REST is to make APIs that are understandable and readable. A specific endpoint that gets a useful piece of data definitely falls inside that.
Will it be silly, if I use /v1/solar-systems/average-system-cost?
The REST architecture doesn't enforce any URI design (see notes below). It's totally up to you to pick the URIs that better identify your resources.
However I would probably use query parameters to select the fields to be returned in the response. Something like /v1/solar-systems?fields=average-system-cost.
Note 1: The REST architectural style, described in the chapter 5 of Roy T. Fielding's dissertation, defines a set of constraints that must be followed by the applications that follow such architecture. However it says nothing about what the URLs must be like.
Note 2: On the other hand, the examples of a popular article written by Martin Fowler explaining a model defined by Leonard Richardson suggest a URL structure that looks friendly and easy to read.

REST url proper format

my REST API format:
http://example.com/api/v1.0/products - get all products
http://example.com/api/v1.0/products/3 - get product with id=3
Also, the products can be orginized into a product groups.
What is a proper way to get all product groups according to REST best practices:
http://example.com/api/v1.0/products/groups
or
http://example.com/api/v1.0/productgroups
...
another option ?
I can't agree with Rishabh Soni because http://example.com/api/v1.0/products/groups may lead to ambiguity.
I would put my money on http://example.com/api/v1.0/productgroups or even better http://example.com/api/v1.0/product_groups (better readability).
I've had similar discussion here: Updating RESTful resources against aggregate roots only
Question: About the thing of /products/features or /product-features,
is there any consensus on this? Do you know any good source to ensure
that it's not just a matter of taste?
Answer: I think this is misleading. I would expect to get all features
in all products rather than get all possible features. But, to be
honest, it’s hard to find any source talking directly about this
problem, but there is a bunch of articles where people don’t try to
create nested resources like /products/features, but do this
separately.
So, we can't be sure http://example.com/api/v1.0/products/groups will return all possible groups or just all groups that are connected with all existing products (what about a group that has not been connected with the product yet?).
To avoid this ambiguity, you can add some annotation in documentation. But you can just prepare http://example.com/api/v1.0/product_groups and all is clear.
If you are developing Rest API for your clients than you should not rely on id's. Instead build a meaningful abbreviation and map them to actual id on server side.
If that is not possible, instead of using
http://example.com/api/v1.0/products/3 you can use http://example.com/api/v1.0/products?product_id=3 and then you can provide "product_id" description in the documentation. basically telling the client ways to use product_id.
In short a url must be meaningful and follow a pattern.The variable part must be send by in the url query(part after ? or POST payload)
With this, method to querying the server is also important. If client is trying to get something to the server he should use "GET" http request, similar POST http request if it is uploading new info and "PUT" request if it is updating or creating a new resource.
So by this analogy http://example.com/api/v1.0/products/groups is more appropriate as it is following a pattern(groups in product) while productgroups is more like a keyword with no pattern.
A directory like pattern is more easier to understand. Like in file systems(C:\Program Files\WinRAR), every part gets us to more generalized target.
You can also customize this for specific group- http://example.com/api/v1.0/products/groups?id=3

What should a link extension relation type URI point to in a RESTful API?

I've been designing an API recently that needs to be RESTful, and have managed to define a system that uses exclusively HTTP headers and query string parameters to define meta data so that the body of responses is free to just be actual resource data only.
However I'm now thinking about links for HATEOAS, and due to wanting to keep everything in HTTP headers or query string parameters I've decided on using the HTTP Link header field.
This has brought up a question about the rel attribute that I'm having trouble finding a direct answer for.
My idea is that for collections of resources one of the Links that will be sent in a response will be something like: Link: <https://api.domain.com/things/{id}>; rel="..."
This would allow a client to use simple string expansion, as defined in RFC6570, to create a correct resource URI for each resource in a collection without me having to embed meta data into each resource and without the client needing to know anything other than the URI template and the resource ID.
However, I'm not sure what the rel should be here, or what it should point to.
In RFC5988, it says that an extension relation type must be a URI and:
Although the URI can point to a
resource that contains a definition of the semantics of the relation
type, clients SHOULD NOT automatically access that resource to avoid
overburdening its server.
My question is, what should the definition look like in a RESTful API?
By the looks of it I could just make the rel something like https://api.domain.com/media/thing, or something like that.
But then what should the actual definition content be?
It looks like it could technically be anything, for example a plain text document with a short explanation.
Is there any RESTful standard for these kinds of rel attributes and what they should point to?
Any help is appreciated.
Looking at Richardson's Maturity Model level 3, rel seems to be representing the name of the published link/relationship. In your case that might translate to curie:thing-by-id (provided you're using curies as suggested in the proposed HAL draft), for example. The idea is that the client could search a link by its name (rel), without peering into the actual url.
Is there any RESTful standard for these kinds of rel attributes and what they should point to?
I don't know of an authoritative answer, but it is probably worth noticing that link relations that are registered with IANA reference the standards document that describes the link.
For example, in the registry, the "item" and "collection" relations both reference RFC 6573. Which, you will notice, is pretty darn close to a "a plain text document with a short explanation."
If the media type of your documentation supports anchors, then you could use a link directly to the secondary resource as your link relation
Link: <https://api.domain.com/things/2>; rel="https://api.domain.com/link-relations#foo"

RESTfully Fetching by Attribute

Which of the following URLs is more RESTful compliant when it comes to fetch only items that have a certain value for attribute?
GET: /items/attribute/{value}
GET: /items/findByAttribute?attribute={value}
GET: /items?attribute={value}
Having in mind that GET: /items returns all items.
Example
GET: /shirts/color/FF9900
GET: /shirts/findByColor?color=FF9900
GET: /shirts?color=FF9900
I think that the last option is the correct one ;-)
Here are some comments for the others:
Generally the path element right after the one that corresponds to the list resource is the identifier of the element. So if you use something at this level, it could be considered as an identifier...
You can have resource to manage a particular field but the URL would be something like /items/{itemid}/fieldname.
You shouldn't use "action names" within the URL (in your example findByAttribute). The HTTP method should correspond to the "action" itself. See this answer if you want to support several actions for an HTTP method: How to Update a REST Resource Collection.
There is a question about how to design search filter: How to desing RESTful advanced search/filter. I think that your use case if a bit simple and using query parameters matches for you.
Otherwise I wrote a post about the way to design a Web API. This could be useful for you. See this link: https://templth.wordpress.com/2014/12/15/designing-a-web-api/.
Hope it helps you,
Thierry
Most certainly this one
GET: /items?attribute={value}
Why?
GET: /items/attribute/{value} is wrong because with REST, url segments represent resources, attribute is not a resource
GET: /items/findByAttribute?attribute={value} is wrong for the same reason really. findByAttribute is not a resource
Using url queries to filter by attributes is perfectly fine, so go with that.
URI semantics are irrelevant to REST. It doesn't make sense to ask which URI is more RESTful. What makes an URI RESTful or not is how the client obtains it. If he's reading URI patterns in documentation and filling placeholders with values, it's not RESTful. If this is news for you, I recommend reading this.
With that in mind, all three examples can be RESTful if the server provided that URI template to the client as a link to query the collection resource filtering by that value, but 3 is definitely the best option since it follows a more conventional query syntax. I wouldn't use 2 since it implies a method call and it looks too RPC for my taste, and I wouldn't use 1 since it implies for a human that it will return only the attribute as a resource.

Boolean logic in RESTful filtering and queries

This is sort of a follow-up to someone else's question about filtering/querying a list of cars. There the recommendation for a RESTful filtering request was to put filter expressions in the query of the URI, like this:
/cars?color=blue&type=sedan&doors=4
That's fine. But what if my filtering query becomes more complicated and I need to use Boolean operators, such as:
((color=blue OR type=sedan) AND doors=4) OR color=red
That is, I want to find a four-door blue car or a four-door sedan, but if the car is red I'll take it without caring about any of the other properties.
Is there any sort of convention for providing Boolean expressions in a RESTful URI's query parameters? I suppose I could by create some new querying expression language and put it in a POST, but that seems like a heavy and proprietary approach. How are others solving this?
It is perfectly okay to use
/cars/color:blue/type:sedan/doors:4
instead of
/cars?color=blue&type=sedan&doors=4
The URL standard says only that the path should contain the hierarchical part, and the query should contain the non-hierarchical. Since this is a map-reduce, using / is perfectly valid.
In your case you need a query language to describe your filters. If I were you I would copy an already existing solution, for example the query language of a noSQL database which has a REST API.
I think resource query language is what you need. I think you could use it like this:
/sthg?q="(foo=3|foo=bar)&price=lt=10"
or forget the default queryString parser, and like this:
/sthg?(foo=3|foo=bar)&price=lt=10
I suggest you to read the manual for further details.
Since I found no other URL compatible query language (yet), I think the only other option to serialize another query language and send it in a param, like SparSQL
http://localhost:8003/v1/graphs/sparql?query=your-urlencoded-query
by marklogic7. Hydra defines a freeTextQuery in its vocab, so they follow the same approach. But I'll ask Markus about this. It's a complicated topic, since according to the self-descriptive messages constraint you should describe somewhere what type of query language you use in the URL. I am not sure about this. :S
conclusion:
In order to support ad-hoc search queries we need a standard way to describe them in the link meta-data. Currently there are only a few standards about this. The most widely used standard is URI templates which does not support nested statements, operators, etc... for what I know. There is a draft called link descriptions which tries to fill the gap, but it is incomplete.
One possible workaround to define an URI template with a single q parameter which has rdf:type of x:SearchQuery and rdfs:range of xsd:string, and create another vocab about how to describe such a x:SearchQuery. After that the description could be used to build search forms, and validate queries sent to the server. Already existing queries could be supported too with this approach, so we don't need a new one.
So this problem can be solved with vocabs or new URI template standards.
I have seen many use a query string as you have provided - much like a SQL query string.
Here are just two examples:
Socrata (Open Data Portal company)'s SoQL (SQL variant): http://dev.socrata.com/consumers/cookbooks/querying-block-ranges.html
openFDA (API from fda.gov for open data) uses a similar string-based query parameter which maps to ElasticSearch queries, I believe: https://open.fda.gov/api/reference/#query-syntax
Try using 1 for true, 0 for false.
/_api/web/lists/getbytitle('XYZ')/items?$filter=Active eq 1