Sending application specific messages - rest

There is a change to our business logic, where earlier with one of the APIs we use to return a list, for eg. list of employees. Recently we introduced authorization checks, to see if a particular user has permission to view a specific employee.
If say there are 10 employees that should be returned through method GET, due to the missing permission only 5 are returned. The request itself in this case is successful. I am currently not sure how to pass on the information back to the client that there were 5 employees that are filtered out due to missing permission.
Should this be mapped to HTTP status codes? If yes, which status code fits this? Or this is not an error at all?
What would be the best approach in this case?

A status code by itself wouldn't be sufficient to indicate the partial response. The status code 206 sounds close by name but is used when a client specifically requests a partial set of data based on headers.
Use 200. The request was fulfilled successfully after all, and the reason for the smaller set of data is proprietary to your API so extra metadata in the response to indicate a message might be sufficient.
Assuming JSON response:
{
"data": [ ... ],
"messages": [
"Only some data was returned due to permissions."
]
}
If you have many consumers and are worried about backward compatibility you may also want to provide a vendor specific versioned JSON media type:
"Content-Type": "application/vnd.myorg-v2+json"

Related

Which http status code should be returned when the identifier in the payload does not exist?

I've the endpoint POST /permission-period which should create a permission period for a specific user.
The payload:
{
"userId": 10,
"permissionPeriodDateFrom": "2017-12-01",
"permissionPeriodDateTo": "2017-12-10"
}
If any property from the payload is invalid, i usually return 422 Unprocessable Entity, which means the syntax of the request payload is valid but it cannot be processed due to invalid data.
What status should I return if the user does not exist and I do not want to provide the client with this security related information? Should i expose the message that the user does not exist or not?
I think HTTP status code wise I would choose a 400 - Bad request. Regarding the returned error message I would give the user a helpful information while keeping security-related information secret.
You could return something like The given userId is either malformed, does not exist or cannot be linked to the posted resource. This would allow the user to identify the spot where in the body the error comes up (property userId) but does not tell him the exact error to prevent user enumeration.
The good news is that you obviously have a protected endpoint when creating a permission-period so the API user is identifiable and you can take other actions for preventing user enumeration and related brute force attacks such as consumer-based throttling or locking the API consumer after x attempts.
I hope my notes help you with your API design.

Correct (RESTful) HTTP Method for handing mixed / batch requests

I have an application that needs to send multiple (change) requests to the server at a time. These requests are being sent in a batch, represented by a JSON object. The requests can be of any (change) type (e.g. creations, updates, deletions).
the JSON looks something like this:
[
{ "delete": { "id": "to delete" } },
{ "update": { "id": "to update", "data": {} } },
{ "create": { "data": {} } },
...
]
My question is simple:
If I was sending these over to the server one at a time, I'd use DELETE, PUT or POST depending on the nature of the operation, but since I'm sending over a batch potentially containing all three types of requests, I'm not sure which method is most appropriate (aside from DELETE).
Which is the correct HTTP Method to use in this instance?
Thanks.
The correct method to use is a POST method since you are creating a batch-process resource. In addition, you should respond with a 202 Accepted status code which indicates "The request has been accepted for processing, but the processing has not been completed." (RFC 2616)
I hope this helps!
UPDATE:
This should definitely be a POST method because this request IS NOT idempotent. Before you continue, please see What is idempotency in HTTP methods? and Is REST DELETE really idempotent?.
If this request is made multiple times, it may have n number of side-effects (because it creates resources)!
I retracted my PUT recommendation comment because I misspoke—PUT should be idempotent.
Well, AFAIK, there is no such method to do so. You can use just the json as in your post with a new POST request.
This new request will parse the data sent and call delete method on delete related data, put on put related data, and so on.
If I was sending these over to the server one at a time, I'd use DELETE, PUT or POST depending on the nature of the operation, but since I'm sending over a batch potentially containing all three types of requests, I'm not sure which method is most appropriate (aside from DELETE).
Which is the correct HTTP Method to use in this instance?
"It depends".
The key point is this: http semantics apply to resources, which live in the integration domain. The fact that these representations you are sending impact the domain model in interesting ways isn't relevant.
The method you choose should have unsafe semantics, since you are encouraging the origin server to change. You also need a method where the message body is meaningful. Of the methods defined within the HTTP spec, you have PUT and POST -- either of these is fine. PATCH may also be suitable, depending on whether or not you can make this collection of changes atomically.
Example: suppose what we are really doing is taking the body of the message, and sticking it into a queue to be handled "later". The REST part is taking that implementation, and dressing it up with an HTTP disguise.
Either PUT or POST is perfectly fine for that. Using POST to add something to a queue should not be a big surprise. PUT is analogous to inserting the message into a key value store.
HTTP is an application protocol whose application domain is "the transfer of documents over a network." -- Jim Webber
What you have at your client is a document, which happens to describe changes that you want to make in your domain model. You are using HTTP to transmit a copy of that document to the server. Does POST work for that? Yes. Does PUT work for that? also yes.
Consider this resource, which means exactly what it says on the tin
/newest-message-in-queue
Can you update that resource by sending a new representation via POST? Sure. Can you update that resource by sending a PUT? Of course. Will the side effects on the domain objects work either way? Yes.
Can the client tell the difference between this, and changing a value in a key value store? No <-- and that's the point; we're disguising our implementation behind a generic document store semantics, so that we can take advantage of off-the-shelf-ware.

