Content-Range header - allowed units? - api

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

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.

Should REST API returns error 400 on request that should not have query?

Is there any standard in HTTP regarding how request should be handled in case where an endpoint/request URL that supposed to not receive any query but the requester supply a query anyway ?
if it exist, what the standard states ? if not, is there any other related standard/statement regarding this like how request query supposed to be handled in general or such within the HTTP standard ?
thank you
By default, when you receive more parameters than expected and if you don't need it, you don't care
Is there any standard in HTTP regarding how request should be handled in case where an endpoint/request URL that supposed to not receive any query but the requester supply a query anyway ?
From the perspective of HTTP, the entire target-uri in the request line is the identifier for the resource:
POST /123?456
In this example, the target-uri is /123?456.
RFC 7231 defines 404 Not Found
The 404 (Not Found) status code indicates that the origin server did not find a current representation for the target resource or is not willing to disclose that one exists.
Which is to say, if you want to draw the clients attention to the spelling of the target-uri, 404 Not Found is the way to do that.
That said, there are no "rules" about how the server interprets the target-uri. If you want to ignore the query part, and provide the same representation that is used for /123 then that's fine.
when you receive more parameters than expected and if you don't need it, you don't care
In messaging, ignoring unrecognized parts of the message can be useful when trying to ensure that your schema is forwards/backwards compatible; old clients using the old specification can talk to new servers using the new specification, and vice versa.
The same principle is described in the header specification for HTTP
Other recipients SHOULD ignore unrecognized header fields. These requirements allow HTTP's functionality to be enhanced without requiring prior update of deployed intermediaries.

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

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.

REST request cannot be encoded for GET (URL too long)

Example:
URL: http://example.com/collection/a%20search%20term
Method: GET
Response: All items in collection matching a search term.
Problem: The search term may be so long that it breaks the web server's maximum
URL length.
How do I allow extremely long search terms and still stay RESTful?
For inspiration, I just looked at Google Translate's API v2, which is "using
the RESTful calling style."
Naturally, texts to be translated can be quite long. And so Google optionally
allows sending a request with POST, but with a twist:
To use POST, you must use the X-HTTP-Method-Override header to tell the
Translate API to treat the request as a GET (use X-HTTP-Method-Override:
GET).
So it is possible to semantically transform a POST request into a GET request.
(This discovery led me to add the x-http-method-override tag to my question.)
REST does not restrict POST to creation. Be careful with mapping CRUD to HTTP methods and assume that's RESTful. POST is the method used for any action that isn't standardized by HTTP.
Since the standard doesn't establish a limit for URIs, this can be considered a broken implementation, and it's ok to fix it. As long as the workaround is loosely coupled to your API, you are still RESTful. This means your API shouldn't implement a translation or override directly, but on a pre-processor of some kind that rewrites the request properly. It should be clearly documented somewhere that this is due to a broken implementation, and you expect it to eventually become obsolete.
It's a bad smell if your query can be so long that it exceeds the maximum length (de facto for browsers is 2000 characters but it can be higher for other means of accessing REST APIs).
If the user can pass in that much data, it should go in the request body/data field, not in the URL.

API design - what's the best way to respond useful error messages with 400s?

I'm designing an API to be as HTTP compliant as I can. This includes sending specific response codes back and using the Accept header to specify versions and response types.
I understand this may appear subjective, but I'm sure there's a conventional way of doing this. I have a set of response types that the API supports, along with a vendor-specific mime type to specify the type and version.
Currently, when the client specifies a non-existant version or type, I'm just returning a 400 Bad Request with an empty body, however, I want to return a useful error message. In the event that I don't know the response type, I feel a bit dirty responding with plain text (or defaulting to JSON). Is there a header I'm missing, or some convention that I should follow? I want to get this one right from the offset.
Thanks, and my best,
Jamie
Try the status code of 406 Not Acceptable.
http://support.microsoft.com/kb/943891/
This is a list of HTTP sub-codes supported by Microsoft IIS. I've found this page damn handy since it gives you some insight into the messages they use to handle various errors. There are some HTTP sub-codes that refer to headers.