Modify Rest POST request behavior with query String - rest

I have a resource which basically represents a number. I have two possible updates for this number: Set the number to a specific value or add a value to it. Now I'm confused if I can use the query string part of the URL to specify the desired behavior.
Something like this:
/resource/{id}/?mode=add
/resource/{id}/?mode=set
Or is there an alternative way two represent to update strategies for a rest resource?
An Alternative would be to extend the request body with this information but this since strange, since the request data should contain the data and not "meta information" for the request itself - as far as I understand REST apis.
The project is an ordinary angularjs (client) and java (server) project.

Related

Is it a good practice to use 'createModel' in REST?

I'm looking for a best way for implementing an endpoint of REST-full application that will be responsible for creating a new library orders. Let's assume that I have the following resources.
If I want to get all books of a particular author I can use the next endpoint:
HTTP GET
api/books/author/123
If I want to fetch all orders of a particular book I can use the endpoint provided below:
HTTP GET
api/books/456/orders
My question is what will be the most suitable URL and a request model for an endpoint that will create orders?
From my perspective it can be
HTTP POST
api/books/456/orders
And one more question. Is it a good practice in REST to use request models like CreateOrder? If I want to create a REST-full web application can I use the following request model:
class CreateOrder
{
AuthorId: number;
BookId: number;
ClientId: number;
}
Sometimes it makes me confused. Should request models look like our resources or not?
Let's assume that I have the following resources.
Your "resources" look suspiciously like "tables". Resources are closer to (logical) documents about information.
what will be the most suitable URL and a request model for an endpoint that will create orders
For the most part, it doesn't matter what URL you use to create orders. In a hypermedia application (think HTML), I'm going to submit a "form", and the meta data associated with that form are going to describe for the client how to compose a request from the form data.
So the human, or the code, that is manipulating the form doesn't need to know anything about the URL (when is the last time that you looked to see where Google was actually sending your search?)
As far as general purpose web components are concerned, the URL/URI is just an opaque identifier - they don't care what the spelling means.
A thing they do care about is whether the spelling is the same as something that they have cached. One of the consequences of a successful POST /x message is that the cached representation(s) of /x are invalidated.
So if you like, you can think about which cached document should be refreshed when an order is created, and send the request to the identifier for that document.
Should request models look like our resources or not?
It's not necessary. Again, think about the web -- what would the representation of create order look like if you were POSTing form data?
clientId=1&bookId=2
or maybe
bookId=2&copies=3
If the "who is creating an order" is answered using the authorization headers.
In our HTTP requests and responses, we are fundamentally sending message representations - sequences of bytes that conform to some schema. There's no particular reason that those sequences of bytes must, or must not, be the same as those we use elsewhere in the implementation.
Your end-point does not need to always start with /books. You can introduce another end-point /orders for creating or getting orders. So , to create an order , you can :
HTTP POST
api/orders
And does the 'request model' that you mean is the HTTP request body structure ? If yes, it does not need to be 100% match with your back-end persisted/domain model. Just include enough parameters that the server needs to know in order to create an order. (e.g. Include bookId rather than the whole book object etc.)
BTW , to get all books for a particular author , it is more common to use query parameter such as :
HTTP GET
api/books?authorId=123
What you are doing is not REST, it is CRUD over HTTP. REST does not care about your URI structures and resources are very far from database tables. If CRUD is all you need, then download a CRUD generator library https://github.com/search?q=crud+generator&type=Repositories, which will generate all the upper and you won't need to write it manually.

bulk GET using HATEOAS

