3👍
My main concern boils down to that this is trivial to do without strictly adhering to REST architectural guidelines, but I feel like I’ve missed the boat completely in trying to do so. I understand designing proper REST APIs and clients isn’t “easy”, but it seems that I’m in dire need of a similar example to work through the actual implementation.
The best example I’ve been able to find is the Sun Cloud API. Most of the documentation describes the various media types used by the system, which seems to be the key to pulling this kind of thing off.
I find that it helps to be writing your client at the same time you’re developing your API. That way you can spot what’s likely to make your API a pain to code for right away and fix the problem.
It isn’t easy. If you follow the HATEOAS constraint to its logical conclusion, each media type you define will be handled by one of a family of clients. To the extent that you can make all of your resources follow a similar pattern of behavior, your job of writing clients will become easier.
For example, you could define a media type ‘Index’ that simply lists related resources. Index defines links for pagination, getting items in the list, finding items by name, etc.
Then, you might define a base media type called ‘Item’. Item has a link for displaying its parent Index, updating/deleting itself, etc. Your resource Widget could then be represented by two different media types – one Index and one based on Item.
You could begin by implementing a single class that handles the Index media type. Then you could write a base class that handles all common Item media type behavior. Finally, you could write a Widget client that handles all widget-specific behavior and which extends the Item client. These clients could expose their functionality (availability of more links and data fields) in an idiomatic way for the language they’re written in.
Processing a response from your server would then be a matter of matching the mime type of the response to one of the clients you’ve written.
In other words, even though the client for your service as a whole would be made up of many clients of limited scope, they would each be based on common behaviors and so could be implemented in a DRY way.
3👍
From my experience the REST model makes much more sense if the representations and their contained links are translated directly to a client UI. In this scenario it is the user that directs the exploring of the REST interface.
Often I see people trying to use REST interfaces as a kind of HTTP based data access layer. With this mental model, hyperlinked data provides little more than structural data relationships. It becomes difficult to build application behaviour on top of that interface without violating RESTful constraints.
I like to think of a RESTful interface as delivering UI content to an application that is going to render that content with some arbitrary technology. Unfortunately, REST is frequently compared to web services which, in my opinion, fit in a different architectural layer. Web services deliver data that is to be processed by a client application. RESTful interfaces should deliver content that will be rendered to the user.
Sure you can use a REST interface to deliver data to remote applications but think of it as simplified screen scraping.
When writing a client for REST interface I find it useful to imagine that I am writing a custom web browser that only understands the media-types that are delivered by that RESTful interface and is hard-coded to start at a specific URL and there is no address bar!
- [Django]-Cannot concatenate 'str' and 'tuple' objects – Django – johnny cache
- [Django]-Django with django-nose: two identical settings files with different behavior in running test command
1👍
If I understand your question correctly, you want to explore an unknown service, correct?
If so, then you could, for example continue with an OPTIONS
request to the “widget” resource, to see which HTTP methods it supports (these should be listed in the Allow
header of the response).
You can then do the same for all URIs found in <link rel="whatever">
elements. If a resource found this way indicates that it supports GET
, then fetch it and repeat …
This way you should be able to explore all nested resources.
This kind of exploration will of course only get you so far, because to really interact with the service, you will need to know about its media types (or representations), and what the different <link rel="whatever">
actions you found actually mean. This step can’t be automated, you’ll have to read the documentation for the service and build you client accordingly. I suggest reading the article “How to GET a Cup of Coffee“, which I think explains this interaction very well.
- [Django]-'ascii' codec can't decode byte 0xe2 in position 5367: ordinal not in range(128)
- [Django]-Why do you need to use Django REST API?
- [Django]-Django: 'User' object has no attribute 'user'
1👍
Sun Cloud API documentation is a great example of a RESTful API, focusing on the media types.
- [Django]-How to get the length of a TextField in Django?
- [Django]-Checking whether two Django querysets have any items in common
- [Django]-Django – How can I set/change the verbose name of Djangos User-Model attributes?