When REST API don't follow HATEOAS style, it is often referred your REST is not truly REST.
How come we can think of every possible request from clients can map to CRUD operations?
For example if the client(mobile) would like to send a reset password link to user for a given email id, how this shall be thought of as CRUD?
Very few REST advocates will argue that that REST should be applied to everything. I'm a big proponent of REST, but there are more than a few situations where not using HATEOAS is the most pragmatic move. Your example is one of them.
However, if you want to make this work in a RESTful manner, it's totally still possible.
For example, a lost password reset link might require a one-time authentication token. This token might be represented by a resource in a collection such as:
/users/xyz/auth-tokens
And perhaps you can initiate a lost-password email operation by creating a new 'auth-token' resource in that collection using POST.
Should you? I don't know! Can you? for sure!
Creating a PasswordReset resource is easy enough.
POST /password-resets
RPC minded people struggle to switch over to REST because they're used to doing things as RPC. :)
https://www.smashingmagazine.com/2016/09/understanding-rest-and-rpc-for-http-apis/
Related
Say I'm creating a journaling application and I want users to be able to post entries to their journals.
I do not intend to ever allow a user (even a moderator) to post an entry in someone else's journal.
That said, are there any arguments for exposing the account or journal id in my endpoint path?
I would think that POST api/journals/postEntry would be sufficient as I can determine the user via access token or JWT token.
Can anyone think of arguments for providing the journalId in the path? EX: POST api/journals/{user journalId}/postEntry
Can anyone think of arguments for providing the journalId in the path? EX: POST api/journals/{user journalId}/postEntry
Short answer: it's a violation of the uniform interface constraint.
See Fielding, 2000.
What you are doing, in effect, is creating this little corner of the world where, instead of using the target-uri to identify a resource, you are instead using target-uri + token.
Which means that your thing doesn't use the semantics that the general purpose components in the world are expecting.
For example, when I copy the URI out of my user agent, and share it with someone else, that other person doesn't get the result I expect -- they end up looking at their view, not mine.
The fact that we can stick a URI in an email message and have it just work for the person reading the email is a really big piece in the adoption story.
Furthermore, the cache constraint in REST rather depends on being able to use the identifier as the primary cache key. So your bespoke identity mechanism has the potential to mess up caching.
IN PRACTICE: you are using HTTP, and HTTP has caching rules that prohibit sharing authenticated requests. So the caching issues mentioned above are purely theoretical.
Alternatives you might consider
You could arrange for /api/journals/postEntry to redirect to /api/journals/{userJournalId}/postEntry
You could use the Content-Location header to indicate that there is a more specific identifier for the current representation.
You can use the canonical link relation to help clients navigate to the preferred resource from the alternatives.
I'm currently developing a web application with a senior developer. We've agreed to use REST API for client-server communication and he sent me the parameters and the expected responses.
But the design does not seem to be RESTful. Rather it looks like JSON-RPC over http utilizing only the POST method.
For example, to register a user you send a POST request to the server the following parameters.
{
id: 1,
method: "RegisterUser",
params: {
firstName: "John",
lastName: 'Smith',
country: 'USA',
phone: "~",
email: "~",
password: "~"
}
}
And the expected response is
{
id: 1
result: "jwt-token",
error : null
}
Multiple requests are sent to the same URL and the server sends back the response based on the 'method' in the parameters. For example, to get a user info, you send a { method: "GetUserInfo", params: { id: ~ }} to the same URL. All responses have the status code 200, and the errors are handled by the error in the response body. So even if the status code is 200, if error is not null it means something is wrong.
The way I'm used to doing is sending a POST request to 'users/' with a request body when registering a new user, sending a GET request to 'users/1' to retrieve a user information, etc.
When I asked why he'd decided to do it this way, he said in his previous job, trying to add more and more APIs was a pain when following RESTful API design. Also, he said he didn't understand why RESTful API uses different HTTP verbs when all of them could be done with POST.
I tried to come up with the pros of REST API over JSON-RPC over http with POST.
GET requests are cached by the browser, but some browsers may not support POST request caching.
If we are going to open the API to outside developers, this might cause discomfort for them since this is not a typical REST API.
In what circumstance would the JSON-RPC over http style be better the REST RESTful APIs? Or does it just not matter and just a matter of preferance?
it looks like JSON-RPC over http utilizing only the POST method.
Yes, it does.
The way I'm used to doing is sending a POST request to 'users/' with a request body when registering a new user, sending a GET request to 'users/1' to retrieve a user information, etc.
That's not quite it either.
Riddle. How did you submit this question to stack overflow? Well, you probably followed a book mark you had saved, or followed a link from google. Maybe you submitted a search or two, eventually you clicked the "Ask Question", which took you to a form. After filling in the details of the form, you hit the submit button. That took you to a view of your question, that include (among other things) a link to edit the question. You weren't interested in that, so you were done -- except for refreshing the page from time to time hoping for an answer.
That's a REST api. You, the agent, follow links from one state to another, negotiating stack overflows "submit a question" protocol.
Among other things to notice: the browser didn't need to know in advance what URLs to send things to, or which http method to use, because the HTML had encoded those instructions into it. The browser just need to understand the HTML standard, so that it could understand how to find the links/forms within the representation.
Now, REST is just a set of architectural constraints, that boil down to "do it the way a web server does". You don't need to use HTML as your media type; you don't need to design for web browsers as your clients. But, to do REST, you do need hypermedia; and clients that understand that hypermedia type -- so it is going to be a lot easier for you to choose one of the standardized media types.
Are there more reasons why I should prefer RESTful API over JSON-RPC over http with POST? Or does it just not matter?
Roy Fielding, in 2008, offered this simple and correct observation
REST is intended for long-lived network-based applications that span multiple organizations. If you don’t see a need for the constraints, then don’t use them.
For instance, the folks working on GraphQL decided that the properties that the REST constraints induce weren't valuable for their use case; not nearly as valuable as being able to delivery to the client a representation tuned to a clients specific needs.
Horses for courses.
Use RESTful APIs when you are performing standard create, read, update and delete actions on resources. The CRUD actions should behave the same way for each resource, unless you have some before and after hooks. Any new developer coming to the project will easily understand your API if it follows the standards.
Use JSON-RPC when you are performing actions that don't necessarily map cleanly to any CRUD. For instance, maybe you want to retrieve counts or summary data of a specific resource collection. You could do this with REST, but it might require you to think of it as some sort of "summary" resource that you read from. It's easier to do with JSON-RPC, since you can just implement a procedure that runs the appropriate query in your database and returns an appropriate result object.
Or what if you want to make an API call that lets a user delete or update all of instances of a resource(s) that meet some condition, without knowing ahead of time what those instances are?
You can also use JSON-RPC in cases where you need to have a lot of side effects for standard CRUD actions and it's inconvenient to make hooks that run before or after each action.
You don't have to go all in with one of the other, you can use both. Have standard RESTful endpoints where appropriate and another RPC endpoint for handling JSON-RPC calls.
Use REST when you write public web services. REST is standardized and predictable, it will help consumers to write client apps. Also, GET HTTP method is widely used to retrieve resources from public web services.
Use JSON RPC when you write back-end for an application (i.e. not public web services). JSON RPC style is more flexible and more suitable for register, login, and getProductsByFilters methods. There is no reason to use GET with JSON RPC, only POST should be used.
I'm having some trouble with RPC style verbs starting to appear in my API.
My question is: Is it okay to have these verbs, "Submit", "SendForApproval", "Accept" and "Reject" in a Restful API? Is that going against the Restful principles? What's best practice for naming these Actions?
Our business case:
I have an order. It starts out at status "pre-ordered". I want to then make a call to validate the order against our business logic. Depending on the validation results, I then either submit it or send it for approval. The approval process happens externally to our solution and then when it has been through the approval process the Api is called to mark the order as either Accepted or Rejected.
There is a bit more going on than simply updating statuses - we send things to print queues, spin off tracking documents etc.
So the URI's that we have defined are
https://api.site.com/orders // A list of orders
https://api.site.com/orders/{orderId} // An order
https://api.site.com/orders/{orderId}/ValidationErrors // Get a list of validation results
https://api.site.com/orders/{orderId}/Submit // Submit the order for processing
https://api.site.com/orders/{orderId}/SendForApproval // Send to supervisor
https://api.site.com/orders/{orderId}/Accept // Supervisor Accepts the order for processing
https://api.site.com/orders/{orderId}/Reject // Supervisor can Reject the order
You must avoid inserting verbs in your URIs as much as you possibly can. Furthermore, I disagree with user1438038, because the QueryString filters should be used for search purposes instead of specifying actions.
I believe that there're better approaches to solve this problem. First off, take into account that you shouldn't model your RESTful API in a way that it's highly tied to your business objects (supposing that you're using a OO approach). Moreover, remember that in a REST perspective, everything you expose is a resource rather than objects with its state and behavior.
I'm going to suggest you a different approach but I'm not sure if it's going to fulfill your system requirements but maybe it can be useful to give you some ideas. In your case, you can have multiple resources like PreOrders, Orders, Supervisors...
https://api.site.com/preorders
GET - Display all pre-orders.
POST - Create a new pre-order.
Creating a new order:
https://api.site.com/preorders/1
POST - approves the pre-order. This action's gonna create a new Order.
Displaying all orders that are waiting for approval (by the supervisor with ID=1).
https://api.site.com/supervisors/1/orders
Searching for approved and canceled orders:
https://api.site.com/supervisors/1/orders?status=canceled
https://api.site.com/supervisors/1/orders?status=approved
To cancel or approve an order:
https://api.site.com/supervisors/1/orders/1 (DELETE cancels the order)
https://api.site.com/supervisors/1/orders/1 (POST approves the order)
I'm unsure if it's the best approach to solve your problem but I'm pretty sure it's better than using verbs in your URI.
I'd be fine with that, we are using a very similar setup for order management.
However, another possibility would be passing an action parameter, such as:
https://api.site.com/orders/{orderId}/?action=accept
https://api.site.com/orders/{orderId}/?action=reject
...
The general idea of REST is to have resources (such as order or customer). What you want is more of a RPC semantics, but there is no right or wrong. Your approach is reasonable.
Not is a good practice have verbs in REST uris.
So, if you want change a status in any order, you may send a PUT/POST to https://api.site.com/orders/{orderId} updating only the values you want for your bussines logic.
quick question - I was reading about RESTful services yesterday and someone had asked why SOAP wasn't RESTful. The answer was that SOAP doesn't have the 'generality of interfaces' property as is required by REST.
Then it struck me that I had been adding custom routes to my Web API like so:
Custom Routing with ASP.NET Web API
By doing that - I made my web API non-generic, thereby making the service non-RESTful, right? Not that that's a big deal, I just want to know whether I grasped the concepts correctly.
Well the rest rqeuires you to identify resoruces alone, not actions on them.
For example you might have an action addComment on Person, your route being
POST persons/2/addComment
This would make it non restful. The ideal way to do this would be:
POST persons/2/comments
For deleting a comment DELETE persons/2/comments/{commebntid}
So if you vary from this, your service becomes non restful. Its pretty hard to make a completely restful interface.
For example, if you have an object account, that you directly increment or decrement balance
accounts/2. You might have withdraw and deposit actions. POST accoints/2/withdraw. In rest, you need to either pass the balance as a parameter after decrementing it (PUT). There may be cases where you donot want to do this. You might not want to let the world know the balance of the user. Then you cant easily use put. You'd have to create a new entity: transaction and create transactions and calculate the account balance on the basis of transactions.
Ther eis no such thing as a generic API. You can't use amazons api and facebooks api interchangibly since the entities and operations are different. Don't worry too much about generalization. Just understand what the RESTful way is, and see if you can implemen it. If you have to tweak around it a bit, that's fine
Although I "think" I understand it I need some clarity. With PURE Restful authentication, things do get a bit unwieldy and using forms helps a lot with the UI of the application (i.e., get to have separate login page, forgot password links, easier logout? etc.,)
Now Forms come along and some folks say "not restful" - what is "not restful" about them? Is it that there is no corresponding login resource so to speak? Or does it force something else that I'm missing?
Note: If ones create sessions with them, that's a different matter altogether. I'm more keen on know "why" are they branded as restful? Just googling for "Form based authentication vs restful authentication" throws up quite a few hits.
One could use these "forms" to authenticate and pass on tokens for the application to store in cookies etc., which I feel is entirely restful (assuming cryptographic security etc.,)...
There is nothing wrong with sending your credentials, perhaps through a form, for authentication. The problem is most Form based systems rely on sessions, thus requiring you to only log in "once".
Sessions are server state, thus violating the stateless constraint of a REST architecture.
If you have to send the credentials each time, you can either include them in the payload (i.e. using a form), or you can use the HTTP Authorization header.
If you include them in the payload, you can include them in the body, but only for a POST or PUT, and not a GET or DELETE (since they don't have bodies).
If you include them in the URL as part of the query parameters, then the URL is no longer necessarily representing the actual resource. One of the other tenets is that the URL matches the resource. Adding out of band information (such as credentials) within the query parameters muddies that constraint up a bit.
So, for a REST system over HTTP, you're better to use the existing HTTP Authorization mechanism than working out something else. You could also use client specific SSL certs as well, that works fine also.
Excellent question. I think that RESTful purists will likely say that having a URI associated with an action rather than a resource is what makes form-based auth not RESTful, which is something you pointed out yourself.
Honestly I think that the idea of a 100% pure RESTful application is somewhat of a Utopian ideal when it comes to web applications. I believe it is achievable, however, for RESTful web services, since the calling applications can pass credentials with the request header.
At the end of the day, I think that as long as your application works it is fine, and you should not worry about whether or not it is purely RESTful.
That's my $0.02.
From this answer:
To be RESTful, each HTTP request should carry enough information by itself for its recipient to process it to be in complete harmony with the stateless nature of HTTP.
It's not that form-based auth is not RESTful — it's not RESTful to have a session at all. The RESTful way is to send credentials with every request. This could easily be eavesdropped upon, however, but HTTPS/SSL/TLS closes that hole.
Form-based authentication does not use the authentication techniques that are built into HTTP (e.g. basic authentication, digest authentication).
REST purists will ask you to use the functionality built into HTTP wherever possible. Even though form-based authentication is extremely common, it is not a part of the official protocol. So the REST purist sees form-based authentication as an instance of "building functionality on top of HTTP when that functionality already exists within HTTP itself."
Now Forms come along and some folks say "not restful" - what is "not restful" about them?
The authentication credentials are not in the standard place.
REST doesn’t eliminate the need for a clue. What REST does is concentrate that need for prior knowledge into readily standardizable forms. -- Fielding, 2008
RFC 7235 describes the Authorization header; that gives us a standard way to distinguish authorized requests (which have the header) from anonymous requests (which don't have the header).
Because we can distinguish authorized and anonymous requests, general purpose components can do interesting things.
For example, if the origin server is restricting access to a resource, we probably don't want a shared cache to be re-using copies of the HTTP response to satisfy other requests. Because the authorization has a standardized form, we can define caching semantics that restrict what a shared cache is allowed to do.
Putting the same information into a cookie header, in effect, hides the authorization semantics from general purpose components.
(This is somewhat analogous to using POST requests for safe requests -- general purpose components can't distinguish semantically safe POST requests from semantically unsafe POST requests, and therefore can't do anything intelligently take advantage of the safe handling).
If we had smarter form processing -- form input controls that copied information into the Authorization header instead of the query string/request-body -- then forms would be fine. But (a) we don't have that and (b) we are unlikely to get it, because backwards compatibility.