Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Which HTTP redirect status code is best for this REST API scenario?

I'm working on a REST API. The key objects ("nouns") are "items", and each item has a unique ID. E.g. to get info on the item with ID foo:

GET http://api.example.com/v1/item/foo

New items can be created, but the client doesn't get to pick the ID. Instead, the client sends some info that represents that item. So to create a new item:

POST http://api.example.com/v1/item/
hello=world&hokey=pokey

With that command, the server checks if we already have an item for the info hello=world&hokey=pokey. So there are two cases here.

Case 1: the item doesn't exist; it's created. This case is easy.

201 Created
Location: http://api.example.com/v1/item/bar

Case 2: the item already exists. Here's where I'm struggling... not sure what's the best redirect code to use.

301 Moved Permanently? 302 Found? 303 See Other? 307 Temporary Redirect? Location: http://api.example.com/v1/item/foo

I've studied the Wikipedia descriptions and RFC 2616, and none of these seem to be perfect. Here are the specific characteristics I'm looking for in this case:

The redirect is permanent, as the ID will never change. So for efficiency, the client can and should make all future requests to the ID endpoint directly. This suggests 301, as the other three are meant to be temporary.

The redirect should use GET, even though this request is POST. This suggests 303, as all others are technically supposed to re-use the POST method. In practice, browsers will use GET for 301 and 302, but this is a REST API, not a website meant to be used by regular users in browsers.

It should be broadly usable and easy to play with. Specifically, 303 is HTTP/1.1 whereas 301 and 302 are HTTP/1.0. I'm not sure how much of an issue this is.

At this point, I'm leaning towards 303 just to be semantically correct (use GET, don't re-POST) and just suck it up on the "temporary" part. But I'm not sure if 302 would be better since in practice it's been the same behavior as 303, but without requiring HTTP/1.1. But if I go down that line, I wonder if 301 is even better for the same reason plus the "permanent" part.

Thoughts appreciated!


Edit: Let me try to better explain the semantics of this "get or create" operation with a more concrete example: URL shortening. This is actually much closer to my app anyway.

For URL shorteners, the most common operation by far is retrieving by ID. E.g. for http://bit.ly/4Agih5, bit.ly receives an ID of 4Agih5 and must redirect the user to its corresponding URL.

bit.ly already has an API, but it's not truly RESTful. For the sake of example, let me make up a more RESTful API. For example, querying the ID might return all sorts of info about it (e.g. analytics):

GET http://api.bit.ly/item/4Agih5

Now if I want to submit a new URL to bit.ly to shorten, I don't know the ID of my URL in advance, so I can't use PUT. I'd use POST instead.

POST http://api.bit.ly/item/
url=http://stackoverflow.com/ (but encoded)

If bit.ly hasn't seen this URL before, it'll create a new ID for it and redirect me via 201 Created to the new ID. But if it has seen that URL, it'll still redirect me without making a change. This way, I can hit that redirect location either way to get the info/metadata on the shortened URL.

Like this example of URL shortening, in my app, collisions don't matter. One URL maps to one ID, and that's it. So it doesn't really matter if the URL has been shortened before or not; either way, it makes sense to point the client to the ID for it, whether that ID needs to be created first or not.

So I probably won't be changing this approach; I'm just asking about the best redirect method for it. Thanks!

like image 946
Aseem Kishore Avatar asked Mar 11 '10 18:03

Aseem Kishore


People also ask

Which HTTP status code is returned after a successful REST API request?

2xx Status Codes [Success] Indicates that the request has succeeded. Indicates that the request has succeeded and a new resource has been created as a result.

What is redirection code in API?

URL redirection, also known as URL forwarding, is a technique to give more than one URL address to a page, a form, or a whole Web site/application.


1 Answers

I'd argue for 303. Supposing right now hello=world&hokey=pokey uniquely identifies item foo, but later item foo's hokey value changes to "smokey"? Now those original values are no longer a unique identifier for that resource. I'd argue that a temporary redirect is appropriate.

like image 190
Jacob Mattison Avatar answered Oct 12 '22 08:10

Jacob Mattison