Which of the following are valid URI's(Uniform Resource Identifier) as per the REST API specifications? - api

How to identify which of the following Uniform Resource Identifier(URI) is valid as per REST API specifications.
Choose one or more options
1. POST https://api.example.com/whales/create/9xf3df
2. PUT https://api.example.com/whales/9xf3df
3. GET https://api.example.com/whales/9xf3df?sort=name&valid=true
4. DELETE https://api.example.com/whales

REST doesn't care what spelling conventions you use for your resource identifiers; anything that conforms to the production rules defined by RFC 3986 is fine.
/whales/create/9xf3df
/whales/9xf3df
/whales/9xf3df?sort=name&valid=true
/whales
/0cc846bb-678d-45d8-9c06-d9cf94cee0a5
/9xf3df/whales
These are all fine identifiers.
Identifiers for a "REST API" are exactly like identifiers for web pages - you can use any spelling you want, and the browsers, caches, web crawlers, and so on will work with them quite happily; these general purpose components treat identifiers like identifiers - they don't try to extract any meaning from them.
By way of demonstration, please observe that all of the following work exactly the way you would expect them to:
https://www.merriam-webster.com/dictionary/create
https://www.merriam-webster.com/dictionary/get
https://www.merriam-webster.com/dictionary/put
https://www.merriam-webster.com/dictionary/post
https://www.merriam-webster.com/dictionary/patch
https://www.merriam-webster.com/dictionary/delete
Does REST care about the POST, PUT, GET, and DELETE for the above options?
Hard to be sure which question you are asking here.
PUT /dictionary/delete HTTP/1.1
That's a perfectly satisfactory request-line, and there is no ambiguity about what it means. In this example, PUT is the method-token; that tells the server that we are requesting that the representation of the target resource (identified by /dictionary/delete) be replaced by the representation include in the message-body of the request
For this specific resource, that probably means that the message-body is an HTML document (we'd see Content-Type: text/html in the headers, to ensure that the server knows how to correctly interpret the bytes provided).
PATCH /dictionary/delete HTTP/1.1
This is also a satisfactory request line; we are again requesting a change to the representation of the /dictionary/delete resource, but we're going about it in a slightly different way - instead of including a replacement representation in the message body, we're providing a representation of a list of changes to make (aka a "patch document").
Uniform interface means that we should expect the folks at www.merriam-webster.com to understand these messages exactly as we've described them here.
Now, for these specific resources, they probably don't want random stack-overflow members making changes to their website, so they are likely to respond 403 Forbidden or 405 Method Not Allowed.
All of the general purpose components will understand what that means, again because the standardized response meta-data is common to all resources.

Related

Appropriate REST design for data export

What's the most appropriate way in REST to export something as PDF or other document type?
The next example explains my problem:
I have a resource called Banana.
I created all the canonical CRUD rest endpoint for that resource (i.e. GET /bananas; GET /bananas/{id}; POST /bananas/{id}; ...)
Now I need to create an endpoint which downloads a file (PDF, CSV, ..) which contains the representation of all the bananas.
First thing that came to my mind is GET /bananas/export, but in pure rest using verbs in url should not be allowed. Using a more appropriate httpMethod might be cool, something like EXPORT /bananas, but unfortunately this is not (yet?) possible.
Finally I thought about using the Accept header on the same GET /bananas endpoint, which based on the different media type (application/json, application/pdf, ..) returns the corresponding representation of the data (json, pdf, ..), but I'm not sure if I am misusing the Accept header in this way.
Any ideas?
in pure rest using verbs in url should not be allowed.
REST doesn't care what spelling conventions you use in your resource identifiers.
Example: https://www.merriam-webster.com/dictionary/post
Even though "post" is a verb (and worse, an HTTP method token!) that URI works just like every other resource identifier on the web.
The more interesting question, from a REST perspective, is whether the identifier should be the same that is used in some other context, or different.
REST cares a lot about caching (that's important to making the web "web scale"). In HTTP, caching is primarily about re-using prior responses.
The basic (but incomplete) idea being that we may be able to re-use a response that shares the same target URI.
HTTP also has built into it a general purpose mechanism for invalidating stored responses that is also focused on the target URI.
So here's one part of the riddle you need to think about: when someone sends a POST request to /bananas, should caches throw away the prior responses with the PDF representations?
If the answer is "no", then you need a different target URI. That can be anything that makes sense to you. /pdfs/bananas for example. (How many common path segments are used in the identifiers depends on how much convenience you will realize from relative references and dot segments.)
If the answer is "yes", then you may want to lean into using content negotiation.
In some cases, the answer might be "both" -- which is to say, to have multiple resources (each with its own identifier) that return the same representations.
That's a normal thing to do; we even have a mechanism for describing which resource is "preferred" (see RFC 6596).
REST does not care about this, but the HTTP standard does. Using the accept header for the expected MIME type is the standard way of doing this, so you did the right thing. No need to move it to a separate endpoint if the data is the same just the format is different.
Media types are the best way to represent this, but there is a practical aspect of this in that people will browse a rest API using root nouns... I'd put some record-count limits on it, maybe GET /bananas/export/100 to get the first 100, and GET /bananas/export/all if they really want all of them.

GET vs. POST when the request is some arbitrary size

I understand the semantics of GETting vs. POSTing, one endpoint should get data, the other should post it. The latter being a request that you may not wish the user to be able to easily replay.
That said, on the project I'm working on at the moment - the approach has been to POST to endpoints that are clearly responsible for responding with data, and these endpoints do not transform data in any way.
The reasoning behind this has been that the payloads are (potentially) of considerable size and seem more appropriate for a body as opposed to a query string.
Can anybody please shed light on which request would be right for a GET request that takes a large request payload? I'm not asking for opinion, I'm asking for what would be compliant to RESTful deisgn.
Further Context
The request is potentially large due to the fact it's a search DTO from the UI, where users may choose to pass any number of filters or search terms.
Can anybody please shed light on which request would be right for a GET request that takes a large request payload? I'm not asking for opinion, I'm asking for what would be compliant to RESTful deisgn.
Today's answer: It's OK to use POST.
For requests that are fundamentally read-only, we'd like to use standardized HTTP semantics to communicate that to general purpose components, so that they can themselves do intelligent things.
BUT: GET, while being both safe and ubiquitous, isn't an appropriate choice when you need to include a message-body in the request:
content received in a GET request has no generally defined semantics
So if you can't, for whatever reason, copy the information you need into a resource identifier, then GET is not an option.
Now, if your payloads are consistent with WebDAV, then you might be able to use one of the safe methods described in those specifications. But, as far as I can tell, they aren't really appropriate for general use.
Tomorrow's answer: the HTTP-WG accepted a proposal for a safe-method-with-body. So we should eventually expect to see a registered HTTP method that is safe and has defined semantic for the request content.
Then, depending on what those semantics are, we may be able to use it for requests like yours.

With REST, do you use a body or query params when creating a Resource?

I'm working on a digital media library where users can create entries for a Media resource.
The media resource is made up of tons of properties, eg:
Media:{
id,
name,
type,
private,
}
the url users use to create a resource is
POST api/media
On the backend, we are creating the resource with a UID generated for them while defaulting name, type and private values. However, users can pass in name, type, private if they choose to.
RFC 4.3.3 doesn't seem to have an opinion on whether or not to use params or post body for these data.
So is it better to do this
api/media?type="audio"&name="Hopkins County Collective"&private=false
or with a body instead?
api/media
body{
name:
type:
private:
}
Althought after reading section 4.3.3 for POST here https://www.rfc-editor.org/rfc/rfc7231#section-4.3.3 and I see this piece
Providing a block of data, such as the fields entered into an HTML
form, to a data-handling process;
I'm leaning toward the post fields in the body but I'm still unsure.
Thanks
do you use a body or query params when creating a Resource?
The Body. But it can be more complicated than that.
HTTP gives us standardized message semantics - we all agree, by adopting the common standard, what a given message means. That doesn't necessarily constraint what we do with the message when we get it.
For example.
PUT /id=1 HTTP/?.?
Content-Type: text/plain
id=2
That message means that we want the resource identified by /id=1 to have the representation id=2. In other words, this is the future behavior intended by the client
GET /id=1 HTTP/?.?
200 OK
Content-Location: /id=1
Content-Type: text/plain
id=2
So the body describes what we want the representation to be, and the effective-uri identifies which document we are talking about.
The same basic pattern holds for POST and PATCH - the effective-uri tells us which resource we want to change, the body describes that change.
BUT...
You the server aren't actually required to do what the request asks you to do. You can reject the request (4xx), or you can do something similar to the request, and tell the client about that.
So you might, as part of the implementation hidden behind your REST facade, copy information from the effective-uri in addition to, or instead of, exactly applying the instructions provided by the client in the body of the request. (You have to be a little bit careful with the response metadata to ensure there's no ambiguity about what you did do).
Anecdotally, "just about everyone" seems to be using the body to represent what they want the created resource to look like, be, or contain.
Parameters are often not likely to be used at all, and if they are, only for, perhaps, controlling aspects of how that resource is to be created, not anything having to do with what the resource is to look like, be, or contain.
I say anecdotal, because I'm sure there are exceptions to this -- you're even contemplating it. That said, REST does not specifically say anything about parameters vs. body.
For the sake of conformity, and for the sake of "doing it like everyone else", go with body.
There are other considerations pointing away from parameters: 1) they are part of the URI, and URIs are used for identification purposes, 2) the query string length is highly constrained, so would prevent creating large objects, and 3) it would be a diagnostics/debugging nightmare parsing the query string in your head trying to make sense of it.

