Confirming a message in REST - is it PUT or POST? - api

One of our services generates messages and each message needs to be confirmed. However, the message itself is only identified via it's "type of message", not an ID.
What is the proper HTTP verb for acknowledging the message?
Is it PUT or POST?

If the message does not have a unique ID, then you cannot identify it, so how would you update its status or how do you find it in the database at all? At least generate an MD5 checksum from the JSON representation of the text and other properties md5({message,senderID,receiverID,timestamp,...}). to get an identifier you can use to find the message. After that you can make an endpoint something like /messages/{md5-checksum} and do PUT /messages/{md5-checksum}/confirmed true. You can do POST too POST /messages/{md5-checksum}/confirmation -, but I like PUT better in this scenario.

Related

Should I use GET or POST if getting idempotent information but with parameters that are not meant to be in URL

I have an API that gets a Credit Card number when you supply a reference id. The reference id is considered sensitive data, so my understanding that it shouldn't show up in the URL, and instead needs to be defined in JSON body while the protocol is HTTPs for encryption.
Now should the request be a GET which sounds more natural when reading it, yet looks odd when attaching a JSON body to it. Or should it be POST were it makes sense to have a JSON body, yet sounds odd when reading it, and also the request in itself is idempotent.
A payload within a GET request message has no defined semantics -- RFC 7231
If you must pass information to the server in the payload of the request, then GET isn't a valid option.
On the other hand
POST serves many useful purposes in HTTP, including the general purpose of “this action isn’t worth standardizing.” -- Fielding, 2009
In other words, we use POST if none of the other registered methods have appropriate semantics and we don't want to extend HTTP with our own method-token.
should it be POST were it makes sense to have a JSON body, yet sounds odd when reading it, and also the request in itself is idempotent.
It's not ideal - you have a request where the intended semantics are idempotent, but no effective way to communicate that to general purpose components.
What you can sometimes do, is use a request with a body to create a new resource, and then use GET with the identifier of the new resource. That keeps the sensitive information out of the logs, while still giving you safe semantics, but at the cost of an extra round trip and some complexity
POST /foo
Content-Type: application/json
{ "CreditCardNumber" : "0000-0000-0000-0000" }
201 Created
Location: /4d49cad6-4165-472d-ad61-c91160fdd06c
Content-Location: /4d49cad6-4165-472d-ad61-c91160fdd06c
Here, Location tells a general purpose client where the new page has been created, and Content-Location tells a general purpose client that the contents of this message is a copy of the new page.
If the client wants to check that page later for an update, a simple GET request will work
GET /4d49cad6-4165-472d-ad61-c91160fdd06c
So the URI never has the credit card number, but instead has a token that can unlock the credit card number from some secure store at the server.
In effect, /4d49cad6-4165-472d-ad61-c91160fdd06c is a web page about credit card number 0000-0000-0000-0000.
But there's extra song and dance when the client doesn't remember the unique identifier for that web page, and has to use POST to ask where it is again.

How can a Slack app communicate to the user why a slash command failed, and let the user edit the command?

When an app fails to handle a Slack slash command, the text is brought back to allow the user to edit it and immediately send it again. I have a slash-command that searches, but might fail to find any results. In that case, I would like the user to immediately be able to modify their search. The Slack docs explain that I should always return a 200 HTTP status, but then Slack also erases the command and the user can't immediately try again. When I tried to respond with a 404 status, the users get an alarming message like failed with the error "http_client_error". Is there a way to fail but also provide a custom message to the user why?
Yes, but you must not use HTTP status codes to community a failed search.
Just always return HTTP OK 200 and then add a response message telling the user what went wrong. You can do that by directly replying to the request from Slack within 3 seconds, or alternatively by sending a message to the response_url.
This is also clearly expressed in the offical documentation for slash commands:
Sending Error Responses
There are going to be times when you need to let the user know that something went wrong - perhaps the user supplied an incorrect text parameter alongside the command, or maybe there was a failure in an API being used to generate the command response.
It would be tempting in this case to return an HTTP 500 response to
the initial command, but this isn't the right approach. The status
code returned as a response to the command should only be used to
indicate whether or not the request URL successfully received the data
payload - while an error might have occurred in processing and
responding to that payload, the communication itself was still
successful. (Source)
As far as I know it is not possible to signal Slack that the user should be able to edit his last command though.

REST API GET method

