What is the most common approach to URI naming for API which uses both HTTP and WebSocket protocols for similar requests? Are there any common conventions for that?
Lets suppose we have a HTTP request returning the collection of users:
localhost/users
This request should return a list of registered users.
On similar WS request, the server should open WebSocket channel and send a list of users to the client over it every time the list is updated (e.g. user was added or removed, etc).
How should the URI for WebSocket request look like?
I see several options:
It may be the same, localhost/users. The difference should be only in the request headers (Upgrade: WebSocket). The drawback is that it can be confusing as requests with same URI return different responses dependent on provided headers
localhost/users-ws. This seems a little bit ugly for me as the API grows each time we have similar WS request for a HTTP request
localhost/users/ws. This breaks the possibility of extending the URI with variable, for example we can't use localhost/users/{id} here no more.
Store all WS requests under common ws domain - localhost/ws/users. This is also ugly as we break the order of domains in the URI and can't redirect requests with users domain to the specific handler
So at the monent I don't see an option without obvious drawbacks:)
If someone can provide any examples of big projects like StackOverflow or GitHub where WS and HTTP are used together, it will be very helpful.
I am not aware of any common naming conventions for WebSockets but for web APIs there is a naming convention to start the route with /api/, example api.example.com/api/users.
Following that practice, it could be argued that example.com/ws/users could be a fitting route name to use.
Related
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.
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.
REST and CORS.. how are they different? is it even correct to compare them? because I have seen a seemingly REST API use custom X- headers to make a pre-flighted request(Docebo LMS API). This means that maybe CORS and REST are used for different purposes.. But on the surface, it seems that both are designed to give access to resources stored on a different server. Also, Simple XMLHTTP requests seem to work like HTTP.(The headers sent and received by the browser are through HTTP).. So, are XMLHTTP objects translated into HTTP by the browser? I am really taking in a ton of information right now and I cant seem to make any real progress in understanding these things... Any help is appreciated.
CORS - Cross Origin Resource Sharing. A concept and set of techniques that enables sharing of resource/data across domains. Example, from your page /yourDomain.net you try to make an ajax call to myDomain.net to post some data. Read this Wikipedia and MDN articles.
REST - REpresentational State Transfer. A set of standards & guidelines that defines a specific way for systems to talk to each other. It follows state-less http like standards where URIs reprsent resource and client can work on them using http verbs. e.g. GET weatherApp.com/weather/rome. Refer this.
HTTP - Hyper Text Transfer Protocol. THE standard protocol to transfer data to/from web servers. Check this W3 specifications and Wikipedia page.
XMLHttp - A type of request generally used to make ajax calls from client (mainly html, javascript) applications to web servers. It works on http standards. Not bound to XML though. Read this and this.
Now, all of REST, XMLHttp, CORS work on HTTP is some way, meaning they all use the http infrastructure.
And any/all of them might be used to create a fully functional modern application. For example, a web application might use XMLHttp request to make REST service call to get some data. It can also utilize CORS to get/post data to another domain. Need not say, the whole system relies on http!
They are totally different things. Rest is a specifical approach to prrforming data calls. Basically is characterized by a systen where the state is not stored on the server but rather passed in calls. You can read more here
Cors is a technique for enabling javascript to perform data ervice calls to domains otheir than the server donain that they came from. Normally web browsers prevent javascript and other web technologies from doing cross origin or cross domain calls. These are calls where a js script came from google.com lets say, and now it wats to call microsoft.com. well the browser would stop that call because google.com and microsoft.com are different domains.
That example is obvious, so lets try a less obvious one. Your script on blogs.yoursite.com tries to call a service at shopping.yoursite.com. now these sires are both yoursite.com but they could still be considered cross domain and usually are. CORS allows you(on the html developer side) to say i trust these domains. And by trusting them, now you can call their webservices even if they would have been a cross domain call.
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.
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.