When is JSON-RPC over http with POST more suitable than RESTful API? - rest

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.

Related

HTTP method for both sending and returning information

I'm building a web application that needs to process some information on a server. There is no database involved, the server (using Flask) just needs to receive some (complex) information, process it, and send back the result.
My question is which HTTP method is most suitable here (if any). When I read about HTTP methods, they are usually explained in terms of a REST api, where a GET request is used to retrieve data from the server and a POST request is used to create new data on the server. In my case however, I don't need to store any information on the server. A GET request doesn't seem suitable here, as the information sent to the server is rather complex, and can't be easily encoded in the URL. I think a POST request should work here, as I can send the data in JSON format, but the specifications say POST should be used when you want to create something on the server, and a response should only contain a success message and/or location.
Am I missing something here? Should I use something different like WebSocket, or is a POST request fine here, although it doesn't abide by the REST principles?
Thanks in advance.
the specifications say POST should be used when you want to create something on the server
No, they don't. A lot of people say that, but the specification is not so restrictive.
The POST method requests that the target resource process the representation enclosed in the request according to the resource's own specific semantics
Here's how Roy Fielding explained it in 2009:
POST serves many useful purposes in HTTP, including the general purpose of “this action isn’t worth standardizing.”
Yes, POST isn't ideal - the semantics of POST are neither safe nor idempotent, and your particular case would benefit from communicating those properties to general purpose components.
But it is good enough, until the work is done to standardize the semantics of a new method token that better handles this case.
We use POST method to send data to the server. What the server does with the data is encoded in the server logic.
As a client if you want to just send data to server use POST.

RESTful way to specify commands on a resource

I could not find a universally agreeable way to specify commands in RESTful manner. Consider that I have a resource on which I want to provide 3 commands:
enable
disable
re-trigger
Which is the most RESTful way?
POST /resource/disable
POST /resource?command=disable
Any other way ?
Which is the most RESTful way?
How would you do it with a web site? REST is the architectural style of the world wide web; if you can figure out how you would do it with a web site, that will give you the right idea for how to provide a RESTful API.
On the web, the usual answer would be that we would have forms to collect information from the client, who would then submit a POST request (because we are intending to change the resource) to some endpoint.
Because the form.action property tells the client what URI to use, the server has control over what the URI is -- we can change it later if we want to.
We could, as you suggest, have a different URI for each command. There's nothing wrong with that, but it does miss an opportunity. You see, one of the important ideas in REST is caching; and HTTP defines cache invalidation semantics; the practical aspect of which is that if you use the /resource identifier as the form action, then successful POST requests will automatically invalidate the client's local copies of the resource.
This does imply, of course, that the POST handler in your implementation will have to determine which command was intended -- probably by looking at information included in the body of the post request; a "commandName" parameter or something similar.

How to deal with per verb permission in Rest on a client?

