Is adding an image to a GET request a bad design pattern? - rest

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.

Related

What is a RESTful way to GET specific resources depending on more than one parameter?

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.

GET or POST for stateless RESTFUL API

I'm writing a stateless API. You send it a document, it processes the document, and then returns the processed document. I'm struggling to understand how the RESTFUL rules apply. I'm not retrieving data, creating data or updating data on the server. There is no data on the server. What do I need to use in this case as the http method and why?
Good news - you are right that it is confusing.
Nothing on the server changes in response to the request. That suggests that the request is safe. So GET is the natural choice here... BUT -- GET doesn't support message payloads
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.
HEAD, the other ubiquitous safe method, has the same problem (and is unsuitable when you want to return a document in any case).
The straight forward thing to do at this point is just use POST. It's important to realize that POST doesn't promise that a request is unsafe, only that it doesn't promise that it is safe -- generic components won't know that the request is safe, and won't be able to take advantage of that.
Another possibility is to look through the method registry, to see if somebody has already specified a method that has the semantics that you want. Candidates include SEARCH and REPORT, from the WebDAV specifications. My read of those specifications is that they don't actually have the right semantics for your case.
A Lot of ways to do what you want. But here is a small guideline.
I would create an endpoint that receives the document:
/receive_document
with a 'POST' method. Since you are 'sending' your document to the server
I would create an endpoint that serves up the processed document:
/processed_document
with a 'GET' method. Since you want to retrieve / see your document from the server?
The problem that you are trying to solve is mainly related to the document size, and processing time before returning the response.
Theorically, in order to use a restful approach, you have an endpoint, like yourhost.com/api/document-manager (it can be a php script, or whatever you are using as backend).
OK, so instead of naming the endpoint differently for each operation type, you just change the HTTP method, I'll try to make an example:
POST: used to upload the document, returns 200 OK when the upload is completed.
GET: returns the processed document, you can also return a different HTTP code, in case the document is not ready or even different if the document hasn't been uploaded. 204 no content or 412 precondition failed can be good candidates in case of unavailable document. I'm not sure about the 412, seems like it's returned when you pass a header in the request, that tells the server which resource to return. In your case, I think that the user processes one document at time. But to make a more solid api, maybe you can return an ID token to the user, into the POST response, then forward that token to the GET request, so the server will be able to know exactly which file the user is requesting.
PUT: this method should be used when updating a resource that has been already created with POST
DELETE: removes a resource, then return 204 or 404
OPTIONS: the response contains the allowed methods on this endpoint. You can use it to know for example which privileges has the currently logged user on a resource.
HEAD: is the same as a GET call, but it shouldn't return the response body. This is another good candidate for you to know when the document has been processed. You can upload with POST, then when the upload is done, start some kind of polling to the same endpoint with the HEAD method, finally when it will return "found", the polling will stop, and make the final GET call, which will start the download of the processed document.
HTTP methods are a neat way of managing HTTP communications, if used properly are the way to go, and easily understandable by other developers. And not to forget, you don't have to invent lots of different names for your endpoints, one is enough.
Hope that this helped you a little... But there are loads of guides on the net.
Bye!

HTTP GET request with body for RESTful API [duplicate]

