RESTful model for get-or-create route - rest

What's the most RESTful way to model an API which acts mostly as a GET, except that if the resource doesn't exist it creates it before returning it?
I can imagine using GET, although GET isn't supposed to change server state. I can also imagine using PUT, but in this case the resource should be immutable and PUT implies that the resource should be updated if it already exists. It can certainly be POST, but I feel like POST is the overused hammer to all impedance mismatch nails between API modeling and RESTful modeling.
Or should it be split into two separate routes outright? But that seems unnecessarily inefficient.
What's the consensus?

Typically, it is implemented as follows:
GET:Reads resource
POST:Creates resource
PUT:Updates resource
DELETE:Deletes resource
The common issue seems to be that get is limited on query string args. If you run against this limit, you may want to consider using custom headers. In either case, I would recommend that you follow the verb translations above.
Also, you don't mention the language. There is probably a framework that you can leverage that would abstract a lot of this from you.

Related

Sub-resource creation url

Lets assume we have some main-resource and a related sub-resource with 1-n relation;
User of the API can:
list main-resources so GET /main-resources endpoint.
list sub-resources so GET /sub-resources endpoint.
list sub-resources of a main-resource so one or both of;
GET /main-resources/{main-id}/sub-resources
GET /sub-resouces?main={main-id}
create a sub-resource under a main-resource
POST /main-resource/{main-id}/sub-resouces: Which has the benefit of hierarchy, but in order to support this one needs to provide another set of endpoints(list, create, update, delete).
POST /sub-resouces?main={main-id}: Which has the benefit of having embedded id inside URL. A middleware can handle and inject provided values into request itself.
create a sub-resource with all parameters in body POST /sub-resources
Is providing a URI with main={main-id} query parameter embedded a good way to solve this or should I go with the route of hierarchical URI?
In a true REST environment the spelling of URIs is not of importance as long as the characters used in the URI adhere to the URI specification. While RFC 3986 states that
The path component contains data, usually organized in hierarchical form, that, along with data in the non-hierarchical query component (Section 3.4), serves to identify a resource within the scope of the URI's scheme and naming authority (if any). The path is terminated by the first question mark ("?") and number sign ("#") character, or by the end of the URI. (Source)
it does not state that a URI has to have a hierarchical structure assigned to it. A URI as a whole is a pointer to a resource and as such a combination of various URIs may give the impression of some hierarchy involved. The actual information of whether URIs have some hierarchical structure to it should though stem from link relations that are attached to URIs. These can be registered names like up, fist, last, next, prev and the like or Web linking extensions such as https://acme.org/rel/parent which acts more like a predicate in a Semantic Web relation basically stating that the URI at hand is a parent to the current resource. Don't confuse rel-URIs for real URIs though. Such rel-URIs do not necessarily need to point to an actual resource or even to a documentation. Such link relation extensions though my be defined by media-types or certain profiles.
In a perfect world the URI though is only used to send the request to the actual server. A client won't parse or try to extract some knowledge off an URI as it will use accompanying link relation names to determine whether the URI is of relevance to the task at hand or not. REST is full of such "indirection" mechanism in order to help decoupling clients from servers.
I.e. what is the difference between a URI like https://acme.org/api/users/1 and https://acme.org/api/3f067d90-8b55-4b60-befc-1ce124b4e080? Developers in the first case might be tempted to create a user object representing the data returned by the URI invoked. Over time the response format might break as stuff is renamed, removed and replaced by other stuff. This is what Fielding called typed resources which REST shouldn't have.
The second URI doesn't give you a clue on what content it returns, and you might start questioning on what benefit it brings then. While you might not be aware of what actual content the service returns for such URIs, you know at least that your client is able to process the data somehow as otherwise the service would have responded with a 406 Not Acceptable response. So, content-type negotiation ensures that your client will with high certainty receive data it is able to process. Maintaining interoperability in a domain that is likely to change over time is one of RESTs strong benefits and selling points. Depending on the capabilities of your client and the service, you might receive a tailored response-format, which is only applicable to that particular service, or receive a more general-purpose one, like HTML i.e.. Your client basically needs a mapping to translate the received representation format into something your application then can use. As mentioned, REST is probably all about introducing indirections for the purpose of decoupling clients from servers. The benefit for going this indirection however is that once you have it working it will work with responses issued not only from that server but for any other service that also supports returning that media type format. And just think a minute what options your client has when it supports a couple of general-purpose formats. It then can basically communicate and interoperate with various other services in that ecosystem without a need for you touching it. This is how browsers operate on the Web for decades now.
This is exactly why I think that this phrase of Fielding is probably one of the most important ones but also the one that is ignored and or misinterpreted by most in the domain of REST:
A REST API should spend almost all of its descriptive effort in defining the media type(s) used for representing resources and driving application state, or in defining extended relation names and/or hypertext-enabled mark-up for existing standard media types. (Source)
So, in a true REST environment the form of the URI is unimportant as clients rely on other mechanisms to determine whether to use that URI or not. Even for so called "REST APIs" that do not really care about the true meaning of REST and treat it more like old-school RPC the question at hands is probably very opinionated and there probably isn't that one fits all solution. If your framework supports injecting stuff based on the presence of certain query parameters, use that. If you prefer the more hierarchical structure of URIs, go for those. There isn't a right or wrong in such cases.
According to the URI standard when you have a hierarchical relationship between resources, then better to add it to the path instead of the query. https://datatracker.ietf.org/doc/html/rfc3986#page-22 Sometimes it is better to describe the relation itself, not just the sub-resource, but that happens only if the sub-resource can belong to multiple main resources, which is n:m relationship.