According REST API design recomendations, getting user by id must be
GET /users/{id}
How will look getting user by unique phone number?
GET /users/phone/{number}
or
GET /users/?phone=xxxxxxxxxxx
or
GET /phones/{number}/users
or anything else?
Or for example getting last user comments with limitation:
/users/{id}/comments/limit/{limit}
or
/users/{id}/comments/?limit='xx'
There are constraints or recomendations in such cases?
Which HTTP method is better to send request for making some actions (for example SMS sending).
There are a lot of different aspects in your question, so I am picking some and hope the answer is somewhat helpful to you.
Generally speaking, a URI ist he unique identifier of a certain ressource. Further more, "good REST-API URIs" contain only nouns (to 'name' the resource), not verbs (what should be done with the resource). URI parameters may be used to parameterize the ressources representation, e.g. sorting or filtering.
In your example,
/users/{id}/?limit='xx'
would be a valid way to fetch a list of some sub-ressources (possibly the users comments), but here is nothing on the URI that refers to a specific property or sub-ressource (e.g. comments).
A more meaningful ressource URI would be
/useres/{id}/comments/?max=100&sort=asc
In this case, the first part (users/{id}/comments/) identifies the ressource, while the params are used to parameterize its representation. Proper URI's do not rely on URI params to uniquely identify ressources.
Filter criteria in the URI may be treated similiar. You could put them in parameters, but that may lead to problems with multiple and/or complex filters, e.g.
GET
/useres/?phone=1234&phonemode=startswith&name=foo&namemode=contains
One way to do this could be to create a filter (maybe just temporarily) and then retrieving the filtered information with a subsequent GET request like this:
POST /users/filter
name='mycomplexfilter'
poperty='name'
value='foo'
mode='contains'
GET /useres/filter/mycomplexfilter
Hope this helps to shed some light on the topic
[EDIT]
See this summary for an explanation of the commonly used HTTP methods (aka verbs): Which HTTP methods match up to which CRUD methods?
See this question for a similiar answer.
Initiating a server sent notification (perhaps via SMS) should be requested using POST (e.g. to the ressource URI /notifications) with text and recipient in the payload. HTTP headers could be used to indicate the desired type of the notfication, while the HTTP status codes indicate the success of the sending attempt. Status code 201 indicates successfull sending of the message, returning also the URI for the newly created ressource.
Client request:
POST /notifications
recipient="+0049123456789"
text="this is the SMS text"
Server response:
201 - Created
Location: /notifications/9876

Where should I locate Mule CRC32 filter in my flow?

I want to locate Mule CRC32 calculator and filter in my flows. I've located the calculator at the end of my first flow, right before replying. But where do I locate the filter? right after receiving the second request?
When I do that I get the following error:
Root Exception stack trace: org.mule.api.expression.RequiredValueException: Expression Evaluator "header" with expression "invocation:crc32" returned null but a value was required.
Another thing that might cause this error is:
I send the first HTTP request using Firefox, then I copy the response body and send the second request using Postman (Chrome). Do I lose the checksum data?
Thanks,
Keren
It seems that the problem here is the scope of your properties.
Looks like you want to send the header back to your requestor, that then should send it back to the server.
To do so use an oubound property at the first flow (rather than a flow variable that will never go beyond your first flow). Then if the requested send the crc back you get it as an inbound property on the second flow.
Find here more information about the scopes.

what should be HTTP status code if resource is not available for requested action?