I've seen many examples of HATEOAS where every resource has links to related resources. An API that returns N items of a certain resource per page, the client would probably need N calls to fetch any nested resource by consuming HATEOAS. For example:
GET city/documents:
[{
id: 1,
city: {
self: 'http://service.com/cities?filter=id==1'
},
document: { ... }
...
}, {
id: 2,
city: {
self: 'http://service.com/cities?filter=id==2'
},
document: { ... }
...
}]
FYI, the query parameter uses the FIQL syntax to define the filters.
Now, if the client was to fetch the city details for each document (to show on UI), it will probably need N additional calls. However in my case, the /cities API can additionally take multiple city ids like this: /cities?filter=id=in=(1,2) that can reduce N calls to one. Is there a way to articulate something like this using HATEOAS? I've read about the templates but not sure how should the template look like and how would client consume it?
I've seen many examples of HATEOAS where every resource has links to related resources. An API that returns N items of a certain resource per page, the client would probably need N calls to fetch any nested resource by consuming HATEOAS.
Yes. Less true in a world with Server-Push, where the server can proactively provide multiple resources in response to a query. If you imagine asking for a web page, and getting the html, and then also the images and the java script resources too, then you've got the right sort of idea.
API can additionally take multiple city ids like this: /cities?filter=id=in=(1,2) that can reduce N calls to one. Is there a way to articulate something like this using HATEOAS?
Yes.
Let's walk through it carefully. What you've done here is introduced a new resource, with identifier /cities?filter=id=in=(1,2). You might have another resource /cities?filter=id=in=(1,20) and another resource /cities?filter=id=in=(1,2000). In your implementation, these might be a "single endpoint" that extracts parameters from the identifier and uses them to generate the correct representation.
So what you get is something like a data transfer object - a large grained resource fetched in a single go.
I've read about the templates but not sure how should the template look like and how would client consume it?
The simplest example, which you have likely seen already, is a web form. You allow the client to provide the start and end elements, and the form processing takes that information and creates the specified URI from it.
/filtered-cities?start=1&end=2000
So the client needs to understand what the form is for, and how to identify the semantics of the different elements in the form. The agent needs to understand the processing rules that transfer the form data into the URI.
URI Templates are the same basic idea; they give you a domain agnostic language with which to describe where the parameters go in a resource identifier. The basic pattern is the same - there needs to be agreement about the semantics of the parameters, the server provides a URI, the client provides a parameter map, and the generic code can take care of the merge
uri = template.apply(parameterMap)
URI Templates aren't quite as powerful as forms; with a form, you can introduce a default value for a parameter, but there is no analogous capability in URI templates.
HAL-Forms may give you a better sense of how a form based approach might work in JSON.

Design a REST API in which a search request can take parameters for multiple Queries

I have to design a REST API in which a search request can take parameters for multiple Queries ( i.e. when the client make a call using this API, he should be able to send parameters to form multiple queries).
We have an existing API where we are using GET and it takes multiple parameters which together forms a single Query and then this API call returns the response for this query.
e.g. currently I can pass firstName, lastName, age etc in the request and then get back the person.
But now I have to enhance this service(or have a separate service) where I should be able to send parameters like firstName1, lastName1, age1 to search person1 ; firstName2, lastName2, age2 to search person2 and so on.
Should I use POST for the new API and then send list of parameters(params for query1, params for query2 and so on)?
Or is there a better approach.
We are using Spring Boot for REST implementation.
Its better to use POST because GET is good for 2,3 parameter but when you have a set of parameter or object then POST is Good.
The best thing to do here will be do POST and then return a JSON object with all the details of the Person in an array.
That way it will be faster and you would not have to deal with long urls for GET.
Also GET has limitations regarding the length of the request whereas there is no such limitation in case of POST.
It is really hard to give a right answer here. In general sending a GET request does have the advantage that you can leverage caching easily on a HTTP level, e.g. by using products like varnish, nginx, etc. But if you already can forsee that your URL including all params you'll have to send a POST request to make it work in all Browsers.
RESTfull architecture should respect the principle of addressability.
Since multiple users can be accessed through a unique request, then ideally this group of user should get an address, which would identify it as a resource.
However I understand that in the real world, URIs have a limited length (maximum length of HTTP GET request?). A POST request would indeed work well, but we lose the benefit of addressability.
Another way would be to expose a new resource : group,.
Lets suppose that your current model is something like this :
.../users/{id}
.../users/search?{arg1}={val1};{arg2}={val2}
You could eventually do something like :
.../users/groups/
.../users/groups/{id}
.../users/search?group={id}
(explanation below)
then you could split your research in two :
first a POST on .../users/groups/ with, as proposed by other response, a JSON description of the search parameters. This request could scan the .../users/groups/ directory, and if this set of parameters exists, return the corresponding address .../users/groups/{id}. (for performance issues you could for instance define {id} with a first part which would give the number of users requested).
Then you could make a request for this group with a GET with something like this : .../users/search?group={id}.
This approach would be a bit more complex to implement, but is more consistent with the resource oriented paradigm.

