in REST what method to use for the sync operation - api

Synchronizing data once user gets online involves both Insert and Update (Upsert) and I'm sending both kinds of records in a single request (array) and then server iterates through records to determine insert or update.
My question is whether to use POST or PUT?
Also how a response from the server (JSON) should like in it's body? the data sent is an array, for example
{
"ids" : "15,16,17",
"success" : true
}
Edit:
And what should be the response code, it has both create and update operations:
200 OK
201 Created

REST is not CRUD. Mapping HTTP methods to CRUD operations is a convention introduced by some frameworks, but it has nothing to do with REST. Read this answer for some clarification on that.
A PUT is a complete replacement that ignores the current state of the resource. Think of the mv command in a shell. If there's nothing on the destination, it creates it. If there's something, it replaces completely, ignoring whatever is in there. That's how a PUT should work. Ideally, your application should have an uniform implementation of PUT that works in the exact same way with any URI that supports the method..
A POST submits the payload to be processed by the target resource under predefined rules. This means you can use POST for any operation that isn't already standardized by the HTTP protocol.
In your case, it's clearly not a complete replacement, so it's not a case for PUT. Use POST.

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

What HTTP method should I use for an endpoint that updates a status field of multiple entities

I like to use the correct HTTP methods when I'm creating an API. And usually it's very straightforward. POST for creating entities, PUT for updating them, GET for retrieving etc.
But I have a use-case here where I will create an endpoint that updates the status of multiple objects given 1 identifier.
e.g.:
/api/v1/entity/update-status
But note that I mentioned multiple objects. The initial thought of my team would be to use map it as POST, but it won't actually be creating anything, plus if you were to call the same endpoint multiple times with the same identifier, nothing would change after the first time. Making it idempotent.
With this in mind, my idea was to create it as a PUT or even PATCH endpoint.
What do you smart people think?
I imagine PATCH would be the most correct way. Although if you use a PUT it would also not be incorrect.
The difference between the PUT and PATCH requests is reflected in the
way the server processes the enclosed entity to modify the resource
identified by the Request-URI. In a PUT request, the enclosed entity
is considered to be a modified version of the resource stored on the
origin server, and the client is requesting that the stored version be
replaced. With PATCH, however, the enclosed entity contains a set of
instructions describing how a resource currently residing on the
origin server should be modified to produce a new version. The PATCH
method affects the resource identified by the Request-URI, and it also
MAY have side effects on other resources; i.e., new resources may be
created, or existing ones modified, by the application of a PATCH.
Whilst it is a convention in REST APIs that POST is used to create a resource it doesn't necessarily have to be constrained to this purpose.
Referring back to the definition of POST in RFC 7231:
The POST method requests that the target resource process the representation enclosed in the request according to the resource's own specific semantics. For example, POST is used for the following functions (among others):
Providing a block of data, such as the fields entered into an HTMl form, to a data-handling process
Posting a message to a bulletin board, newsgroup, mailing list, blog, or similar group of articles;
*Creating a new resource that has yet to be identified by the origin server; and *
Appending data to a resource's existing representation(s).
Clearly creation is only one of those purposes and updating existing resources is also legitimate.
The PUT operation is not appropriate for your intended operation because again, per RFC, a PUT is supposed to replace the content of the target resource (URL). The same also applies to PATCH but, since it is intended for partial updates of the target resource you can target it to the URL of the collection.
So I think your viable options are:
POST /api/v1/entity/update-status
PATCH /api/v1/entity
Personally, I would choose to go with the PATCH as I find it semantically more pleasing but the POST is not wrong. Using PATCH doesn't gain you anything in terms of communicating an idempotency guarantee to a consumer. Per RFC 5789: "PATCH is neither safe nor idempotent" which is the same as POST.

What is a good way to handle multiple response codes for an API?

Consider a call to a REST API:
POST /employees
[{ "name":"joe", "job":"dev",
{ "name":"bob" }]
For each array element an employee would be created. However, job is a required field, so the second element is invalid and the employee cannot be created.
What is a good response for this? 201 or 422?
I saw 207, but it seems to require an XML response, and the API does not use XML. It seems strange to return XML only for this case.
For this particular use case, I am thinking that all valid elements would be used to create resources. But I'm not sure what a good response would be.
We use 400 for any field validation errors (including missing required fields), be it on a single resource, or an entire collection.
I'm not entirely sure what are you trying to do.
Process only valid parts from the payload.
Don't process the payload at all.
In order for something to happen, the entire payload should be valid, not just parts of it. So I wouldn't process only the valid parts of the payload.
I would not use any 2xx status, because that would say to the user that everything worked OK, which isn't true in this situation.
I would not return a 400 status, because the syntax of the payload is syntactically correct JSON, but semantically erroneous.
That would leave us with a 422 status, which is more appropriate in this situation, because like I previously said, you have semantic not syntactic problems.
I'd stick with #visc advice, i.e., avoid batch processing. I have to say that #Alexandru Guzinschi advice on all or nothing approach despite being reasonable is not always feasable as sometimes you will become aware of one operation failure only after having tried it.
Both respose codes 207 and 422 you mentioned are defined as HTTP extensions for WebDAV, not in the protocol itself. And it's RFC (4918) is rather obsolete (that's why the suggestion of XML for the 207 response body).
Anyway, If you want to go down this road, I want to clarify that the use of XML is optional and you could create your own JSON definition. That would be harmless if you're not trying to implement a WebDAV server,
RFC 4918
"A Multi-Status response conveys information about multiple resources
in situations where multiple status codes might be appropriate. The
default Multi-Status response body is a text/xml or application/xml
HTTP entity with a 'multistatus' root element
One approach is to have a batch handler. So, you would send a batch of operations in a single HTTP request, but they are processed as individual operations against the api on the server. So, the batch response would include the appropriate response code for each individual operation.
A batch request can also include changesets to define transactional behavior.
Your batch could also include calls to different operations as necessary.
You don't state how you are building your api. If using ASP.NET Web API, there are batch handling capabilities available out of the box.