REST API routing with params good practice

There's routing for my server:
/api/debts/:id
to get info about particular debt and
/api/debts/search?searchData=something
to search debts by something.
And first route always handles search requests. I want to change it and know how to do it in several ways (just remove /api/debts in the second route etc) but I want to know a good practice for this.
UPD: There's also the route
/api/debts
to get all debts
For search or filter purposes /api/debts?searchData=something is preferred.
In /api/debts/search?searchData=something, this is not considered good, because it has search which it verb and the searchData is outside the resources.
For details please refer
here
I want to change it and know how to do it in several ways (just remove /api/debts in the second route etc) but I want to know a good practice for this.
REST doesn't care what spelling conventions you use for your resource identifiers.
So if you decide, in the support of other concerns, that you want to use a different path, then go ahead and do that.
/debts/search?searchData=something
/search/debts?searchData=something
Those are both fine. Sticking additional path-segments like api on the front is also fine. General purpose clients don't care, because they are just copying the identifier into the request line
this is not considered good, because it has search which it verb
Consider the URI below
https://www.merriam-webster.com/dictionary/search
This works, and exactly the way you would expect, even though "search" happens to be a verb (sometimes) in the English language.
It's even ok to use registered HTTP methods in your identifiers:
GET /dictionary/delete HTTP/1.1
Host: www.merriam-webster.com
You can try that one in your web browser by clicking on
https://www.merriam-webster.com/dictionary/delete
What doesn't work particularly well is assuming that the identifier defines the request semantics; the request method is the appropriate mechanism for communicating the request semantics, not the identifier. In other words
GET /delete
is a request that promises safe semantics; if you handle that request by making a bunch of destructive edits, then that's a fault of the implementation
The confusion here is not Raj's fault, of course -- there is a LOT of literature on the web that (a) describes arbitrary spelling constraints for resource identifiers and (b) cites "REST" as an authority for those constraints.
Part (b) has no factual basis - it's just folklore that has gained traction.
REST doesn't care about spelling conventions for your identifiers in the same way that compilers don't care about spelling conventions for your variable names.
REST cares a lot about when two identifiers are the same, because caching, and particularly cache invalidation are important things for the general purpose components to be able to do correctly.
But the machines don't distinguish between nouns, verbs, hmac codes, rot13 ciphers, etc.