I am developing a RESTful API. I am confused about setting HTTP status code in this particular scenario. I am not sure what status code should I (server) return.
Let's say my app has a follow user functionality, if I am already following a user and again I send follow request for the same user id then in this case what should be the HTTP status code from server. The status code will be followed by an error message saying something like: "already following the user."
Similar scenario can be considered for unfollow user functionality, if I am not following an user "A", still I send request to unfollow user "A", then what HTTP status code should server return with error message something like "not following user to unfollow"
Certainly 200 response code doesn't seem to be appropriate to me here? or does it?
Please forgive me if I have posted the question at wrong stack exchange site, I posted it in stackoverflow site just because it is related to REST APIs.
EDIT
From client side user needs to send POST request to the URL:
http://www.myserver.com/api/follow/10
along with other necessary parameters ( like API keys, proper headers, etc) which are used for authentication before serving the requests at server side.
similar URL for unfollow action is:
http://www.myserver.com/api/unfollow/10
Right now, I am sending HTTP status code 200 in response if the client sends follow request, let's say, for user id 10 even if he/she is already following the user with id 10. In this case,along with status code (200) I am sending message similar to "already following the user"
Somehow I feel this is not convincing as no resource is created/updated it should return the error message with proper status code something other than 200, may be one from 4XX, not sure.
422 Unprocessable Entity
422 seems to be the proper HTTP status code in this use case.
The description of 422 says:
The 422 (Unprocessable Entity) status code means the server understands the content type of the request entity (hence a 415(Unsupported Media Type) status code is inappropriate), and the syntax of the request entity is correct (thus a 400 (Bad Request) status code is inappropriate) but was unable to process the contained instructions.
The answer depends on your API. You're describing the API in terms of "follow user X" or "unfollow user Y". That makes me think you might be approaching your API design in an RPC style rather than focusing on resources.
If your API uses REST including the HATEOAS principle, then error codes from the 4xx range may be appropriate (but I would recommend against it in this case, see below). In very short: HATEOAS means that your resources provide links to possible "actions". You can read more about it here: http://restcookbook.com/Basics/hateoas/
Apart from that, it seems a good idea to design your API "fault tolerant", i.e. expect the same request sent multiple times (e.g. because users are impatient and click again and again, or the browser crashed and is restarted and reopens all previous tabs, or...).
My personal opinion and recommendation is the following:
follow user X: Your implementation should check if it needs to add the new follower or not. Regardless, if the user is already following or not, send back HTTP status 201 (created) and add the "Location" HTTP header pointing at the resource.
unfollow user X: Your implementation should check if it needs to delete the follower or not. Regardless, if the user is already removed from the followers or not, send back HTTP status 200 (OK).
The general idea is, if a client requests something to be a certain way and that is already the case, the server has two options: Either it responds to the client "The result you wish is already in place. Therefore your request is invalid." or the server can respond "The result you wish is already in place. You have everything you need.".
Going for the second option makes the API more tolerant and helps with idempotency (see http://restcookbook.com/HTTP%20Methods/idempotency/).
I think djlauk's answer covers a lot, but I want to give a little different approach and add some information:
Do not use verbs in the URI
I would not use POST on /follow/ respectively /unfollow/ URIs because this is not very RESTful see this SO question: Why does including an action verb in the URI in a REST implementation violate the protocol? and escpacially this SO answer: How to create REST URLs without verbs?
Do use the correct HTTP verbs for the actions
What you want to do is a creation of an entity ("follow") so for that you can use the HTTP verbs POST or PUT and afterwards the deletion of that entity ("unfollow") where DELETE would be the right fit.
My approach for your API:
I would do the following:
(The first two examples are just for explaining the structure, you don't have to implement them if you don't need them.)
This does get you the user "robert":
GET http://www.myserver.com/api/users/robert/
response: #200
This does get you the users "robert" is following:
GET http://www.myserver.com/api/users/robert/following/
response: #200
And this is how you let "robert" follow "rahul":
PUT http://www.myserver.com/api/users/robert/following/rahul
response: #200
If you send this request again you get the same response:#200 because PUT is idempotent and this is how it should behave (see (2))
When you now want to let "robert" unfollow "rahul" you send:
DELETE http://www.myserver.com/api/users/robert/following/rahul
response: #200
If you send the DELETE request again you get a little different response a #404 , but this is HTTP standard and the clients should understand this.
For the regular answer codes of HTTP methods I can also recommend this source: restapitutorial.com
I would use some of the following:
System.Net.HttpStatusCode.ServiceUnavailable;
System.Net.HttpStatusCode.MethodNotAllowed;
System.Net.HttpStatusCode.BadRequest;
Better if it is one of the first two.
Certainly 200 response code will not work in this situation.
following are the groups in HTTP Status Code:
1xx Informational
2xx Success
3xx Redirection
4xx Client Error
5xx Server Error
Certainly you need to use 4xx.
I think for the condition that you have described here, you can use any of the following:
405 Method Not Allowed
A request was made of a resource using a request method not supported by that resource; for example, using GET on a form which requires data to be presented via POST, or using PUT on a read-only resource.
400 Bad Request
The server cannot or will not process the request due to something that is perceived to be a client error
409 Conflict
Indicates that the request could not be processed because of conflict in the request, such as an edit conflict in the case of multiple updates.
More details are available here:
http://en.wikipedia.org/wiki/List_of_HTTP_status_codes