This question already has answers here:
HTTP GET with request body
(23 answers)
Closed 2 years ago.
I've been looking at how to implement the following:
I am developing a RESTful Web API (using .Net Core 2.2). I need to create an endpoint where the consuming client can send some text to the API, the API replaces some tokens in this text, and returns the text back to the consuming client.
I thought that the client should simply do a GET request, with the text in the body. The reply would then be the new text after the token replacements. However, from my research, it appears one should not stick anything with semantics in the body of a GET request. I'm not sure if arbitrary text with certain tokens that need to be replaced by the API qualifies as semantic? I've also seen it stated at "you should not be able to use the body of a GET request to alter the response". I guess I'm in trouble there, as depending what goes into he body, will affect the response.
So then, I've been struggling to figure out what is the correct way to do this. If anyone has an pointers I'd greatly appreciate it.
Thank you.
I thought that the client should simply do a GET request, with the text in the body. The reply would then be the new text after the token replacements. However, from my research, it appears one should not stick anything with semantics in the body of a GET request.
Right - RFC 7231
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.
In basic HTTP, you've got choices. One is to include a representation of your document in the URI itself
/?your_document_as_a_query_string
/your/document/as/path/segments
For short documents, that approach can be fine; but implementations are not required to support infinitely long identifiers, so you may discover that intermediate components reject your request, or crop the URI in transit.
A safe mechanism for achieving your goal is to use POST, rather than GET. POST supports a message body, so you can send the blank form to the server, and receive back the edited version in the response.
POST is the wildcard method of HTTP, it can mean anything. In the spec, the body of the response includes "a representation of the status of, or results obtained from, the action".
You might also consider that the response duplicates a lot of the content of the body of the request, and consider instead the possibilities of fetching a map of your template values from the server, and then applying the template on the client.

Requesting RESTful GET with meaningful Body? Standards not clear

We found ourselves in a dead end when trying to follow standards as we need to build a request that should be a GET and should have a meaning Body.
The request just wants to retrieve some data, no modification inside the database, just getting some data. But at the same time we need to send an array of ids for the objects we want to retrieve, and no, these objects can't be indexed in any way so we really need to send the list of ids or alternatively make 100 requests to the server to get them one by one. That's not gonna happen.
We could also add the list to the URL, but we can't be sure the URL won't end up being too long if the list of ids were to be too big. So to ensure the system doesn't fail we want to use the Body.
I read that a GET can have a Body, but only if it isn't meaningful:
HTTP GET with request body
Yes. In other words, any HTTP request message is allowed to contain a message body, and thus must parse messages with that in
mind. Server semantics for GET, however, are restricted such that a
body, if any, has no semantic meaning to the request. The requirements
on parsing are separate from the requirements on method semantics.
So, yes, you can send a body with GET, and no, it is never useful to do so.
This is part of the layered design of HTTP/1.1 that will become clear again once the spec is partitioned (work in progress).
....Roy
But our Body IS meaningful, which takes us to have to decide between unfollowing HTTP standards or unfollowing REST standards.
Is there any alternative to that? (It's not that this blocks us but I would like to know the answer).
Thank you very much.
you should consider changing your request to POST method.
As I understand it, there are three potential issues with a GET with request body: (link to blog)
Not all servers will support this.
Not all tools will support this (Swagger, POSTMAN added support this year: https://github.com/postmanlabs/postman-app-support/issues/131)
There is not yet a consensus on GET with request body. (For example, is Dropbox still using a POST)
so you'll have problems process the body with GET

How to send response code in REST services.?

I am developing RESTful Services to CREATE operations. In my use case, it is enough to tell the clients whether the transaction is success or fail. And if fail, we need to send them back error code.
Is it possible to send only these information back without sending xml response or JSON response. If so, how to do it.
We have existing error code in 5 digits, we wont be changing this for this api. If this is not possible.
Will JSON response better than XML response.? We are accepting XML request.
Requesting your comments.
I'm going to assume this service will be called over HTTP, since that's what most people mean when they say "RESTful service."
Generally speaking, most people map "create" type functionality to POST methods (though you can also do it with PUT).
If you just need to indicate that the record was created, the answer is "None of the above" (i.e., you don't need a response body at all). Usually a 201 Created is returned with a Location header which specifies the URL of the newly-created resource. In theory, you could also return a 204 No Content since you don't need to pass anything other than the status code (though this would be more appropriate for a PUT, otherwise there is no way to communicate to the client the identifier of the newly-created resource).
For failures, usually a 400-series error is returned if the request message is bad (i.e., it's the client's fault) and a 500-series error is returned if a system error occurs when processing (i.e., it's the server's fault). If you need to convey additional information in the response body, consider returning a response that uses a media type of something like application/vnd.error which allows you to express context information about where the error occurred.