Content-Range header - allowed units?

This is related to:
How should I implement a COUNT verb in my RESTful web service? , Paging in a Rest Collection
and Using the HTTP Range Header with a range specifier other than bytes?
Actually I think the -1 rated anwser here is correct https://stackoverflow.com/a/1434701/1237617
Generally anwsers say that you can use custom units citing the sec 3.12
range-unit = bytes-unit | other-range-unit
bytes-unit = "bytes"
other-range-unit = token
However when you read the HTTP spec please notice the production rules are thus:
Content-Range = "Content-Range" ":" content-range-spec
content-range-spec = byte-content-range-spec
byte-content-range-spec = bytes-unit SP
byte-range-resp-spec "/"
( instance-length | "*" )
The header spec only references bytes-unit from sec 3.12, not range-units, so I think that actually it's against the spec to use custom units here.
Am I missing something or is the popular anwser wrong?
EDIT: Since this probbably isn't clear, the gist of my question is:
rfc2616 sec14.16 only references bytes-unit. It never mentions range-unit, so range-unit production is not relevant for Content-Range, and thus only byte-units can be used.
I think this adresses my concerns best, although I needed some time to understand it (plus I wanted to make sure, that there is something wrong with the wording).
This reflects the fact that, apparently, the first set of grammar rules has been specifically made for parsing and the second one for producing HTTP requests
thanks to elgaton
The spec, as being revised, allows custom range units. See HTTPbis Part 5, Section 2.
If you read the HTTP/1.1 RFC, section 3.12, you will see that:
The only range unit defined by HTTP/1.1 is "bytes". HTTP/1.1 implementations MAY ignore ranges specified using other units.
So, the other-range-unit token has been introduced only to make servers more "liberal" when accepting. This reflects the fact that, apparently, the first set of grammar rules has been specifically made for parsing and the second one for producing HTTP requests, so that servers could accept even invalid requests (they will be simply ignored) and clients would use only the universally-accepted bytes unit.
Therefore, I personally recommend to:
use only the bytes unit when acting as a client, and
accept other units (discarding the Content-Range header if they are invalid) when acting as a server.
This is a purely personal opinion, but I think it is fairly consistent with how other HTTP extensions (custom methods or headers) are used. Here is how I read it: Yes I can use custom range units and no, I shouldn't submit a bug report when it gets ignored when passing through firewalls, web proxies, and other intermediaries. I conform to the HTTP spec when I'm sending it and they conform to HTTP when they ignore it. WebDAV uses HTTP extensions correctly, IMO, but rarely works over the Internet for exactly this reason. As I said, a personal opinion only.
Apparently it's OK to use custom units, because:
This reflects the fact that, apparently, the first set of grammar
rules has been specifically made for parsing and the second one for
producing HTTP requests