Imagine I am creating an API to allow a user to attach an image to their profile, where the image may come from a binary submission in the body, or a url, which the server will retrieve and process.
Assuming the API expects a PUT with binary image data to
/user/jon/image
When adding the URl functionality, which of the following would be preferable?
A:
PUT to /user/jon/image/url
passing the url in the body
or
B:
PUT /user/jon/image/
passing in a url in the body and setting a MIME type to advise the host whether or not the content is an image or an URL?
Is there a standard way of dealing with this situation? I feel that using MIME types to dictate the payload is more semantically correct, but a little less discoverable
Thanks
Once I had this same problem. I solved it by first posting the image by "PUT /user/jon/image/" and then posting the URL with PUT to /user/jon/image/url.
The problem is, that the user posts an image and forgets about the URL. I solved this by saving the image temporally in a session and when the URL is posted, I saved the URL and the image at the same time.
Problem is, this is not Restful, because a restful server doesn't have sesions. But being 100% restful is almost imposible, so its your choice.
Related
I'm in a situation where the server has some items that are identified by two keys: type and size. Clients don't know the items ID.
Clients should be able to perform a request to get a list of the items they want. e.g.:
"Give me the circle 40, the circle 30 and the square 40".
That's easy with a json body, but we must use a GET request. Given the problem this is not useful at all: /ids=1,2,3.
Should we make a:
Bizarre convention that clients should send type_size?
Still bizarre convention that clients should send type=size1,size2
GET request for every type?
POST request to act as a GET?
POST request that generates an ID to perform a subsequent GET
request?
How would you do this with an HTML web page?
You'd probably have a web page with a form, the form would have input controls so that the client can list the items they want. When the are finished filling in the form, the submit it.
At that point, the browser uses the data collected by the input controls to create an application/x-www-form-urlencoded document, and (because the method on the form is GET), use that document as the query part of the request uri.
GET /items?circle=30&circle=40&square=40
More generally, we can provide to the client a URI template that describes how information should be encoded into the URI.
But as far as HTTP is concerned: as long as the URI conforms to the production rules described by RFC 3986, it can be anything you want. As long as the client understands how to encode the information, and the server knows to decode the information the same way, you can do what you like.
Let me set up a very specific use case...
Let's say that you're creating a facial recognition API using Python. When you upload an image to the API at an unspecified route, you get back a list of identities that match that image... the return object is an array: ['tom', 'brad', 'john'].
You're not uploading any data to be created or kept on the server.
You're not updating or creating anything.
What kind of request should this be? I'd assume a GET request because you're GETting the identities of the people in the uploaded image regardless of the fact that you're sending an image for processing.
I'd assume a GET request because you're GETting the identities of the people in the uploaded image regardless of the fact that you're sending an image for processing
Sadly, no. The problem here is that GET, in HTTP, does describe the semantics of a message body on the request.
A payload within a GET request message has no defined semantics; sending a payload body on a GET request might cause some existing implementations to reject the request.
You've got the right idea - the request should be safe, so you can look at the HTTP Method Registry to see if there is a match. That might lead you to SEARCH or REPORT. These methods are extensions defined by WebDAV, and may or may not be suitable for your problem.
If it is acceptable to include the representation of the image in the query string, you could pair that with GET. I suspect you'll run into problems with components complaining that the identifier is too long.
The TL;DR? use the POST method to deliver the image payload to the server.
I'm building REST API, and when resource is created normally I return HTTP 201 Created along with Location header to specify where that resource is located. But from some reason http client is not redirecting.
I'm using Postman for this. Does anyone have idea on this problem?
In short, a Location header is not sufficient to trigger a client redirect. It must be used in conjunction with a 3xx HTTP status code.
References:
https://en.m.wikipedia.org/wiki/HTTP_location
Redirecting with a 201 created
This is one of those things where the expectation does not meet what actually happens, and the first thing people think is "well that doesn't work properly", as has been suggested in other comments.
The Location is just a random header, and clients, such as Postman or curl or anything else need to be instructed to follow them. Most won't do this by default, as that is an unreasonable default.
YouTube for example returns a body for some responses and a Location tag too. One example would be video uploads. They respond to your original meta-data for the video is sent with a POST, and they shove a Location URL which is the endpoint to upload the video too. If clients just randomly redirected to that you'd be having a bad time.
You can use Paw to make a "sequence", which I believe will let you take values from headers to reuse. This is also possible with Runscope Ghostinspector.
Thinking in a RESTful way, is it correct to use POST to create in a single call a resource and its sub-resource?
In my application I have the resource /notices/{notice} and sub-resource /notices/{notice}/photos/{photo}. A {photo} can't exists without a {notice}, but a {notice} doesn't have necessarily photos. Normally, I have to do first a POST to create a notice, then another POST to add a photo.
Now I want to allow the creation of a notice with a photo directly attached, enabling the creation of /notices/{notice} and /notices/{notice}/photos/{photo} with a single POST request to /notices/{notice}/photos/{photo}, with a multipart content describing both the resources (JSON for notice, binary for the photo). I think I will return the Location header only for the sub-resource.
Essentially, I want this to prevent Android clients to send two POST request to the server to upload a notice with a photo.
Is this correct? Or does it infringe REST principles? Should I consider to keep them separate and make two different requests? Or is it wrong to consider photos a separate entity from the notice? Should I keep only /notices/{notice} as resource, using PUT to add photos?
Which is the best solution?
Yes, there is nothing wrong with creating sub-resources at the same time you create the parent resource. It would even be OK to use PUT instead of POST to do this, as everything under the parent URL is part of/belongs to the resource you are uploading.
EDIT:
Now I want to allow the creation of a notice with a photo directly attached, enabling the creation of /notices/{notice} and /notices/{notice}/photos/{photo} with a single POST request to /notices/{notice}/photos/{photo}
This I disagree with. I suggest POSTing to the collection resource's URL, /notices. You provide the notice and its photos as a single representation (request body). The back end will then create resources for both the notice and any constituent photographs.
Although its essential in many cases, multiple edits/creates are not formally addressed by the RESTful architecture style.
Problem starts when you need to report failures on part of the collection, and the problem is worsen when they failures have different cause.
An it will effect choosing the right Hypermedia controls which are essential for the client to find a way forward in the given transaction/conversation.
so my suggestion is to have a nested cycle or POST requests rather than a sing POST to create nested Resources , so that it'd be easier and clearer to address each Resource state change.
I'm using the ASIHTTPRequest lib in my iOS app for making REST requests to a web app. I'm doing my best to use the correct verbs (GET, POST, PUT, DELETE) when making the various requests, but when making a POST request, I'm not sure I understand why it matters if I include the parameters in the POST request or in the URL. It works both ways, so why should I include the parameters in the POST request instead of just including them in the URL? As I understand it, the only reason for include the parameters in a POST request is to keep them from being visible in the URL in case someone is looking over your shoulder, or something like that. But if I'm making a POST request from my iOS app and there's no browser involved, then does it really matter which way I do it?
Thanks so much for your wisdom, I'm still learning!
When using a POST request, it is good practice to put the parameters in the data instead of the URL. In your case, it works to put it in the URL, but this isn't always true. Some scripts will expect the parameters to be in a specific place and not find them if they aren't there. As for what POST is good for, it allows you to send more data. The URL is limited to a length of 255 characters, so you need to use some other method if you want to send more data than that. The data in a POST request also doesn't need to be encoded to be compatible with the URL specification.
As I understand it, the only reason for include the parameters in a POST request is to keep them from being visible in the URL in case someone is looking over your shoulder, or something like that.
You misunderstand it.
There are other issues. If your site makes changes to data based off a GET request, it's possible that spambots, search engines, browser prefetchers, and other automated tools will trigger potentially destructive data changes.
If the endpoint isn't under your control, it's entirely possible that it won't even accept the parameters as GET parameters. Most APIs require proper usage of the GET vs. POST verbs.