I have come across numerous JSON over HTTP APIs that were suppose to be RESTful but I'm not sure if the following design is adhering to REST principals -
Request model is used as a subset of Response model.
For example, POST /flight/inquiry
Request :
{
"flight_no":"2384B",
"departure_time":78163918839123,
"arrival_time":78163918889382,
...
}
Response :
{
"request" :
{
"flight_no":"2384B",
"departure_time": 78163918839123,
"arrival_time": 78163918889382,
...
}
"status" : "ON TIME"
"last_updated" : 7816391884313,
...
}
If we analyze this in terms of Richardson Maturity Model, I think it will not qualify for level 1 because there is no clear definition of a Resource. If we call 'Inquiry' as the resource here, the response should not have result on the inquiry such as status, last_updated, etc. Typically, it should respond with an inquiry_id (like 123) that can be passed to a second end point GET /flight/123/status.
This approach, though is more aligned with REST principles (correct me if I'm wrong), developers tend to avoid it simply because it's easy to squeeze the same behavior in a single end point rather than two. My question is, are there consequences to ignoring REST principles in situations like these where it is simpler to take shortcuts?
I think your current understanding is suspect.
Using POST to request a representation of a resource isn't RESTful, because we have GET, which is more suitable.
It isn’t RESTful to use POST for information retrieval when that information corresponds to a potential resource, because that usage prevents safe reusability and the network-effect of having a URI. -- Fielding, 2008
More idiomatic queries would look more like
GET /flights?flight_no=2384B
or even
GET /flights?flight_no=2384B&departure_time=78163918839123&arrival_time=78163918889382
In these cases, nobody would be at all startled that the same "parameters" used in the identifier are also repeated in the representation of the resource.
Given that the query is assigned POST semantics by the client, there's absolutely nothing wrong with a response that looks like:
200 OK
Content-Location: https://example.org/flights?flight_no=2384B&departure_time=78163918839123&arrival_time=78163918889382
In which case having the parameters appear in the response body would also be perfectly normal (just as they would be if the client had used a GET on that resource directly).
are there consequences to ignoring REST principles in situations like these where it is simpler to take shortcuts?
If you relax the REST architectural constraints, then you can no longer expect the corresponding properties to hold.
In particular, when you start replacing the uniform interface with your own bespoke semantics, you sacrifice the capabilities of general-purpose components that could otherwise assist.
Related
I want to know what are all reasons of qraphQL to be used instead of rest api.
As much I know instead of making multiple requests (to reduce HTTP request), can make a group of HTTP requests in one request using graphQL.
Can anybody describe little more, please?
Thanks in advance.
There are many articles covering this question in more details available on the internet. I am trying to give a short overview here.
GraphQL offers a couple of advantages over REST.
Main difference
In a REST interface, everything is about resources. For example, you'd get the resources "car" with ID 25 and ID 83 by calling an endpoint like this:
GET /cars/25
GET /cars/83
Note, how you have to call the interface twice. The endpoint ("cars") and your resource are coupled.
In GraphQL you could get both cars with one call, using this example query:
GET /api?query={ car(ids: [25, 83]) { model, manufacturer { address } } }
Note, how you even specified the exact data you want to fetch (model, manufacturer and its address). Compared to REST, the endpoint ("api") is not resource-specific anymore.
Some advantages
As already mentioned in the question, you can reduce the amount of HTTP operations with the help of GraphQL queries (avoid underfetching).
By specifying exactly, which data you want to fetch, you are able to reduce the overhead being transmitted over the interface (avoid overfetching).
By using flexible queries with GraphQL, you're more likely to avoid coupling the interface consumer too tight to the producer by not implementing exactly the requirements of a specific consumer into a REST interface with defined endpoints.
Because each consumer exactly specifies which data is required with GraphQL, you can gather more detailed statistics on data usage in your backend.
I have a question to RESTful services. In REST the POST method is used to create an entity.
And GET is used to query entities. Right?
As I read in another posts it is not allowed in HTTP to send a GET request with a body.
But when I want to send Json to make a query, what is the best way? Are there any best practices or how do you solve such json queries?
Thanks for your answers
In REST the POST method is used to create an entity. And GET is used to query entities. Right?
Not really. GET is used to fetch representations of resources. POST is deliberately vague -- anything not worth standardizing can use POST.
when I want to send Json to make a query, what is the best way?
There is no best way to do it, just trade offs.
The basic plot of HTTP is that you GET representations of resources. If the resource you want doesn't exist, you create a new one. So the "REST" flow would look something like sending a request to the server to create a "the answer to my query" resource, and then using GET to obtain the current representation of that resource. Which is great, because we can fetch the latest representation of that resource any time we're worried that our copy is out of date. Other people with the same query can use the same resource, so we can use a general-purpose cache to take a lot of the work. The end result is "web scale".
OK, not that great, because we learned that sending information over insecure channels is a bad idea; but we can put a general-purpose caching proxy in front of our server, and get some scale that way.
But "create a new resource" is a lot of ceremony when you only expect to need the query once.
Creating a new resource was using POST in this situation anyway, so why not return a representation of the solution right away? And the answer is, go right ahead! that works great... but doesn't give you any cache support at all. You are effectively performing a remote call under the guise of modifying a resource.
Also, POST doesn't promise idempotent semantics -- on an unreliable network, requests can get lost, and general purpose components won't know that in this particular case it is harmless to just repeat the same request.
PUT has idempotent semantics... but it also has very specific opinions about the contents of the payload that don't match "query" at all.
You can dig through other standardized methods, but there aren't really any good fits. The only methods that are close are SEARCH and REPORT, which are coupled to WebDAV semantics.
You can invent your own non standard method; but general purpose components won't understand it.
You can standardize a new method with the semantics you need, but that's a lot of work.
Or you can just use POST.
Remember, the web took over the world using nothing more than GET and POST. So it's probably fine.
This is a general RESTful API design question. We are trying to solve the following case with the most common approach possible.
We have a resource, let's say: /licenses/5123
The resource has an expiration date which needs to be updated to an expired state. Of course the easiest thing to do would be to just expose the expiration_date and have the client set it to the new date but that is not desired.
To update the resource, we're using PUT method and would like to specify the type of update this will be. In other words, is the update action 'expire' or 'extend' or 'whatever'.
I considered a few option:
implement custom http method - but I don't like extending HTTP protocol beyond its standards
add action url parameter and specify the value: PUT /licenses/5123?action=expire
since there are other params in the body of the request in JSON format, add action param into the JSON request.
implement custom http header for the type of update this is
Please share your opinion and/or provide any references to online resources that may be describing such cases. I can't imagine this is a unique case.
Thank you very much!
Generally option 2 and 3 are preferred. There is no real need to do something custom with HTTP actions or custom headers.
PUT is a reasonable action method for updating a license like you describe. Putting the details of the update in the JSON request body sounds reasonable (Option 3), and that's what I would do.
Option 2 is my preferred choice.
I think going with option 2 has been my common best practice, it's clean, efficient and readable. Most of the time I strive for readability and maintainability over all else as I may not be the developer debugging, fixing or extending the code in the future.
Doing anything with either the HTTP protocol or headers always feels like a 'hack'. I think it's going above and beyond and will require more effort than the problem is most likely worth (which scraps solutions 1 and 4).
A potential issue with option 3 is that you could be confusing business logic with your data which leads to coupling and potential upgrade issues.
Maybe I'm confusing things or over-complicating them, but I'm struggling to develop a RESTful API that supports both HTML and JSON content types. Take for example a simple user management feature. I would expect to have an API that looks like this:
GET /users: lists all users
GET /users/{id}: views a single user
POST /users: creates a new user
A programmatic client posting to /users with a JSON payload would expect a 201 Created response with a Location header specifying the URL to the newly created user, e.g. /users/1. However, a person creating a user through his web browser would post to the same URL with a form-encoded payload and would expect to be redirected to the user list page, requiring the API to return a 302/303 redirect with a Location header of /users.
From a purely conceptual point of view, I find it surprising that an API would react differently based on the submitted content type, and wonder if this is bad design. Then again, maybe it's a mistake to consider the programmatic API and the web-centric API to be the same API and one shouldn't worry about such concerns and worry more about providing a good experience to the different clients.
What do you think?
You've stumbled upon two separate issues.
One, the typical web browser is a pretty lousy REST client.
Two, web application APIs are not necessarily REST APIs (see #1).
And thus, your conundrum of trying to serve two masters.
Arguably representation has little to do with application semantics when it comes to details such as workflow, particularly if you have equally rich media types (vs a constrained media type such as an image, or something else).
So, in those terms, it's really not appropriate to have the application behave differently given similar media types.
On the other hand, media type IS Yet Another aspect of the request which can influence operation on the back end. You could, for example be requesting an elided "lite" data type that may well not offer links to other parts of the api that a richer media type would, or your authorization level is a factor on what data you can view, as well as what other relations are available, or even what media types are supported at all.
So it's fair that every aspect of the request payload can have impact on the particular semantics and effect of any particular request to the server. In that case, you're scenario is not really off the mark.
In the end, it's down to documentation to clarify your intent as an API designer.
I am developing an online game where characters can perform complex actions against other objects and characters. I am building a REST API, and having a lot of trouble trying to follow even some of the most basic standards. I know that REST isn't always the answer, but for a variety of reasons it makes sense for me to use REST since the rest of the API uses it appropriately.
Here are some tricky examples:
GET /characters/bob/items
This returns an array of items that Bob is carrying.
I need to perform a variety of 'operations' against these items, and im having a very difficult time modeling this as 'resources'.
Here are some potential operations, depending on the nature of the item:
throw, eat, drop, hold
This is complicated because these 'operations' are only suitable for certain items. For example, you can't eat a sword. Moreover, 'eat' essentially has a side-effect of 'deleting' the resource. Using 'throw' may also 'delete' the resource. Using 'drop' may 'transform' the resource into another resource type. 'Throw' requires that I provide a 'location'. 'Hold' requires that I supply which hand to hold the item in. So how do you model these operations as resources? None of them are 'alike' because they each require different parameters and result in completely different behaviors.
Currently, I have an 'actions' resource that I POST these arbitrary actions to. But this feels way too RPC and non-standardized/discoverable:
POST /actions/throw
{
characterId: 5,
itemId: 10,
x: 100,
y: 150
}
I try to stick to resources and GET/POST/PUT/PATCH/DELETE where possible, but the base verbs tend to map directly to CRUD calls. Other, more complex operations generally can't be mapped without additional information.
Focusing on the resources, I'd probably do something like this (posting messages to the resources):
POST /characters/bob/items/{bombId}?action=throw
POST /characters/bob/items/{foodId}?action=eat
POST /characters/bob/items/{potionId}?action=add&addedItem={ingredientId}
Return an error when the action is not appropriate for the item.
Where I want a resource to “do a complex action” while remaining RESTful, I'd POST a complex document to the resource that describes what I want to happen. (The complex document could be in XML, JSON, or any number of other formats.) This is somewhat distinct from the more common pattern of mapping POST to “create a child resource”, but the meaning of POST is “do non-idempotent action defined by body content”. That's a reasonable fit for what you're after.
As part of the HATEOAS principle of discovery, when you GET the resource which you will later POST to, part of the document returned should say what these complex action documents are and where they should be sent to. Logically, think of filling in a form and submitting it (even if the “form” is actually slots in a JSON document or something like that).