Lets assume we have a resource on an URL like so: foo.com/api/bar
And lets say that a user might be allowed to GET that resource, but not allowed to POST to that resource.
I can easily solve that by specifying different permissions per verb.
But how should the client know on beforhand if it is allowed to perform the POST?
Lets say we have a "save" button on a page, that should not be enabled if the user lacks the rights to do a POST.
I know about HATEOAS/Hypermedia constraint, and that I can pass a list of links for different actions together with the resource.
But AFAIK, that doesn't carry information on what verbs to use, only URL's for different actions.
Are there other variations where the verb is included?
Are there other approaches if you don't want to clutter the resource with all sorts of metadata?
This has been asked a lot on the HAL discuss forums https://groups.google.com/forum/#!forum/hal-discuss
The fact that verbs aren't returned is a decision of the hypermedia format you're using, which i'm guessing is HAL (or maybe collection+json). Some formats DO include verb information.
HAL actually allows you to include custom fields on your link objects if you wish, but i would discourage this because any standard client won't know how to interpret this.
But also i've found the verb to be worthless in the end.
First off in human 2 machine the user is going to read documentation. HAL has all of it's links dereference (via CURIE's as they are currently naemd) to human readable documentation that should describe the effects of requesting that link with different parameters, verbs, headers, etc.
Next off is that for your Application to be truly RESTful you should respond to all verbs...you might just not respond that the verb was OK. For an HTTP based app returning a 405 is VERY appropriate. Returning a 404 is not! A 500 would be worse!. Your 405 should include what methods are available for the requested resource.
Next in the case of machine 2 machine (and a bit of h2m) your application when accessed via HTTP (i try to avoid http in my answers as RESTful applications aren't necessarily HTTP..although i'd say 101% of them are) should use the OPTIONS method (http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html) against the resource URL in order to get a description of what's possible.
Here's where i see a lot of people getting tripped up, what should the response of OPTIONS be? well what people forget is content type negotiation! The requester should say what format for option information they expect. Accept: some-machine-language/xml or application/language+json. Some RFC or standards define these content types and your API can identify what formats it supports. I would suggest you include support for text/html so that you can return human readable documentation as well about what verbs are supported. This covers the h2m scenario nicely.
The same content type negotiation can be useful when returning info about a method not being supported. The server can send a content-type that the client can understand that describes semantically what methods are allowed.
The final thing i like to point out is that methods imply client intent. i want to PUT this resource or DELETE that resource. The server should accept requests and return responses indicated what state transitions occurred because of that request. Thus it's a little silly to have the API identify possible intents of the client with every request. The client knows what it wants to do, it should try, and if it can't then it should deal with that.
HTTP Verbs are pure transport protocol verbs. Those might not be the right verbs to do application functions, precisely because of the issues you mentioned in the question. So let us see if we can approach this differently without using http verbs. Doing http verbs to do appliction actions might limit us tommorrow as we might have need to move from http to another protocol.
LEt us take an example to illustrate. Let us say we are talking about Update Delete application using HATEOAS. So in this case, if the there are two products, represented by the URL www.abc.com/product/001 and www.abc.com/product/002. In a true HATEOAS situation, If the response of the two products product/001 and product/002 has to be looked at show the client screens.
So if the response to product/001 has a response product/001/delete,product/001/change and product/002 has the response product/002/Change then the client will show delete for only product/001 and change for the other two products.
So in response to your question. By appropriately identifying actions with product now it is possible to do role based actions.
I hope i have answered your question.

GET vs POST in REST Web Service