What is the RESTful way to design URL that returns parent of a child resource?

I am modeling blogging REST API which has resources Blog, Post and Comment with following URLs:
/api/blogs
/api/blogs/{blogId}
/api/blogs/{blogId}/posts
and I create separate endpoint for all Posts in and their Comment`s:
/api/posts
/api/posts/{postId}
/api/posts/{postId}/comments
Given that I have postId, what is the RESTful way to get Blog for a specific Post? I have three ideas:
1. /api/posts/{postId}/blog
2. /api/blogs/parent-of-post/{postId}
3. /api/blogs?postId={postId}
To me the 1. URL looks more "prettier" but the 2. option looks more "logical" since that endpoint (eg. /api/blogs/*) is generally for blogs resources.
The third option uses query string as parameter but the issue I have with it is that this endpoint would return different type of body depending on the parameter. Eg. without parameter /api/blogs returns a collection of Blog resources, while with parameter postId it would return just single instance of Blog. I am not sure if this is good thing to do (especially because I am using ASP.NET Core and C# which has strongly typed return objects, so implementation might be awkward).
what is the RESTful way to get Blog for a specific Post?
Real answer: anything you want.
REST doesn't care what spelling conventions you use for your resource identifiers. As long as your identifiers conform to the production rules described by RFC 3986, you are good to go.
/api/blogs?postId={postId}
This is a perfectly normal choice, and turns out to be a really convenient one when you want to use general purpose web browsers, because HTML forms already have standards that make it easy to create URI with this shape.
Your other two choices are fine; they lose a point for not being HTML form friendly, but it's still easy enough to describe these identifiers using a URI template.
The third option uses query string as parameter but the issue I have with it is that this endpoint would return different type of body depending on the parameter
General purpose API consumers do NOT assume that two resources are alike just because the spellings of their identifiers overlap each other.
Which is to say, from the outside, there is no implied relationship between
/api/blogs
/api/blogs/1
/api/blogs?postId=2
so the fact that they return different bodies really isn't going to be a surprise to a general purpose consumer.
Now, your routing framework may not support returning different types from the handlers for these resources (or, more likely, may not have any "nice" way to do the routing automatically), but that's an implementation detail deliberately hidden behind the REST API facade.
Similarly, the human beings that read your access log might prefer one spelling to another, to reduce their own cognitive load.

REST API on files

I'm trying to get an understanding of REST
You have a web server which allows operations on files, you can copy, print, merge, translate, delete, etc files (so, basically a whole bunch of verbs on the noun)
How does this translate into REST?
Can all/most RPC type interfaces be mapped to REST?
As long as you think of your data as a collection of resources that can be manipulated with GET, DELETE, POST, PUT, then yes.
It might require you to add more 'nouns' though.
You could treat some of these operations as their own resource.
For example, a POST to /myfile/copy would return a Location header with the URL of the new copy: /myfile(2) or something like that.
A process like printing could look like this:
POST the print config to /myfile/prints which would create a print job resource:
/myfile/prints/12345
a GET on /myfile/prints/12345 would give you the status of the print job.
a DELETE on /myfile/prints/12345 would stop the print job
The basic gist of REST is to provide a guideline for interacting with resources in a common way, in order to make discovery and interaction easier for callers. This is done by mapping logical API concepts to HTTP concepts.
At its heart, REST is all about resources. So, what's a resource? In a nutshell, it is a thing - a noun. Each resource should be represented by a unique URI, and each URI should represent one unique resource. This will typically follow the pattern of root/collection/item where that may sometimes repeat. For example: api.halo.com/players/SomeGuy/matches/1234. In the example, the noun, is a match that was played by a specific player. To reference it, we start at the root (api.halo.com) and go through the collection of players to reach the player named SomeGuy and then through the collection of matches that he/she played to get to the specific match (1234) that we're interested in.
Now that we have a resource, we want to do some things with that resource, such as look at it, replace the entire thing with a new one, update some properties of it, or maybe create a new resource. REST makes use of HTTP verbs to express the operation that you'd like to perform. For example, GET is used to indicate "hey, please give me this thing", POST indicates "hey, please create me a new thing", PUT indicates "please take my new thing and replace the thing you have with it", PATCH indicates "please update some of the properties of the thing with my new data", and DELETE indicates "please remove this thing.
In general, interfaces that deal with a single "thing" or a collection of a single type of "thing" are the ones that map most cleanly to RESTful design. That said, if you're creative enough, you can usually find a RESTful way to model just about all of the concepts that you'd be making RPC calls for, though tuning your API patterns to concentrate on resources and data will help a lot there.
One final call-out that I should make is that you're likely to find that there are many, many strong opinions on REST in the community. There are those that are very pedantic, black-and-white, about what qualifies as RESTful and what doesn't - and different schools of thought on what that is. There are just as many individuals that are apt to relax some of the concepts when needed but still consider their design RESTful.
My very general advice would be to concentrate on who the consumers of your API are and design something that helps them fall into the pit of success - doing the obvious thing and following well-established guidelines where possible, but making things as obvious and easy for them as you can when it doesn't line up so clean.
Here's a couple of things that may offer more introductory context:
Info Q: REST Introduction
H9: Introduction to REST
Pearson eCollege: What is REST?

REST design: resource verbs or related collections?

One approach says that you should keep your resource URL simple. We have verb in HTTP and resource name as path. So we can have:
GET /books/12
And if we want to fetch related collection, we might do:
GET /books/12/pages
On the other hand, there is a practice to use so-called resource verbs where you can fine-tune the verbs operation:
POST /books/12/bookmark
I would not use both approaches for my API. I tend to think that first approach is more correct (i.e. no verbs in resource name allowed), and to model the second approach we might use different entity, like:
POST /book-bookmarks/12/
or different id:
POST /bookmarks/12+book/
I know there is no true answer on this, but which one would be preferred? I would like to see some answers from people that actually went through design decisions like this one.
URI (or IRI) is a standard about indentifying resources. These resources can be web documents, real things, etc... In the current case they are web documents. Afaik. there is not standard about the URI structures, but URI standard along with HTTP standard suggest that you should use URIs and HTTP methods in a procedural way. So the HTTP verbs describe the procedure and the URIs identify the object of the procedure. Now you typically describe procedures with verbs and you typically describe objects with nouns. That's why it is logical to use only nouns in the URI structure, at least in the (hierarchical) path part of it.
(You usually can solve everything with the standard HTTP methods and proper nouns. Only in very special things can cause problems. In those cases I think it is better to use a new HTTP method than putting verbs into the URI. But that is really very rare. E.g. search with query string non compatible parameters e.g. files can be such a case. Another alternative approach in these cases to use POST and verbs in the URI.)

RESTful POSTS, do you POST objects to the singular or plural Uri?

Which one of these URIs would be more 'fit' for receiving POSTs (adding product(s))? Are there any best practices available or is it just personal preference?
/product/ (singular)
or
/products/ (plural)
Currently we use /products/?query=blah for searching and /product/{productId}/ for GETs PUTs & DELETEs of a single product.
Since POST is an "append" operation, it might be more Englishy to POST to /products, as you'd be appending a new product to the existing list of products.
As long as you've standardized on something within your API, I think that's good enough.
Since REST APIs should be hypertext-driven, the URI is relatively inconsequential anyway. Clients should be pulling URIs from returned documents and using those in subsequent requests; typically applications and people aren't going to need to guess or visually interpret URIs, since the application will be explicitly instructing clients what resources and URIs are available.
Typically you use POST to create a resource when you don't know the identifier of the resource in advance, and PUT when you do. So you'd POST to /products, or PUT to /products/{new-id}.
With both of these you'll return 201 Created, and with the POST additionally return a Location header containing the URL of the newly created resource (assuming it was successfully created).
In RESTful design, there are a few patterns around creating new resources. The pattern that you choose largely depends on who is responsible for choosing the URL for the newly created resource.
If the client is responsible for choosing the URL, then the client should PUT to the URL for the resource. In contrast, if the server is responsible for the URL for the resource then the client should POST to a "factory" resource. Typically the factory resource is the parent resource of the resource being created and is usually a collection which is pluralized.
So, in your case I would recommend using /products
You POST or GET a single thing: a single PRODUCT.
Sometimes you GET with no specific product (or with query criteria). But you still say it in the singular.
You rarely work plural forms of names. If you have a collection (a Catalog of products), it's one Catalog.
I would only post to the singular /product. It's just too easy to mix up the two URL-s and get confused or make mistakes.
As many said, you can probably choose any style you like as long as you are consistent, however I'd like to point out some arguments on both sides; I'm personally biased towards singular
In favor of plural resource names:
simplicity of the URL scheme as you know the resource name is always at plural
many consider this convention similar to how databases tables are addressed and consider this an advantage
seems to be more widely adopted
In favor of singular resource names (this doesn't exclude plurals when working on multiple resources)
the URL scheme is more complex but you gain more expressivity
you always know when you are dealing with one or more resources based on the resource name, as opposed to check whether the resource has an additional Id path component
plural is sometimes harder for non-native speakers (when is not simply an "s")
the URL is longer
the "s" seems to be a redundant from a programmers' standpoint
is just awkward to consider the path parameter as a sub-resource of the collection as opposed to consider it for what it is: simply an ID of the resource it identifies
you can apply the filtering parameters only where they are needed (endpoint with plural resource name)
you could use the same url for all of them and use the MessageContext to determine what type of action the caller of the web service wanted to perform.
No language was specified but in Java you can do something like this.
WebServiceContext ws_ctx;
MessageContext ctx = ws_ctx.getMessageContext();
String action = (String)ctx.get(MessageContext.HTTP_REQUEST_METHOD);
if(action.equals("GET")
// do something
else if(action.equals("POST")
// do something
That way you can check the type of request that was sent to the web service and perform the appropriate action based upon the request method.