According to the RFC Put is used to update an existing resource.
But, the Stripe API uses Post to update objects. Why is this?
For example, in the Stripe Node Library
update: stripeMethod({
method: 'POST',
path: '{id}',
}),
the update method calls POST
I understand that there is no Patch method since the entire resource must be sent on every call, by why is the Put HTTP Verb not used in that case?
(Unlike this example from an SO question about the Facebook API, the resource is identifiable by a single ID that is passed in the URL) eg the URL is simply /v1/customers/:id
Interesting question! From your link:
The PUT method requests that the enclosed entity be stored under the
supplied Request-URI. If the Request-URI refers to an already
existing resource, the enclosed entity SHOULD be considered as a
modified version of the one residing on the origin server. [emphasis mine]
This means you must PUT the entire resource (changes and and non-changes alike). Very few APIs are designed that way.
From the spec for POST:
The POST method is used to request that the origin server accept the
entity enclosed in the request as a new subordinate of the resource
identified by the Request-URI in the Request-Line. POST is designed
to allow a uniform method to cover the following functions:
Annotation of existing resources;
Many/most APIs have adopted POST as the way to update objects.
Some additional thoughts here: https://stackoverflow.com/a/25909372/379538
Related
Having the entity Client and a rest api for it, I can think of two restpoint PATCH methods, one from a screen that modifies just some attributes and the other from calling a webservice that register an existing client in some third party system and alter some attribute on it. The points is that both methods would have the same PATCH HTTP verb and URI path like PATCH myApp/v1/clients/12345
This is just an example but I could think of many more PATCH methods with the same URI, so in order to avoid duplications in the URIs and give some meaning URIs for this cases to the caller of this API:
Could I just add to the end of the path for registering an existing client in some third party system the next? myApp/v1/clients/12345/registerInThirdPartySystem . Is it bad? Is it not restful? Any other ideas?
Thanks
Conceptually the body of a PATCH is intended to describe how you are modifying the resource at the URI.
So if your resource at /myApp/v1/clients/12345 represents a client, then any PATCH requests on that endpoint I would expect to change the entity.
Similarly, if I did a patch request on /myApp/v1/clients/12345/registerInThirdPartySystem, I would expect the purpose of this request is to update the "registerInThirdPartySystem" resource, which is nonsensical.
The registerInThirdPartySystem to me sounds like an RPC operation, so to me the appropriate method for this would be POST.
If the different PATCH operations you are describing do change the "client" itself, you should keep the URI pointing to the "client" and differentiate the request by their media-type and/or body.
When to use RestRequest/RestResponse and when to use HttpResuest/HttpResponse?
I am learning REST in Saleforce. I know there are methods like GET, POST, PUT, PATCH, DELETE.
But having confusion in these both and can I use Http request/Http Response instead of RestRequest/Restresponse ?
RestRequest/RestResponse are custom functions that allow you to listen for outside REST API requests from Apex code. You define a #RestResource annotated class and it functions much like the built in SF Rest API (although with the logic that you define). The different HTTP methods you mention are meant to respond (at a specific path) to different types of outside requests. A REST GET method should get a record. SF already has a REST API that follows these rules. They just enable you to write the logic to get the record (in this example) yourself, should you have some custom logic you wish to implement. Here is a link to the MDN docs that describe the different HTTP methods.
An HTTP request/response is when you wish to, from inside your APEX code, make a callout to some resource outside of SF.
In other words, think of RestRequest/RestResponse as a server method and HTTP as a client method.
I have an API that will delete a resource (DELETE /resources/{resourceId})
THE above API can only tell us to delete the resource. Now I want to extend the API for other use cases like taking a backup of that resource before deleting or delete other dependant resources of this resource etc.
I want to extend the delete API to this (DELETE /resources/{resourceId}?backupBeforeDelete=true...)
Is the above-mentioned extension API good/recommended?
According to the HTTP Specification, any HTTP message can bear an optional body and/or header part, which means, that you can control in your back-end - what to do (e.g. see what your server receives and conventionally perform your operation), in case of any HTTP Method; however, if you're talking about RESTful API design, DELETE, or any other operation should refer to REST API endpoint resource, which is mapped to controller's DELETE method, and server should then perform the operation, based on the logic in your method.
DELETE /resources/{resourceId} HTTP/1.1
should be OK.
Is the above-mentioned extension API good/recommended?
Probably not.
HTTP is (among other things) an agreement about message semantics: a uniform agreement about what the messages mean.
The basic goal is that, since everybody has the same understanding about what messages mean, we can use a lot of general purpose components (browsers, reverse proxies, etc).
When we start trying to finesse the messages in non standard ways, we lose the benefits of the common interface.
As far as DELETE is concerned, your use case runs into a problem, which is that HTTP does not define a parameterized DELETE.
The usual place to put parameters in an HTTP message is within the message body. Unfortunately...
A payload within a DELETE request message has no defined semantics; sending a payload body on a DELETE request might cause some existing implementations to reject the request
In other words, you can't count on general purpose components doing the right thing here, because the request body is out of bounds.
On the other hand
DELETE /resources/{resourceId}?backupBeforeDelete=true
This has the problem that general purpose components will not recognize that /resources/{resourceId}?backupBeforeDelete=true is the same resource as /resources/{resourceId}. The identifiers for the two are different, and messages sent to one are not understood to affect the other.
The right answer, for your use case, is to change your method token; the correct standard method for what you are trying to do here is POST
POST serves many useful purposes in HTTP, including the general purpose of “this action isn’t worth standardizing.” -- Fielding, 2009
You should use the "real" URI for the resource (the same one that is used in a GET request), and stick any parameters that you need into the payload.
POST /resources/{resourceId}
backupBeforeDelete=true
Assuming you are using POST for other "not worth standardizing" actions, there will need to be enough context in the request that the server can distinguish the different use cases. On the web, we would normally collect the parameters via an HTML form, the usual answer is to include a request token in the body
POST /resources/{resourceId}
action=delete&backupBeforeDelete=true
On the other hand, if you think you are working on an action that is worth standardizing, then the right thing to do is set to defining a new method token with the semantics that you want, and pushing for adoption
MAGIC_NEW_DELETE /resources/{resourceId}
backupBeforeDelete=true
This is, after all, where PATCH comes from; Dusseault et al recognized that patch semantics could be useful for all resources, created a document that described the semantics that they wanted, and shepherded that document through the standardization process.
This is a generic design question, but where should the responsibility fall in this situation? Should it be the caller's responsibility to check if a record already exists and then call Update? Or should it be the responsibility of the API to make that decision?
In the first scenario, the problem is that the caller is burdened with the business logic, but in the second scenario, the logic pollutes the API and creates hybrid behavior, violating the separation of concerns principle.
Implementing a CreateOrUpdate endpoint will be breaking some REST principles, but may be convenient for the application developer. You are thinking in terms for a remote function call rather than in terms of resource-oriented API.
Consider this: the API URL identifies the resource.
If the URL points to a collection (i.e. /customers/) then the Create action (typically mapped to the POST method) certainly makes sense. The Update function might makes sense, if you want allow update to multiple resources at one. The POST should return code 201 and an identifier to a newly created resource (i.e. /customers/1); or if the create failed due to resource already existing it should return code 409; 400 if some other constraints like data validation are not met.
If the URL points to an existing resource (i.e. /customers/id/1) then Create action does not make sense and should result in code 400. The update is typically mapped to the PUT method (or sometiemes PATCH, if partial resource update) and generally would return 200 if the update was successful or 4xx series if not.
If you choose to create a /CreateOrUpdate endpoint, which takes POST requests you will have to design your own protocol around it because its behavior and return values will be different depending on circumstance.
#Evert the PUT can be used for create but only when you require client to formulate the endpoint URI with the identifier i.e.
PUT /users/myusername
Problems with that are:
the client must discover an available one,
if a natural identifier is used, there may also exist a natural reason for changing it, which depending on the implementation may be problematic
The main point I am making is to avoid creating REST API endpoints, which represent an action (function). Instead use HTTP methods to effect respective actions on persisted resources.
Assume i've read a lot about versioning a restful api, and I decided to not version the the service through the uri, but using mediatypes (format and schema in the request accept header):
What would be the best way to implement a wcf service or a web api service to serve requests defining the requested resource in the uri, the format (eg. application/json) and the schema/version (eg player-v2) in the accept header?
WCF allows me to route based on the uri, but not based on headers. So I cannot route properly.
Web Api allows me to define custom mediatypeformatters, routing for the requested format, but not the schema (eg. return type PlayerV1 or PlayerV2).
I would like to implement a service(either with WCF or Web Api) which, for this request (Pseudo code):
api.myservice.com/players/123 Accept format=application/json; schema=player-v1
returns a PlayerV1 entity, in json format
and for this request:
api.myservice.com/players/123 Accept format=application/json; schema=player-v2
returns a PlayerV2 entity, in json format.
Any tips on how to implement this?
EDIT: To clarify why I want to use content negotiation to deal with versions, see here: REST API Design: Put the “Type” in “Content-Type”.
What you are bringing here does not look to me as versioning but it is is more of content negotiation. Accept header expresses wishes of the client on the format of the resource. Server should grant the wishes or return 406. So if we need more of a concept of Contract (although Web API unline RPC does not define one) then using resource is more solid.
The best practices for versioning have yet to be discussed fully but most REST enthusiast believe using the version in the URL is the way to go (e.g. http://server/api/1.0.3/...). This also makes more sense to me since in your approach using content negotiation server has to keep backward compatibility and I can only imagine the code at the server will get more and more complex. With using URL approach, you can make a clean break: old clients can happily use previous while new clients can enjoy the benefits of new API.
UPDATE
OK, now the question has changed to "Implementing content-negotiation in a RESTful AP".
Type 1: Controller-oblivious
Basically, if content negotiation involves only the format of the resource, implementing or using the right media type formatter is enough. For example, if content negotiation involves returning JSON or XML. In these cases, controller is oblivious to content negotiations.
Type 2: Controller-aware
Controller needs to be aware of the request negotiation. In this case, parameters from the request needs to be extracted from the request and passed in as parameter. For example, let's imagine this action on a controller:
public Player Get(string schemaVersion)
{
...
}
In this case, I would use classic MVC style value providers (See Brad Wilson's post on ValueProviders - this is on MVC but Web API's value provider looks similar):
public Player Get([ValueProvider(typeof(RequestHeadersSchemaValueProviderFactory))]string schemaVersion)
{
...
}