how to make a get body travel method? - api

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
....

Related

Restful api - Is it a good practice, for the same upsert api, return different HttpStatusCode based on action

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.)

With REST, do you use a body or query params when creating a Resource?

I'm working on a digital media library where users can create entries for a Media resource.
The media resource is made up of tons of properties, eg:
Media:{
id,
name,
type,
private,
}
the url users use to create a resource is
POST api/media
On the backend, we are creating the resource with a UID generated for them while defaulting name, type and private values. However, users can pass in name, type, private if they choose to.
RFC 4.3.3 doesn't seem to have an opinion on whether or not to use params or post body for these data.
So is it better to do this
api/media?type="audio"&name="Hopkins County Collective"&private=false
or with a body instead?
api/media
body{
name:
type:
private:
}
Althought after reading section 4.3.3 for POST here https://www.rfc-editor.org/rfc/rfc7231#section-4.3.3 and I see this piece
Providing a block of data, such as the fields entered into an HTML
form, to a data-handling process;
I'm leaning toward the post fields in the body but I'm still unsure.
Thanks
do you use a body or query params when creating a Resource?
The Body. But it can be more complicated than that.
HTTP gives us standardized message semantics - we all agree, by adopting the common standard, what a given message means. That doesn't necessarily constraint what we do with the message when we get it.
For example.
PUT /id=1 HTTP/?.?
Content-Type: text/plain
id=2
That message means that we want the resource identified by /id=1 to have the representation id=2. In other words, this is the future behavior intended by the client
GET /id=1 HTTP/?.?
200 OK
Content-Location: /id=1
Content-Type: text/plain
id=2
So the body describes what we want the representation to be, and the effective-uri identifies which document we are talking about.
The same basic pattern holds for POST and PATCH - the effective-uri tells us which resource we want to change, the body describes that change.
BUT...
You the server aren't actually required to do what the request asks you to do. You can reject the request (4xx), or you can do something similar to the request, and tell the client about that.
So you might, as part of the implementation hidden behind your REST facade, copy information from the effective-uri in addition to, or instead of, exactly applying the instructions provided by the client in the body of the request. (You have to be a little bit careful with the response metadata to ensure there's no ambiguity about what you did do).
Anecdotally, "just about everyone" seems to be using the body to represent what they want the created resource to look like, be, or contain.
Parameters are often not likely to be used at all, and if they are, only for, perhaps, controlling aspects of how that resource is to be created, not anything having to do with what the resource is to look like, be, or contain.
I say anecdotal, because I'm sure there are exceptions to this -- you're even contemplating it. That said, REST does not specifically say anything about parameters vs. body.
For the sake of conformity, and for the sake of "doing it like everyone else", go with body.
There are other considerations pointing away from parameters: 1) they are part of the URI, and URIs are used for identification purposes, 2) the query string length is highly constrained, so would prevent creating large objects, and 3) it would be a diagnostics/debugging nightmare parsing the query string in your head trying to make sense of it.

How do I design a REST call that is just a data transformation?

I am designing my first REST API.
Suppose I have a (SOAP) web service that takes MyData1 and returns MyData2.
It is a pure function with no side effects, for example:
MyData2 myData2 = transform(MyData myData);
transform() does not change the state of the server. My question is, what REST call do I use? MyData can be large, so I will need to put it in the body of the request, so POST seems required. However, POST seems to be used only to change the server state and not return anything, which transform() is not doing. So POST might not be correct? Is there a specific REST technique to use for pure functions that take and return something, or should I just use POST, unload the response body, and not worry about it?
I think POST is the way to go here, because of the sheer fact that you need to pass data in the body. The GET method is used when you need to retrieve information (in the form of an entity), identified by the Request-URI. In short, that means that when processing a GET request, a server is only required to examine the Request-URI and Host header field, and nothing else.
See the pertinent section of the HTTP specification for details.
It is okay to use POST
POST serves many useful purposes in HTTP, including the general purpose of “this action isn’t worth standardizing.”
It's not a great answer, but it's the right answer. The real issue here is that HTTP, which is a protocol for the transfer of documents over a network, isn't a great fit for document transformation.
If you imagine this idea on the web, how would it work? well, you'd click of a bunch of links to get to some web form, and that web form would allow you to specify the source data (including perhaps attaching a file), and then submitting the form would send everything to the server, and you'd get the transformed representation back as the response.
But - because of the payload, you would end up using POST, which means that general purpose components wouldn't have the data available to tell them that the request was safe.
You could look into the WebDav specifications to see if SEARCH or REPORT is a satisfactory fit -- every time I've looked into them for myself I've decided against using them (no, I don't want an HTTP file server).

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.

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