Can you please confirm if below implementation for PUT vs POST defies REST principle:
If a resource was created via POST, allow update to the resource via POST (else return 412 error)
If the resource was created via PUT, allow update to resource via PUT (else return 412 error)
I understand both PUT and POST can be used to create a resource. What I think is not right in this case is dependency on how resource was created (PUT/ POST) and takes action based on it. Can you point me to the RFC?
If a resource was created via POST, allow update to the resource via POST (else return 412 error)
If the resource was created via PUT, allow update to resource via PUT (else return 412 error)
Can you please confirm if below implementation for PUT vs POST defies REST principle
It's probably wrong, but not necessarily so.
In particular, PUT in HTTP has very specific semantics
The PUT method requests that the state of the target resource be created or replaced with the state defined by the representation enclosed in the request message payload.
In other words, PUT is appropriate for replace, but it is not appropriate for modify.
So what your guideline is actually implying is that if you create a resource via a PUT of its representation, then all subsequent changes to that resource must also be complete replacements.
It's not obvious to me that's a good idea, and there is nothing in HTTP that requires you to be so strict; but it's certainly possible that your guideline authors had some bad experiences, which may be specific to the circumstances in which those guidelines apply.
The notes about using 412 response is... odd. Again, in HTTP, 412 has a very specific meaning; and that meaning is not related to the method used in the request. Using a conditional request to ensure that your edit doesn't conflict with another is good idea.
But if somebody has done a POST where they should do a PUT, or vice versa, then the correct status code to return in that case is 405.
The 405 (Method Not Allowed) status code indicates that the method received in the request-line is known by the origin server but not supported by the target resource. The origin server MUST generate an Allow header field in a 405 response containing a list of the target resource's currently supported methods.
Can you point me to the RFC?
There is no "RFC" for REST; it's not a standard, in that sense. REST is just a set of architectural constraints discovered by Roy T. Fielding during the early web standardization process. The appropriate reference is Chapter 5 of Fielding's thesis.
HTTP as a standard does (for the most part) use an architecture that satisfies the REST constraints. As of late 2016, the standard is documented by RFCs 7230-7235 inclusive.
A RESTful URL typically points to either a collection or an element.
A collection is typically denoted in plural and could look like this:
https://www.example.com/api/v1/cars
An element is typically adressed with its identifier and could look like this:
https://www.example.com/api/v1/cars/17
Collections can be children to elements:
<code>https://www.example.com/api/v1/workplaces/22/rooms</code>
Doing a POST to a collection usually means creating an element in the collection and the new element is typically returned with the response. The server would be responsible for creating the URI for the newly created element. It is the recommended "RESTful" way of creating elements.
Doing a POST to a element is not often used (and discouraged) as that would mean the client would be the one assigning the identifier. If used, most often, it means that you treat the element as a collection in itself and create a new element within it.
Doing a PUT to a collection is perfectly valid "RESTfulness" but would typically mean replacing the entire collection.
Doing a PUT to an element is common and typically means replacing the entire element, meaning that the entire element should be passed along in the request body. Some argue it is fine for the element to be created if it does not exist (but I would argue it being a bad request).
Doing a PATCH to an element typically means updating the element. The fields that should be updated are the only fields necessary in the request body.
I've never stumbled on doing a PATCH to a collection and would probably recommend against it.
Related
I have a resource Car which have some required fields and another optional ones.
The Car was created with the following request:
POST /cars
{
plate: "XYZ-A2C4",
color: "blue,
owner: "John" //OPTIONAL
}
A REST client wants to update all required info of this car:
PUT /cars/:id
{
plate: "ABC-1234",
color: "black"
}
What happen to the owner optional field?
It will be removed, since it was not informed? ie: PUT must replace the entire resource with the representation passed in the payload ?
Or, since owner is not required, the server may preserve the old value?
I know that the server can provide a PATCH method, but sometimes it is not possible to update a single field because the new state could become invalid (there are no minimum required payload to enforce related fields values). Also, manipulating arrays, removing fields or setting it with null can be tricky in some cases with PATCH since it can be done with two different patterns; JSON Merge Patch is limited and JSON Patch is kinda strange.
Is it OK to perform a PUT with the required fields and the server preserves the old optional values when it is omitted?
If you want to go by the book (being section 4.3.4 of RFC 7231), then yes, the PUT request should, in your case, replace the entire Car resource:
The PUT method requests that the state of the target resource be created or replaced with the state defined by the representation enclosed in the request message payload. A successful PUT of a given representation would suggest that a subsequent GET on that same target resource will result in an equivalent representation being sent in a 200 (OK) response.
So, by the book, you should not use PUT for partial updates, but rather PATCH.
However, in practice, it is really up to you to decide how exactly this is applicable to your service, and more importantly, to document it.
Here are a few real-world examples of how some well-known APIs allow partial updates:
The Ghost API does not support partial resource update, it requires a PUT request with a full resource for any update
The Rossum API supports PATCH for partial resource update, but their documentation explicitly states that only top-level properties are supported
GitHub allows both PATCH and POST requests for partial data updates
Firebase allows PATCH requests but also POST with an X-HTTP-Method-Override header
You are exactly right that sometimes, a PATCH method could result in an invalid resource if processes as-is. However nothing prevents the server from ensuring proper data state as a side-effect. Therefore, during each call you can have the server:
verify the proper state of the resource before persisting it
reject (with a 400 Bad Request error) any request that would result in improper state
respond with the resource (maybe bearing side-effects) on success
Strictly speaking PUT should replace the resource being identified with the entity that is being supplied. In your example, that would mean car would be replaced without the optional field unless the optional field was also supplied in the PUT request.
The number of APIs that strictly adhere to REST or a resource oriented architecture are pretty few and far between, so I personally would try not to sweat this level of detail and just document your api and the behavior that your users can expect.
If you really want to be fanatical about it, I think you're on the right track with PATCH, or you could identify a sub-resource:
PUT /cars/:id/plate
"ABC-1234"
PUT /cars/:id/color
"black
OR perhaps:
PUT /cars/:id/description
{
plate: "ABC-1234",
color: "black"
}
The www-tag mailing list archives include this interesting observation from Roy Fielding in 2002:
HTTP does not attempt to require the results of a GET to be safe. What it does is require that the semantics of the operation be safe, and therefore it is a fault of the implementation, not the interface or the user of that interface, if anything happens as a result that causes loss of property (money, BTW, is considered property for the sake of this definition).
The specification for HTTP PUT should be understood the same way; the specification tells us what the messages mean, but not how to do it.
The PUT method requests that the state of the target resource be created or replaced with the state defined by the representation enclosed in the request message payload.
PUT semantics are fundamentally "remote authoring"; the request tells the server to make its copy of a resource look like a clients copy.
So when you leave an "optional" element out of the representation provided in the request, you are telling the server to remove that optional element from its own representation as well.
It's the responsibility of the client to create a message that describes what the actually wants. So if you the client intend that the optional fields are unchanged after your request, you need to include them in the representation that you include in the body of the request.
The server is expected to interpret the PUT request as described; but it is not constrained in what it does with such a thing (subject to Fielding's observation above: which way does the blame finger point when things go wrong?)
HTTP does not define exactly how a PUT method affects the state of an origin server beyond what can be expressed by the intent of the user agent request and the semantics of the origin server response.
What happen to the owner optional field?
So in your specific example, the request clearly says "do not include the owner element". But the server is allowed to ignore that; it need only be careful in crafting its response not to imply that the provided representation was stored unchanged.
I have a REST API with a PUT endpoint which looks like this:
api.website.net/resources/resourceId
The controller implementation of this endpoint looks like follows:
#RequestMapping("/resources/{resourceId}")
public Resource putResource(#PathVariable(value = "resourceId") String resourceId, #RequestBody(required = false) Resource resource)
There is the case where a user may perform a PUT on this resource, but neglect to provide an object in the body (i.e. resource == null is true).
Which of the following approaches is more RESTful?
Have a PUT on this endpoint simply return the existing Resource object with no changes, or
Make the object required in the request body?
Note that the object exists at the given URL in both cases.
From my interpretation of the definition of PUT, it would be more RESTful to require a body because the definition seems to imply an entity exists:
From https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html
9.6 PUT
The PUT method requests that the enclosed entity be stored under the
supplied Request-URI.
The part which says "the enclosed entity" to me implies an entity actually exists.
I think if you PUT nothing, it would end up being the same as a DELETE. This just makes me think even more that a body should be required for PUT and DELETE should be used for that functionality.
All this being said, it is certainly possible to implement something which accepts PUT requests with no body, though as I said I don't think this would be RESTful.
There is some discussion about this topic here: Is an HTTP PUT request required to include a body?
There is the case where a user may perform a PUT on this resource, but neglect to provide an object in the body (i.e. resource == null is true).
Intriguing.
The PUT method is mentioned in appendix D of the HTTP/1.0 spec, was included in the HTTP/1.1 specification, and is currently defined within the content and semantics chapter of the 2014 HTTP/1.1 spec.
Its use case lineage is page publishing, taking the representation embedded within the request and writing it into the servers own store.
A PUT request, with no payload, is analogous to a request that you upsert an empty file into a specific location. That's a perfectly reasonable thing for a file system or a key value store to do.
Which of the following approaches is more RESTful?
The applicable constraint of REST is the uniform interface - PUT on this resource should have the same semantics as PUT everywhere else on the web. So it's important that PUT handling is idempotent, and that a successful PUT creates/replaces the state of the resource with the state defined by the representation in the request.
Have a PUT on this endpoint simply return the existing Resource object with no changes
Make the object required in the request body?
The second of these, I think, is closer to what you want. You can't force the client to send you a valid representation of your resource, but you can reject any request that doesn't provide a valid representation. So if you find that the provided representation isn't satisfactory, you should be thinking in terms of 400 Bad Request or 409 Conflict.
Note: when sending a 4xx response, you are normally sending a representation of the problem, rather than a representation of the resource.
Except when responding to a HEAD request, the server SHOULD send a representation containing an explanation of the error situation, and whether it is a temporary or permanent condition.
Returning a copy of the current state of the resource isn't useful for telling the client what went wrong.
I have a REST service.
And now I need to have functionality to move some child resources from one parent to another, for example move a book from one author to another.
My variant is:
POST /api/books/x/moveto/y
But how to create such architect the RESTful way?
From a REST point of view, URLs should be used to locate the resources rather than expressing operations. To express operations, the existing HTTP verbs should be used.
Looks like your "move" operation is all about replacing the author of the book.
And the PUT method seems to be the way to go:
4.3.4. PUT
The PUT method requests that the state of the target resource be
created or replaced with the state defined by the representation
enclosed in the request message payload. [...]
So, you can have an endpoint like the following:
PUT /api/books/{bookId}/author
And the request payload will contain a representation of the new author.
I think in this case updating the author as suggested in Cassio's answer is a good solution. For less obvious "actions" I use PATCH endpoints. Consider archiving a book:
PATCH /api/books/{bookId}/archive
The intent is obvious -- archive the book with this identifier. For more complex actions, include a body or use a query string parameter. For instance, moving a book out of one category and into another (assume a book can have 0-many categories):
PATCH /api/books/{bookId}/move
{
fromCategoryId: 100,
toCategoryId: 200
}
Or:
PATCH /api/books/{bookId}/move?fromCategoryId=100&toCategoryId=200
In the end, IMO, what matters most is readability and consistency. There is not necessarily a "right" way to do this sort of thing.
I have a design question on REST. I need to expose a validate method as a rest resource. Let us say it looks like this
public ValidatedResult validate(ObjectToBeValidated object)
ObjectToBeValidated is a class that contains the actual Object and also some parameters concerning the validation.
When I design this as a Restful resource, which action do I use? From my understanding GET is the action that best suits this case. If that is so, how I can pass my ObjectTobeValidated as an object but not as URL parameters? I shy away from URL parameters because ObjectToBeValidated may contain a lot of properties, ending up with an URL like below which is feel is too long
http://localhost/rest/validate?prop1=somevalu&prop2=somevalue&prop3=something&prop11=somevalu&prop22=somevalue&prop33=something
Any help would be appreciated
Thanks
Kay
The HTTP standard allows you to use the POST method. It does not necessary need to have a side effect.
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.
HTTP 1.1 / method definitions / POST
In your case you can do something like this if you want to follow the noun-verb approach Tim suggested:
POST /api/my/object/validator
Be aware that by REST the messages must be self-descriptive, so either you need a vendor MIME type or you need to add meta-data e.g. RDF to describe what this link does and what params are allowed. Otherwise we are not talking about REST, just a regular webapp.
I am creating a new REST service.
What is the standard for passing parameters to REST services. From different REST implementations in Java, you can configure parameters as part of the path or as request parameters. For example,
Path parameters
http://www.rest.services.com/item/b
Request parameters
http://www.rest.services.com/get?item=b
Does anyone know what the advantages/disadvantages for each method of passing parameters. It seems that passing the parameters as part of the path seems to coincide better with the notion of the REST protocol. That is, a single location signifies a unique response, correct?
Paths tend to be cached, parameters tend to not be, as a general rule.
So...
GET /customers/bob
vs
GET /customers?name=bob
The first is more likely to be cached (assuming proper headers, etc.) whereas the latter is likely not to be cached.
tl;dr: You might want both.
Item #42 exists:
GET /items/42
Accept: application/vnd.foo.item+json
--> 200 OK
{
"id": 42,
"bar": "baz"
}
GET /items?id=42
Accept: application/vnd.foo.item-list+json
--> 200 OK
[
{
"id": 42,
"bar": "baz"
}
]
Item #99 doesn't exist:
GET /items/99
Accept: application/vnd.foo.item+json
--> 404 Not Found
GET /items?id=99
Accept: application/vnd.foo.item-list+json
--> 200 OK
[
]
Explanations & comments
/items/{id} returns an item while /items?id={id} returns an item-list.
Even if there is only a single element in a filtered item-list, a list of a single element is still returned for consistency (as opposed to the element itself).
It just so happens that id is a unique property. If we were to filter on other properties, this would still work in exactly the same way.
Elements of a collection resource can only be named using unique properties (e.g. keys as a subresource of the collection) for obvious reasons (they're normal resources and URIs uniquely identify resources).
If the element is not found when using a filter, the response is still OK and still contains a list (albeit empty). Just because we're requesting a filtered list containing an item that doesn't exist doesn't mean the list itself doesn't exist.
Because they're so different and independently useful, you might want both. The client will want to differentiate between all cases (e.g. whether the list is empty or the list itself doesn't exist, in which case you should return a 404 for /items?...).
Disclaimer: This approach is by no means "standard". It makes so much sense to me though that I felt like sharing.
PS: Naming the item collection "get" is a code smell; prefer "items" or similar.
Your second example of "request parameters" is not correct because "get" is included as part of the path. GET is the request type, it should not be part of the path.
There are 4 main types of requests:
GET
PUT
POST
DELETE
GET requests should always be able to be completed without any information in the request body. Additionally, GET requests should be "safe", meaning that no significant data is modified by the request.
Besides the caching concern mentioned above, parameters in the URL path would tend to be required and/or expected because they are also part of your routing, whereas parameters passed in the query string are more variable and don't affect which part of your application the request is routed to. Although could potentially also pass a variable length set of parameters through the url:
GET somedomain.com/states/Virginia,California,Mississippi/
A good book to read as a primer on this topic is "Restful Web Services". Though I will warn you to be prepared to skim over some redundant information.
I think it depends. One URL for one resource. If you want to receive that resource in a slightly different way, give it a query string. But for a value that would deliver a different resource, put it in the path.
So in your example, the variable's value is directly related to the resource being returned. So it makes more sense in the path.
The first variation is a little cleaner, and allows you to reserve the request parameters for things like sort order and page, as in
http://www.rest.services.com/items/b?sort=ascending;page=6
This is a great fundamental question. I've recently come to the conclusion to stay away from using path parameters. They lead to ambiguous resource resolution. The URL is a basically the 'method name' of a piece of code running somewhere on a server. I prefer not to mix variable names with method names. The name of your method is apparently 'customer' (which IMHO is a rotten name for a method but REST folks love this pattern). The parameter you're passing to this method is the name of the customer. A query parameter works well for that, and this resource and query-parameter value can even be cached if desired.
There is no physical IT customer resource. There is likely no file on disk under a customer folder that's named after the customer. This is a web-service that performs some kind of database transaction. The 'resource' is your service, not the customer.
This obsession over REST and web-verbs reminds me of the early days of Object Oriented programming where we attempted to cram our code into virtual representations of physical objects. Then we realized that objects are usually virtual concepts in a system. OO is still useful when done the right way. REST is also useful if you realize that RESTful resources are services, not objects.