RESTful API required parameters in query string?

When designing a RESTful API, what to do if a GET request only makes sense if there are specific parameters associated with the request? Should the parameters be passed as a query string, and if so, what to do when all the parameters aren't specified or are formatted incorrectly?
For example, lets say i have a Post resource, which can be accessed by `api/posts` endpoint. Each post has a geographical location, and posts can be retrieved ONLY when specifying an area that the posts may reside in. Thus, 3 parameters are required: latitude, longitude and radius.
I can think of 2 options in this case:
1. Putting the parameters in query string: api/posts/?lat=5.54158&lng=71.5486&radius=10
2. Putting the parameters in the URL: api/posts/lat/5.54158/lng/71.5486/radius/10
Which of these would be the correct approach? It seems wrong to put required parameters in the query string, but the latter approach feels somewhat 'uglier'.
PS. I'm aware there are many discussion on this topic already (for example: REST API Best practices: Where to put parameters?), but my question is specifically addressed to the case when parameters are required, not optional.
The first approach is better.
api/posts/?lat=5.54158&lng=71.5486&radius=10
The second approach is a little misleading.
api/posts/lat/5.54158/lng/71.5486/radius/10
You should think of each of your directories as resources. In this cause, sub-resources (for example: "api/posts/lat/5.54158") are not really resources and thus misleading. There are cases where this pattern is a better solution, but looking at what's given, I'd go with using the query string. Unless you have some entity linking to link you directly to this URL, I don't really like it.
You should put everything in the query string and set the server to return an error code when not receiving the 3 required parameters.
Because it's a group of parameter that identify an object.
Taking the example:
lat=5.54158; lng=71.5486 radius=10
It would be very unlikely to this url make sense:
api/posts/lat/5.54158/lng/yyyy/radius/zz
It's different than:
api/memb/35/..
because the member with id 35 can have a lot of functions ( so, valid urls ) as:
api/memb/35/status or
api/memb/35/lastlogin
When designing a RESTful API, what to do if a GET request only makes
sense if there are specific parameters associated with the request?
Should the parameters be passed as a query string, and if so, what to
do when all the parameters aren't specified or are formatted
incorrectly?
By REST your API must fulfill the REST constraints, which are described in the Fielding dissertation. One of these constraints is the uniform interface constraint, which includes the HATEOAS constraint. According to the HATEOAS constraint your API must serve a standard hypermedia format as response. This hypermedia contains hyperlinks (e.g. HTML links, forms) annotated with metadata (e.g. link relation or RDF annotation). The clients check the metadata, which explains to them what the hyperlink does. After that they can decide whether they want to follow the link or not. When they follow the link, they can build the HTTP request based on the URI template, parameters, etc... and send it to the REST service.
In your case it does not matter which URI structure you use, it is for service usage only, since the client always uses the given URI template and the client does not care what is in that template until it is a valid URI template which it can fill with parameters.
In most of the cases your client has enough validation information to test whether the params are incorrect or missing. In that case it does not send a HTTP request, so you have nothing to do in the service. If an invalid param gets through, then in your case your service sends back a 404 - not found, since the URI is the resource identifier, and no resource belongs to an invalid URI (generated from the given URI template and invalid params).

How to define transforms on a resource in a REST way?

I'm designing a REST api, following best practices, including a form of hypermedia/hateoas. I'm using jsonapi for the design guidelines, which seems to be pretty complete.
Currently, I have a need for:
combining 2 resources in a response (a Resource A and a related Resource B). I do this using the Compound Documents - structure as specified in jsonapi. Or also commonly known as resource expansion
formatting the result of 1. in a specialized way so it can be readily consumed by a specialized client that expects said formatting.
My problem is with 2. How do I correctly represent this in a REST-way? It seems I may need a separate endpoint, but that wouldn't be 'RESTy', since that implies a separate resource, while it's just a transformation of the output of the same resource.
Any references on how to do this?
You could use a header or a query param to handle this.
When the client needs specific formatting, they could add an additional header to the request something like Format:Indented or something like http:\\myapp.com\resouces\myresource?format=indented
Or if the server is formatting and wants the client to know that the response is pre-formatted, the server could add a Format response header to notify the client that response is formatted.