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
Related
So i have one single http post API called UpsertPerson, where it does two things:
check if Person existed in DB, if it does, update the person , then return Http code 200
if not existed in DB, create the Person, then return http 201.
So is it a good practices by having the same api return different statusCode (200,201) based on different actions(update, create)?
This is what my company does currently , i just feel like its weird. i think we should have two individual api to handle the update and create.
ninja edit my answer doesn't make as much sense because I misread the question, I thought OP used PUT not POST.
Original answer
Yes, this is an excellent practice, The best method for creating new resources is PUT, because it's idempotent and has a very specific meaning (create/replace the resource at the target URI).
The reason many people use POST for creation is for 1 specific reason: In many cases the client cannot determine the target URI of the new resource. The standard example for this is if there's auto-incrementing database ids in the URL. PUT just doesn't really work for that.
So PUT should probably be your default for creation, and POST if the client doesn't control the namespace. In practice most APIs fall in the second category.
And returning 201/200/204 depending on if a resource was created or updated is also an excellent idea.
Revision
I think having a way to 'upsert' an item without knowing the URI can be a useful optimization. I think the general design I use for building APIs is that the standard plumbing should be in place (CRUD, 1 resource per item).
But if the situation demands optimizations, I typically layer those on top of these standards. I wouldn't avoid optimizations, but adopt them on an as-needed basis. It's still nice to know if every resource has a URI, and I have a URI I can just call PUT on it.
But a POST request that either creates or updates something that already exists based on its own body should:
Return 201 Created and a Location header if something new was created.
I would probably return 200 OK + The full resource body of what was updated + a Content-Location header of the existing resource if something was updated.
Alternatively this post endpoint could also return 303 See Other and a Location header pointing to the updated resource.
Alternatively I also like at the very least sending a Link: </updated-resource>; rel="invalidates" header to give a hint to the client that if they had a cache of the resource, that cache is now invalid.
So is it a good practices by having the same api return different statusCode (200,201) based on different actions(update, create)?
Yes, if... the key thing to keep in mind is that HTTP status codes are metadata of the transfer-of-documents-over-a-network domain. So it is appropriate to return a 201 when the result of processing a POST request include the creation of new resources on the web server, because that's what the current HTTP standard says that you should do (see RFC 9110).
i think we should have two individual api to handle the update and create.
"It depends". HTTP really wants you to send request that change documents to the documents that are changed (see RFC 9111). A way to think about it is that your HTTP request handlers are really just a facade that is supposed to make your service look like a general purpose document store (aka a web site).
Using the same resource identifier whether saving a new document or saving a revised document is a pretty normal thing to do.
It's absolutely what you would want to be doing with PUT semantics and an anemic document store.
POST can be a little bit weird, because the target URI for the request is not necessarily the same as the URI for the document that will be created (ie, in resource models where the server, rather than the client, is responsible for choosing the resource identifier). A common example would be to store new documents by sending a request to a collection resource, that updates itself and selects an identifier for the new item resource that you are creating.
(Note: sending requests that update an item to the collection is a weird choice.)
I found in my job that people are designing a RESTs API that has endpoints that return a single Json object (not a collection) based in query params (not path param).
For example:
/users?name=John&surname=Sparrow
with response body
{id:10, name="John", surname="Sparrow", gender="male"}
But what response code corresponds in REST API to not finding a resource due to query params?
For example:
/users?name=John&surname=Smith
(when John Smith doesn't exist).
I don't think it is a 404 error because /users endpoint exists, but I don't know if I must return a 400 error or a 200 without body (or null value) or other kind of response
Can you help me?
Thanks
What is most appropriate depends on whether an empty result list is OK or a clear failure. Whether parameters are PathParams or QueryParams has no bearing on return codes.
My general approach is that search functions such as findStuffBySearchTerms always return a successful HTTP code such as 200 and either the results or an empty list. On the other hand, fetchStuffById where I expect the entity to be found will return HTTP 404 if it is not found.
What response code corresponds in REST API to not finding a resource due to query params?
404 Not Found.
I don't think it is a 404 error because /users endpoint exists,
The resource identifier includes the query params. Which is to say, the query parameters are part of the identifier in precisely the same sense that path segments are part of the identifier.
In your request body, you can describe the circumstances of your implementation as precisely as you like.
But the audience of HTTP status codes includes general purpose components (browsers, proxies, web crawlers), for whom the response code is the primary mechanism for describing the semantics of the response:
The status-code element is a 3-digit integer code describing the result of the server's attempt to understand and satisfy the client's corresponding request. The rest of the response message is to be interpreted in light of the semantics defined for that status code. -- RFC 7230
That said, your server owns its own resources, and therefore you get to decide whether or not a resource exists, and what it's current representation looks like.
GET /users?name=Dave HTTP/1.1
200 OK
Content-Type: text/plain
Dave's not here, man.
From an HTTP/REST framing, that's a perfectly reasonable exchange; somebody asked for the latest representation of /users?name=Dave, and the latest representation is a plain text document. Absolutely fine.
The key idea here is that that HTTP status-code is metadata of the transfer of documents over a network domain.
HTTP is indifferent to the semantic meaning of the representations of resources.
That said, you should be considering in your design concerns like "what does this look like in our access logs?" If you want your operators to be able to distinguish this case from the similar case where the query parameters match information in your database, 200 vs 404 is the natural way to do that.
You'll normally prefer 404 to the other error status codes for this case because 404 indicates the response is cacheable, which is probably want you want when you are passed a request-target that has a spelling error in it somewhere.
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.
hello I have the following question, I have started to study about the API and RESTful
I hope you can help me.
The Get methods are normally sent via the uri, for example
http: // example / login? name = Xxxx
but each method must maintain the standard of doing what the method indicates.
POST update
PUT insert
GET get
DELEATE delete
but if I have to do a Get but the data is very sensitive to travel in the uri. what should I do? Change it for a Post method so that it travels in the body?
I understand that it has security terms like jwt, but in those cases, what should be done?
I have to do a Get but the data is very sensitive to travel in the uri. what should I do? Change it for a Post method so that it travels in the body?
Yes, that's exactly right.
In theory, there's no reason that we couldn't have an HTTP method that is effectively read only and has a method body; but as of 2020-09 the only registered methods that fit the bill are SEARCH and REPORT, which both have WebDAV semantics that you likely want to avoid.
In the absence of a standard method with the semantics that you need, it is okay to use POST.
One way of thinking about this, is that we are using POST to create a new resource using the contents of the request as arguments; the new resource would have its own identifier which obscures the sensitive data. Then you could use the new identifier to GET the latest representation of the resource any time you wanted.
To that basic idea, we add the idea of returning the representation of the new resource when we create it, and treating that resource as an ephemeral thing that you don't need to store because it "goes away" immediately after use (meaning that subsequent attempts to fetch the representation would 404).
So you might end up with a response that looks like
201 Created
Location: /random-url-that-has-no-sensitive-information
Content-Location: /random-url-that-has-no-sensitive-information
Cache-Control: no-cache
....
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.