What should be the response of GET for multiple requested resources with some invalid ids?

what should be the response to a request to
http://localhost:8080/users/1,2,3 when the system doesn't have a user with id 3?
When all users are present I return a 200 response code with all user objects in the response body. When the user requests a single missing user I return a 404 with an error message in the body.
However, what should be the body and status code for a mix between valid and missing ids?
I assume that you want to follow REST API principles. In order to keep clear api design you should rather use query string for filtering
http://localhost:8080/users?id=1,2,3
Then you won't have such dilemmas - you can return just only users with id contained in provided value list and 200 status code (even if list is empty). This endpoint in general
http://localhost:8080/users/{id}
should be reserved for requesting single resource (user) by providing primary key.
What you are requesting there is a collection. The request essentially reads: "give me all users whose ID is in {1, 2, 3}." A subset of those users (let's say there is no user yet with the ID 3) would still be a successful operation, which is asking for a 200 (OK).
If you are overly concerned by this, there's still the possibility to redirect the client via 303 (See Other) to a resource representation without the offending elements.
If all of the IDs are invalid, things get a bit tricky. One may be tempted to simply return a 404 (Not Found), but strictly speaking that were not correct:
The 404 status code indicates that the origin server did not find a current representation for the target resource
Indeed, there is one: The empty set. From a programmatic standpoint, it may indeed be easier to just return that instead of throwing an error. This relies on clients being able to process empty sets/documents.
The RFC grants you the freedom to go either way:
[…] the origin server did not find a current representation for the target resource or is not willing to disclose that one exists.
So if you wish to hide the existence of an empty set, it's okay. It bears mentioning that a set containing nothing is not nothing itself ;)
I would recommend not to offer the method in the first place, but rather force the user of your APIto make three separate requests and return unambiguous responses (two 200s for users 1 and 2 and 404 for user 3). Additionally, the API could offer a get method that responds with all available user ids or such (depends on your system).
Alternatively, if that's not an option, I guess, you have two options:
Return 404 as soon as one user is not found, which technically is more accurate in my opinion. I mean, the request was for 1, 2 AND 3, which was not found.
Return 200 with users 1 and 2, and null, which probably is the most useful for your scenario.

Pass complex object to delete method of REST Service

I have REST service that manage the resource EASYPAY.. In this moment this service exposes 3 different methods:
Get a EasyPay request (GET);
Insert a Easypay request (POST);
Update a Easypay request (PUT).
Whe I inserto or update a request I must insert also a row on a trace table on my database.
Now I have to delete a Easypay request and I must add also a row on the trace table.
I wanted to use the DELETE HTTP verb, but I saw that with delete I cannot pass a complex object but just the ID of the request to delete.
I cannot use the PUT HTTP verb because I have already used it, and in any case it would not be conceptually correct...
I do not want to do more that one call from client to server (one for delete the request, the other one to add a row in the trace table)..
So I do not know how to solve the problem.
EDIT
I try to explain better... I have a web site that is deployed on two different server. One for front-end and one for Back-end. Back-end expose some REST services just for front-end and it has no access to internet (just to intranet).
The customer that access the web site can do a payment via a system called XPAY and it works really similar to paypal (XPAY is just another virtual POS).
So when the customer try to do a payment, I save some information on the database + I trace the attempt of the payment, then he is redirected to XPAY. There, he can do the payment. At the endy XPAY return to the web-site (the front end) communicating us the result of the payment.
The result is in the URL of payment, so i must take all the information in the url and send them to the back-end.
According to the result, I must update (if result is ok) or delete (if result is ko) the information I saved before and write a row on the trace table.
What do you suggest?
Thank you
There are actually a couple of ways to solve your problem. First, REST is just an architectural style and not a protocol. Therefore REST does not dictate how an URI has to be made up or what parameters you pass. It only requires a unique resource identifier and probably that it should be self-descriptive, meaning that a client can take further actions based on the returned content (HATEOAS, included links even to itself and proper content type specification).
DELETE
As you want to keep a trace of the deleted resource in some other table, you can either pass data within the URI itself maybe as query parameter (even JSON can be encoded in order to be passed as query parameter) or use custom HTTP headers to pass (meta-)information to the backend.
Sending a complex object (it does not matter if it is XML or JSON) as query parameter may cause certain issues though as some HTTP frameworks limit the maximum URI size to roughly 2000 characters. So if the invoked URI exceeds this limit, the backend may have trouble to fulfill the request.
Although the hypertext transfer protocol does not define a maximum number (or size) of headers certain implementations may raise an error if the request is to large though.
POST
You of course also have the possibility to send a new temporary resource to the backend which may be used to remove the pending payment request and add a new entry to the trace table.
According to the spec:
The action performed by the POST method might not result in a resource that can be identified by a URI. In this case, either 200 (OK) or 204 (No Content) is the appropriate response status, depending on whether or not the response includes an entity that describes the result.
This makes POST request feasible for short living temporary resources which trigger some processing on the server side. This is useful if you want to design some queue-like or listener system where you place an action for execution into the system. As a POST request may contain a body, you can therefore send the POS response within the body of the POST request. This action request can then be used to remove the pending POS request and add a new entry to the trace table.
PATCH
Patch is a way a client can instruct a server to transform one or more resources from state 1 to state 2. Therefore, the client is responsible for breaking down the neccessary actions the server has to take to transform the resources to their desired state while the server tries to execute them. A client always works on a known state (which it gathered at some previous time). This allows the client to modify the current state to a desired state and therefore know the needed steps for the transition. As of its atomic requirements either all instruction succeed or none of them.
A JSON Patch for your scenario may look like this:
PATCH /path/to/resource HTTP/1.1
Host: backend.server.org
Content-lengt: 137
Content-Type: application/json-patch+json
If-Match: "abc123"
[
{ "op": "remove", "path": "/easyPayRequest/12345" }
{ "op": "add", "path": "/trace/12345", "value": [ "answer": "POSAnswerHere" ] }
]
where 12345 is the ID of the actual easypay request and POSAnswerHere should be replaced with the actual response of the POS service or what the backend furthermore expects to write as a trace.
The If-Match header in the example just gurantees that the patch request is executed on the latest known state. If in the meantime a further process changed the state (which also generates a new If-Match value) the request will fail with a 412 Precondition Failed failure.
Discussion
While DELETE may initially be the first choice, it is by far not the best solution in your situation in my opinion as this request is not really idempotent. The actual POS entity deletion is idempotent but the add of the trace is not as multiple sends of the same request will add an entry for each request (-> side-effect). This however contradicts the idempotency requirements of the DELETE operation to some degree.
POST on the otherhand is an all-purpose operation that does not guarantee idempotency (as PATCH does not gurantee either). While it is mainly used to create new resources on the server side, only the server (or the creators of that server-application) know what it actually does with the request (though this may be extended to all operations). As there are no transactional restrictions adding the trace might succeed while the deletion of the pending request entity might fail or vice versa. While this may be handled by the dev-team, the actual operation does not give any gurantees on that issue. This may be a major concern if the server is not in your own hands and thus can not be modified or checked easily.
The PATCH request, which is still in RFC, may contain therefore a bit more semantic then the POST request. It also specifies the ability to modify more then one resource per request explicitely and insist on atomicity which also requires a transaction-like handling. JSON Patch is quite intuitive and conveys a more semantics then just adding the POS response to a POST entity body.
In my opinion PATCH should therefore be prefered over POSTor DELETE.

Can a RESTful POST method be implemented to be idempotent?

I am designing a RESTful API that is managing favorites. Each favorite resource can contain details of two items that are considered as part of the favorite.
HTTP POST /favorites
{ "item1" : "ball",
"item1-ID" : "1",
"item2" : "bat",
"item2-ID" : "2"
}
Please excuse the rudimentary JSON payload. The focus is however on the semantics of the POST
The above POST method creates a new favorite resource (that contains a ball (ID 1) and a bat (ID 2))
My question is with regard to the expected behavior when the same POST request is sent twice. The first request will create a favorite (as expected). What should happen when the second request is sent?
1) Signal an error with 409
2) Signal a success with 201
1) is not idempotent (as POST is), while 2) makes POST idempotent.
Which is the correct approach?
You are thinking about this in the wrong way. If a POST creates a new resource then the resource should have a URL that identifies it (e.g., http://.../favorite/1). When the second POST with the same payload happens, is a new resource created? If so, then you have two separate resources with unique URLs. If you application does not create a new resource, then the second POST would return the same URL as the first one.
Edit
The POST section of RFC7231 does not prohibit it from being implemented in an idempotent manner. It does provide some guidance though:
If a POST creates a new resource, then it SHOULD send a 201 (Created) response containing a Location header identifying the created resource
If the result of a POST is equivalent to an existing resource, then the server MAY redirect the UA to the existing resource by returning a 303 (See Other) with the appropriate Location header
POST is not required to change the state of a resource. However, GET and HEAD are required to be idempotent. I'm not aware of any method that is required to change state on the server.
Personally, I implement resource creating POST methods as returning a 303 redirect to the canonical URL for the resource as a matter of practice. I wasn't aware of the RFC distinguishing status codes for resource creation and re-use responses. The benefit of this approach is that it removes the need to include the created resource in the POST response and the GET to the canonical URL will cache the response in any intermediate caches that may be present. It also allows for the implementation of intelligent clients that do not retrieve the response and use the canonical URL (from the Location header) instead.
In your case, I think that I would adopt the 303 approach provided that a favorite has a URL of it's own; 201 would be strange if it did not. If there is very good reason for distinguishing the creation and re-use cases in the response, then a 201 when the new resource is created and a 303 when it is reused is appropriate. What I would not do is to return a 409 unless your application requires you to deny the creation of a resource that already exists.
To me, as you pictured it, it should create a new favorite. But this feels strange for almost any application. What if:
your favorites could be defined as non-repeatable if they are exact copies
you could send an ID with the favorite (not a good idea, as it'd be client-based), and insert or update based on that
you could send some other unique field and use that to define whether it is a "create" or an "update" (ie. "favorite name" or "position in menu")
As you see, it all depends on your application.
Maybe you can get some ideas from this article I happened to write some time ago: A look into various REST APIs . Don't miss the summary at the bottom.
What should happen when the second request is sent?
It all depends on your implementation . Say if you have some logic in your controller that checks if ID 1 and ID 2 exist in the data base then update the value else create the new record.
The whole thing is not depended on POST request.
AND FYI HTTP response code for success is 200 and not 201.
Your current approach is not correct and the question is not a JAVA question
In general, it depends on you, how you want to design the underlying system. In most cases, POST creates a new resource (Yes, there are instances when you use POST and not create anything new. For example, you have a use-case where in you want to search on a very long list of the parameters and GET might not be the way!. This is completely acceptable and not a violation of REST principles.)
Commenting on your specific case,
What should happen when the second request is sent?
You should ask the following questions to yourself.
Is having a duplicate request (a request with the same payload/headers/time-stamp etc.) a "different" request for your system ? If YES - treat it normally as if it's not duplicate. I assume that the next systems to which the request is going are also understanding this as a new request, otherwise they could fail and flag error. For example, MySQL could throw Duplicate Primary Key error (Refer: Error Code: 1062. Duplicate entry 'PRIMARY')
If the answer to (1) is NO - Is the duplicate occurrence of this request an expected behaviour of the clients ? (For example, you tend to get duplicate requests from mobile if it's intermittently getting the network.) If YES - return 200 OK. Note the idempotency here.
If the answer to (2) is NO - throw 409 conflict with a custom error-code which client can handle and react accordingly. I would also investigate the unwanted behaviour of client on throwing the duplicate requests and fix it if that's doable.
Duplicate idempotent POST requests should return the previously created resource in response if the status code of the response was 200. Idempotency Enforcement Scenarios