I'm in the process of developing a REST service that allows a user to claim their listing based on a couple of pieces of information that appear on their invoice (invoice number and billing zip).
I've read countless articles and Stack Overflow questions about when to use GET and when to use POST. Overall, the common consensus is that GET should be used for idempotent operations and POST should be used for operations that create something on the server side. However, this article:
http://blog.teamtreehouse.com/the-definitive-guide-to-get-vs-post
has caused me to question using GET for this particular scenario, simply because of the fact that I'm using these 2 pieces of information as a mechanism to validate the identity of the user. I'm not updating anything on the server using this particular method call, but I also don't necessarily want to expose the information in the URL.
This is an internal web service and only the front-end that calls the service is publicly exposed, so I don't have to worry about the URL showing up in a user's browser history. My only concern would be the unlikely event that someone gain server log access, in which case, I'd have bigger problems.
I'm leaning toward POST for security reasons; however, GET feels like the correct method due to the fact that the request is idempotent. What is the recommended method in this case?
Independently of POST vs GET, I would recommend NOT basing your security as something as simple as a zip code and an invoice number. I would bet on the fact that invoice numbers are sequential (or close), and there aren't that many zip codes around - voila, I got full access to your listings.
If you're using another authentication method (typically in HTTP header), then you're good - it doesn't matter if you have an invoice number if the URL, so might as well use GET.
If you're not, then I guess POST isn't as bad as GET in term of exposing confidential content.
There isn't really any added security in a POST vs a GET. Sure, the request isn't in the URL, but it's REST we are talking about here, and the URL wouldn't be seen by a human anyway.
You question starts with some bad presumptions. Firstly, GET is not just for any old idempotent operation, it is for GETting resources from the server; it just happens that doing so should be side effect free. Secondly, the URL is not the only way for a GET request to send data to the server, you can use a payload with a GET request (at least as far as HTTP is concerned, some implementations are bad and don't support this or make it hard). Third, as pointed out, you have chosen some terrible data fields to secure your access. Finally, you are using a plain text protocol any way, so what neither method really offers and better security.
You should use the the verb that best describes what you are doing, you are getting some information from the server, so use GET. Use some proper security, such as basic HTTPS encryption. If you want to avoid these fields 'clogging' up the URL, you can send data in the payload of the request, something like:
GET /listings HTTP/1.1
Content-Type = application/json
{ "zip" : "IN0N0USZ1PC0D35",
"invoice" : "54859081145" }

RESTful HATEOAS Client Url

I'm reasonably sure I understand the server-side of HATEOAS design - returning state URL's in the response - but I'm slightly confused about how to design a client to accept these.
For instance, we access a resource at //somehost.com/resource/1 - this provides us with the resource data and links. We'll assume POST to //somehost.com/resource is returned, indicating a 'new' action. Now I understand posting some data to that url creates a new resource, and provides a response, but where does the form to post that data reside? I've seen implementations where //somehost.com/resource/1/new provides a form which POSTS to /resource, but that URL itself contains a verb, and seems to violate REST.
I think my confusion lies in that I'm implementing a RESTful API and a client to consume it, within the same application.
Is there some sort of best-practice for this sort of thing?
I've seen implementations where //somehost.com/resource/1/new provides a form which POSTS to /resource, but that URL itself contains a verb, and seems to violate REST.
This is incorrect. A URI containing a verb does not, in itself, violate any REST constraint. It is only when that URI represents an action that this becomes a violation. If you can perform a GET request on the URL and receive some meaningful resource (such as a "create new resource" form), then that is perfectly RESTful, and good practice.
My own API is exactly as you describe: /{collection}/new returns a form. /new is just shorthand for a hypothetical /new-resource-creation-form and still represents a noun, and only supports GET requests (HEAD, OPTIONS and TRACE not withstanding).
What HATEOAS prohibits is the user agent being required to know, that in order to create a new resource, it must add /new to the name of the collection.
Basically, if you implement your API as (X)HTML, and can surf it in a browser and perform all actions (AJAX may be required for non-POST form submissions until HTML and browsers catch up with HTTP), then it complies with the hypermedia constraint of REST.
EDIT promoted from comments:
As long as the response negates any need for a priori knowledge, it conforms to the hypermedia constraint. If the client claims to understand HTML, and you send back a response containing a link to an external stylesheet or javascript (no matter where that is hosted) which the client needs to be able to render the page correctly, then it is reasonable to say that the constraint is met. The client should know how to handle all media types it claims to support. A normal human web browser is the perfect example of a client with no out-of-band knowledge about any one HTTP service (web site).
Just to say it explicitly, a web site is a kind of HTTP service. Web browsers do not treat different web sites differently. In order to search for products on Amazon, you load the Amazon service endpoint at http://amazon.com/ and follow links or fill out forms provided in that response. In order to search for products on eBay, you load the eBay service endpoint at http://ebay.com/ and do the same.
Browsers don't know in advance that for searching eBay you must do this, but for searching Amazon you have to do that. Browsers are ignorant. Clients for other HTTP services should be ignorant too.
Yes, you could provide a URI that returns a form for resource creation. Conceivably the form could be used for dynamic discovery of the elements needed to construct a new resource (but you'd want to decide how practical that would really be in a machine-to-machine environment).
Unless there is a requirement that somehow the API has an exact browser-surfable equivalent, the documentation of the media type will describe what elements are needed.
Remember that documentation of media types and the allowed HTTP verbs for a resource is not contrary to RESTful principles. Look at the SunCloud API for an example.
Indeed, according to your example, POST'ing to
//somehost.com/resource
to create a new resource is more standard than first returning a form
//somehost.com/resource/1/new
and THEN POST'ing to
//somehost.com/resource
anyway.