In HTTP, does PUT and POST send data differently?

From what I know you can send JSON data via POST, but should PUT be specifically sending information in the URI or can you do both?
Thanks!
Both POST and PUT can be used for create and update operations in different situations. So what exactly is the difference between PUT and POST?
In a nutshell: use PUT if and only if you know both the URL where the resource will live, and the entirety of the contents of the resource. Otherwise, use POST.
POST is an incredibly general verb. Because it promises neither safety nor idempotence, and it has a relatively loosely-worded description in the RFC, you can use it for pretty much anything. In fact, you could make all of your requests POST requests because POST makes very few promises; it can behave like a GET, a PUT, or a DELETE if it wants to. It also can do some things that no other verb can do - it can create a new resource at a URL different from the URL in the HTTP request; and it can modify part of a resource without changing the whole thing (although the proposed but not widely-accepted PATCH method can do something similar).
PUT is a much more restrictive verb. It takes a complete resource and stores it at the given URL. If there was a resource there previously, it is replaced; if not, a new one is created. These properties support idempotence, which a naive create or update operation might not. I suspect this may be why PUT is defined the way it is; it's an idempotent operation which allows the client to send information to the server.
References:
RFC 2616 - HTTP 1.1
RFC 5789 - PATCH method for HTTP
Martin Fowler, the Richardson Maturity Model
From HTTP's point of view, the request format is the same.
You can send the request body the same way, it is just handled differently by your application code...
The POST verb is traditionally used to create a resource
The PUT verb is traditionally used to update a resource
PUT uploads a new resource on the server. If the resource already exists and is different, it is replaced; if it doesn't exist, it is created.
POST triggers an action on the server. It has side-effects and can be used to trigger an order, modify a database, post a message in a forum, or other actions.

Is it REST if I pass the following URI /apps/{id}?control=start

I'm in the process of designing a REST API for our web app.
POST > /apps > Creates an app
PUT > /apps/{id} > Updates the app
I want to start the apps.
Is this REST and if not, how can I make it more RESTful?
POST > /apps/{id}?control=start
Sun Cloud API does this: http://kenai.com/projects/suncloudapis/pages/CloudAPISpecificationResourceModels
Or is it better to:
2. PUT /apps/{id} and include a status parameter in the response Json/XML?
3. POST /apps/{id} and include a status parameter in the response Json/xml?
4. POST /apps/start?app={id}
I think the right question here is more whether the HTTP verbs are being used as intended rather than whether the application is or is not as RESTful as possible. However, these days the two concepts are pretty much the same.
The thing about PUT is that whatever you PUT you should be able to immediately GET. In other words, PUT does a wholesale replacement of the resource. If the resource stored at apps/5 is something that has a "control" attribute as part of its state, then the control=start part should be part of the representation you put. If you want to send just the new piece of the resource, you are doing a PATCH, not a PUT.
PATCH is not widely supported, so IMHO you should use a POST. POST has no requirements of safety or idempotency; generally you can do whatever you want with a POST (more or less), including patching parts of a resource. After all that is what you do when you create a new item in a collection with a POST. Updating a portion of a resource is not really much different.
Generally though you POST new data in the request body, not as query parameters. Query parameters are used mostly for GETs, because you are, well, querying. :)
Does starting an app changes it state? (to "running", for example) If it does what you're actually doing is updating the state of the resource (application). That seems like a good use for the PUT operation. Although as Ray said, if control is part of the state of the resource, the body of the PUT request should contain the state you're updating. I believe a partial update would be possible (CouchDB uses this).
On the other hand, if starting an app means creating a new resource (representing the app execution, for example), the POST method would be a great fit. You could have something like this:
POST /app/1/start
Which would result in a HTTP/1.1 201 Created. Then, to access the information on the created execution, you could use a URL like this:
GET /app/1/execution/1
To me, this would seem like a good "Restful" approach. For more information, check out this article.
PUT apps/{id}
I would PUT the app to update it's status from off to on
I like to do something like,
POST /runningapps?url=/app/1