Background
I am developing my first webapi2 rest interface for some products/batches/packs etc. I read this excellent page on how to make a good rest api and i'm stuck on a few concepts and my googling skills have failed me.
I would like to give the developer the option to embed or sideload sub resources to prevent repeated api hits for child/sub-resource data (i.e return all packs with a batch). I would also like them to be able to specify which fields they would like to return.
I'm used to a normal MVC/WebApi style of creating a Method and its own or shared ViewModel and sending down that in its entirety. If I need to send less data I create a slimmer ViewModel.
Question
What return type do I put on the rest endpoint, is it just a JObject that I construct manually depending on what fields they've requested (and the developer has to rely on the documentation to figure out what it could return)?
Or do I create a fat view model and somehow mark the fields as optional with the ability for the JSON/XML converter to omit these fields if the value is null etc (but then how do I side-load sub-resources...)?
Thanks, Pete
I have decided to use OData v4 so that I can allow the client-app to decide on what and how to consume the data i'm exposing. It doesn't support sideloading (that i've discovered so far) but it allows me to embed, filter and slim down any models easily.
Related
I created a few Rest apis right now and I always preferred a solution, where I created an endpoint for each resource.
For example:
GET .../employees/{id}/account
GET .../supervisors/{id}/account
and the same with the other http methods like put, post and delete. This blows up my api pretty much. My rest apis in general preferred redundancy to reduce complexity but in this cases it always feels a bit cumbersome. So I create another approach where I work with inheritance to keep the "dry" principle.
In this case there is a base class User and via inheritance my employee and supervisor model extends from it. Now I only need one endpoint like
GET .../accounts/{id}
and the server decides which object is returned. Also while this thins out my api, it increases complexity and in my api documentation ( where I use spring rest docs ) I have to document two different Objects for the same endpoint.
Now I am not sure about what is the right way to do it ( or at least the better way ). When I think about Rest, I think in resources. So my employees are a seperate resource as well as my supervisors.
Because I always followed this approach, I tink I might be mentally run in it and maybe lost the objectivity.
It would be great if you can give my any objective advice on how this should be handled.
I built an online service that deals with this too. It's called Wirespec:
https://wirespec.dev
The backend automatically creates the url for users and their endpoints dynamically with very little code. The code for handling the frontend is written in Kotlin while the backend for generating APIs for users is written in Node.js. In both cases, the amount of code is very negligible and self-maintaining, meaning that if the user changes the name of their API, the endpoint automatically updates with the name. Here are some examples:
API: https://wirespec.dev/Wirespec/projects/apis/Stackoverflow/apis/getUserDetails
Endpoint: https://api.wirespec.dev/wirespec/stackoverflow/getuserdetails?id=100
So to answer your question, it really doesn't matter where you place the username in the url.
Try signing in to Wirespec with your Github account and you'll see where your Github username appears in the url.
There is, unfortunately, no wright or wrong answer to this one and it soley depends on how you want to design things.
With that being said, you need to distinguish between client and server. A client shouldn't know the nifty details of your API. It is just an arbitrary consumer of your API that is fed all the information it needs in order to make informed choices. I.e. if you want the client to send some data to the server that follows a certain structure, the best advice is to use from-like representations, such as HAL forms, Ion or even HTML. Forms not only teach a client about the respective properties a resource supports but also about the HTTP operation to use, the target URI to send the request to as well as the representation format to send the data in, which in case of HTML is application/x-www-form-urlencoded most of the time.
In regards to receiving data from the server, a client shouldn't attempt to extract knowledge from URIs directly, as they may change over time and thus break clients that rely on such a methodology, but rely on link relation names. Per URI there might be multiple link relation names attached to that URI. A client not knowing the meaning of one should simply ignore it. Here, either one of the standardized link relation names should be used or an extension mechanism as defined by Web linking. While an arbitrary client might not make sense from this "arbitrary string" out of the box, the link relation name may be considered the predicate in a tripple often used in ontologies where the link relation name "connects" the current resource with the one the link relation was annotated for. For a set of URIs and link relation names you might therefore "learn" a semantic graph over all the resources and how they are connected to each other. I.e. you might annotate an URI pointing to a form resource with prefetch to hint a client that it may load the content of the referenced URI if it is IDLE as the likelihood is high that the client will be interested to load that resource next anyway. The same URI might also be annotated with edit-form to hint a client that the resource will provide an edit form to send some data to the server. It might also contain a Web linking extension such as https://acme.org/ref/orderForm that allows clients, that support such a custom extension, to react to such a resource accordingly.
In your accounts example, it is totally fine to return different data for different resources of the same URI-path. I.e. resource A pointing to an employee account might only contain properties name, age, position, salery while resource B pointing to a supervisor could also contain a list of subordinates or the like. To a generic HTTP client these are two totally different resources even though they used a URI structure like /accounts/{id}. Resources in a REST architecture are untyped, meaning they don't have a type ouf of the box per se. Think of some arbitrary Web page you access through your browser. Your browser is not aware of whether the Web page it renders contains details about a specific car or about the most recent local news. HTML is designed to express a multitude of different data in the same way. Different media types though may provide more concrete hints about the data exchanged. I.e. text/vcard, applciation/vcard+xml or application/vcard+json all may respresent data describing an entity (i.e. human person, jusistic entity, animal, ...) while application/mathml+xml might be used to express certain mathematical formulas and so on. The more general a media type is, the more wiedspread usage it may find. With more narrow media types however you can provide more specific support. With content type negotiation you also have a tool at your hand where a client can express its capabilities to servers and if the server/API is smart enough it can respond with a representation the client is able to handle.
This in essence is all what REST is and if followed correctly allow the decoupling of clients from specific servers. While this might sound confusing and burdensome to implement at first, these techniques are intended if you strive for a long-lasting environment that still is able to operate in decateds to come. Evolution is inherently integrated into this phiolosophy and supported by the decoupled design. If you don't need all of that, REST might not be the thing you want to do actually. Buf if you still want something like REST, you for sure should design the interactions between client and server as if you'd intereact with a typical Web server. After all, REST is just a generalization of the concepts used on the Web quite successfully for the past two decades.
I'm new to web services world. I have created a rest api in ERP software that creates sales order. How will anyone outside the world know what parameters to send to this and in what format ? From all the videos I have watched and all materials read they talk about no api documentation is needed as it is REST service, People just know what request payload to send. I m not sure if I understand how that is possible. Its like I give somebody the url and tell them go figure. I tried sending orders with different parameter list and it is creating errors. But, if I send it in the way it accepts then it is working fine. Not sure if I understand the concepts well. Should I be creating documentation of this api telling what the request payload should look like ?
I completely disagree with the answer given by Joessel, which just propagates a typical RPC take on it, which is NOT REST at all!
In regards to how a service utilizing the REST architecture style should inform clients about what properties a resource supports and stuff like that, just look at traditional HTML pages. How are Web server able to tell your Browser what input it expects?
HTML is a media type that specifies the syntax to use as well as the semantics of each of the elements and attributes wich are admissible in a HTML document. I.e. HTML Forms enables a server to inform a client on the respective properties a resource support. In addition to that, a server also teaches a client on the respective target URI to send the request to, the HTTP operation to use upon sending the request as well as the media type to use for marshalling the request to a respective representation format. This is why you DON'T NEED any other documentation to interact with Web pages. Most arbitrary Web clients support HTML documents by default and therefore you don't need to reimplement the wheel to process such documents.
For non-HTML resources it is also just a matter of whether your client supports the respective media type or not. I.e. PNG files also follow a certain standard which allows arbitrary clients to show images instead of the actual bytes on your screen.
Most of those so called "REST APIs", which are truely RPC ones, just use custom JSON based message structures. JSON itself just defines the basic syntax but no semantics for any elements, attributes or other properties. It doesn't even add support for links. JSON Hyper-Schema is an extension which at least triest o add support for it, though it already requires to use an other media type than application/json. Though, if such formats are not well-defined and standardized, widespread adoption will not be possible on the long run. Hence creating a common media type is of importance to increase interoperability for such media types. I.e. for JSON based formats, HAL+JSON, HAL Forms, ION, and others provide definitions for basic JSON based message structures, with support for links and other features like form-support and other things.
So, if you take a closer look at the Web, you will find many concepts that you can reuse for a truely RESTful design. After all, REST just takes the ideas used on the Web for decades and attempts to offer the benefits resulting from these concepts to applications rather than humans alone. As such, it is always a good idea to first design the interaction flow as if one would interact with a traditional Web page and then take the concepts used in that design and apply it onto your application domain model.
As you don't need external documentation to interact with Web pages, so you don't need external documentation to interact with well defined message formats that follow a common media type as well. Through content-type negotiation both server and client will communicate with representation formats both support. So, the more (different) media types you support, the more likely you will be in the end to interact with different parties in that environment and if all of the supported media types are standardized you might not need any external documentation at all.
If you follow the academic definition of REST defined by Dr Fielding in his dissertation, it is true that such a service doesn't need any documentation. Hovewer, the chance are high that your service is not RESTful by his definition and that you need a documention to help your consumers. You can find an informative discussion about why a REST api doesn't need a documentation here.
That being said, you will probably need a documentation in most case. Depending on your needs and consumers of your api, a simple text file could be enough; maybe a markdown that you can easily share with other developers. Just remember to add all information needed to understand each route (verb, path, query, body, response...), and you can even throw some example code to make it easy to start.
And if you need something more robust, I can only advise you to follow the open api specification. One of the easiest way to get started is to use the swagger editor . You will even be able to publish your documentation in a nice way using one of the many tools out there (ex: redoc).
Writing a documention is never fun but nobody will use a product that they cannot understand, however great the product is.
Good luck,
Edit:
I rewrote the introduction as it was misleading, thanks to #Roman Vottner for pointing it out. THe previous intro was:
I don't know who told you that a documentation is not needed for a REST Api but I find this highly misleading for newcomers... A documentation is (super) important, especially if you are not the sole consumer of your API, and in that case I would say it's mandatory.
I've seen a lot of REST implementation examples.
According to them, create endpoint has several options for response body:
no body at all;
id of the created entity;
created entity JSON.
For example, we have a table with data and create a form on the same page on UI.
And we don't want to reload the full page after creating a new entity.
In this case, we have to call our API two times to correctly update our data:
POST to create an entity;
GET to get a list of entities.
We can't just add a new entity JSON from the response body for a list on UI e.g. if we have pagination/sorting on the server-side.
Based on this information, I have a question. Could a creating/updating endpoint return a resulted list immediately? Or does it violate some best practices? And why?
We can't avoid a second call to a database, but we can avoid a second request to an API.
Could a creating/updating endpoint return a resulted list immediately?
Yes
does it violate some best practices?
No
And why
Because REST is the architectural style of the world wide web.
You GET a web page. It includes a form. You fill in the fields and submit the form. What do you get back...?
Another web page.
When you are creating a machine to machine interface, the same basic ideas hold. There are just a few simple changes
You probably don't want to use media types that are designed for describing displays for human beings, instead preferring something more compact
You want stable semantics, because machines aren't as adaptable as humans when it comes to interpreting implicit schema.
In my API I should return a list of products. In the client (browser) the user can add this products to a cart, increasing, decreasing, or remove this a product from the cart.
In my response with the products list should I put the URLs actions like this:
{
"alias": 'aliasValue',
"removeUrl": 'domain/product/alias/',
"increaseUrl": 'domain/product/alias/increase/',
"decreaseUrl": 'domain/product/alias/decrease/',
...
}
Is this a good practice, I've searched for this but the only thing that I found about URL and API is about the URL structures.
What do you think?
I would advise against reinventing the wheel. There are many ways to use HATEOAS in your API.
Consider, for example, the HAL (Hypertext Application Language) approach, where you have a _links property:
{
"_links": {
"self": {
"href": "http://example.com/api/books/1"
}
},
"id": "1",
"name": "Hypermedia as First-Class Citizen"
}
What you are trying to achieve as a name HATEOAS that stands for Hypermedia as the Engine of Application State.
So if you search for it you will find a lot of formats:
JSON-LD
HAL
SIREN
ION
JSON API
Spring
Ripozo
Source: https://nordicapis.com/tools-to-make-hateoas-compliance-easier/
As REST is just a generatlization of the browsable Web we all know, you can basically apply the same concepts as if you'd implement your system for the browser. In short, a server should provide a client with all the necessary information the client will need to make educated decisions which resources to invoke next.
In a browser-based Web application the interaction model could be similar to invoking the start page, seeing a section in the response that is of interest to you, click a link to learn further details. The next page might list some items where you are provided with further controls to modify this list, i.e. add a new item, remove one and so forth. Upon clicking some "add" button a form is presented to you which teaches you what fields a request should contain and also where this request should be sent to, even if it might not be visible to you. In the back the browser will take care of that for you. The jumping point here is, the server is actually feeding the client with any information needed to proceed through his task, whether it is the choice of available links to explore or the presentation of some guidelines on how a request should look like.
In order to determine whether a link is of interest to a client a server will use meaningful link relation names "attached" to URIs a client should use instead of parsing and interpreting URIs. This allows a server to change URIs anytime without affecting a client. Fielding mentioned the following in one of his blogposts:
A REST API should spend almost all of its descriptive effort in defining the media type(s) used for representing resources and driving application state, or in defining extended relation names and/or hypertext-enabled mark-up for existing standard media types. (Source)
In addtion to that REST APIs shouldn't have typed resources meaningful to clients as this basically couples the client tightly to the API itself and will lead to failures if the serve ever changes anything in regards to the response returned. Instead content-type negotiation should be used in order to let client and server negotiate about the actual representation format used.
A media type defines the processing rules of some payload that is received for a certain Content-Type HTTP header. These rules define both syntax as well as semantics of the document. Servers in a REST architecture are i.e. allowed to reject any messages sent for a certain content type if the rules outlined in the media type are violated.
While the focus on media-types doesn't prevent changes done to the representations received completly, it still is useful in helping to decouple clients from servers further and reduce out-of-band information needed in order to interact with the service. Instead of coupling a client directly to the API, both couple to the media-type actually, and there might be multiple media types they actually couple to. If there ever needs to be a change done to a media-type you can easily introduce a new media type or, similar to HTML, specify within the media-type how backwards compatibility is achived.
In regards to prior, out-of-band information requirements, which REST doesn't completly remove, Fielding stated
Of course the client has prior knowledge. Every protocol, every media type definition, every URI scheme, and every link relationship type constitutes prior knowledge that the client must know (or learn) in order to make use of that knowledge. REST doesn’t eliminate the need for a clue. What REST does is concentrate that need for prior knowledge into readily standardizable forms. That is the essential distinction between data-oriented and control-oriented integration. (Source)
As REST isn't a focus on one single aspect but a conglomeration of all of the aspects mentioned above, your actual question should be tackled from multiple angles.
First, either use existing link relations, i.e. administered by IANA or other microformats, define new ones which you should register with IANA at best or use some semantic web related tags like schema.org. I.e. if you have collections then next, prev, first and last are pretty meaningful (and already registered at IANA) for pagination or item for a decicated item within the list. This collection might have been returned previously as collection before or specified by the respective item in order to go back to the previous collection. If somethin like an add or edit should be done a link-relation like edit-form can teach the client that the URI will return some kind of form that will tell the client how a request to the API will need to look like.
Next, as basic JSON isn't that great in terms of providing help to a client, as all it does is define the syntactical structure of a document but lack support of given the elements meaning, some more advanced media types should be supported. As already mentioned by Cassio and Exadra37 there are a couple of JSON based document types that provide support for HATEOAS (~ URIs and link relation names). Instead of only going for i.e. application/hal+json a multitude of document types would be preferable as this just increases interoperablility with a magnitude of different clients that might come with support for other media types. Note futher that there is nothing wrong with returning a HTML representation as well. REST isn't restricting you to only specific JSON or XML content. I guess most of the time, instead of specifying an own media-type, simply using HTML would be sufficient to carry the meaning of the content from API to server.
You are of course free to create your own media type and use it. In order to increase interoperability you should however standardize it and probably also provide plugins/libraries for third party frameworks so that they are able to use your format as well.
The best advice, though, for sure is to reuse existing standards as the likelihood of other clients already being familiar with such implementations or concepts is way higher than for your custom format. Besides that, it probably also spares you from a lot of work and effort.
Most REST tutorials arranged resources as following:
GET /car/ -> list of cars
GET /car/<id>/ -> info about specific car
POST /car/ -> create a new car
but when building web applications for use in browsers, there is a missing link that are rarely discussed, before you can POST to /car/, you need to GET a form for creating a new resource (car). What should the URL for this form be?
I typically used:
GET /car/new/ -> form for creating a new car
POST /car/new/ -> redirect to /car/<id>/ if item is created else show form with invalid fields highlighted
but according to http://www.slideshare.net/Wombert/phpjp-urls-rest this is not a good REST URL. I can see why it's not a good REST, because "new" is really used as a verb and not a resource, but where should the form be then, because GET /car/ is already used for listing cars, so you can't use GET /car/ for the form for new cars.
In short, my question is: "What is the RESTful URL for 'create resource form'?"
On a slightly related note, even in a web service, it is sometimes not always wise to rely on the client knowing the schema in advance, therefore even in web services there could be a need to be a way for client to request the resource's current schema. AFAICS, this as a similar situation with the need to GET a create form (i.e. the form is sort of like a schema which describes how to construct POST query for creating the resource). Is my line of thought here correct?
REST does not care too much about what your URI looks like as long as it identifies one unique resource and is self-describing. Meet those criteria, and beyond that, it is personal preference. Nothing prohibits using a verb in a URI if it makes sense to use one.
In regards to your slightly related note, what you hint at with the form being a schema is media type. RESTful architecture concerns the client and the server both understanding the media types used to represent the application state.
A REST API should spend almost all of its descriptive effort in
defining the media type(s) used for representing resources and driving
application state, or in defining extended relation names and/or
hypertext-enabled mark-up for existing standard media types. Any
effort spent describing what methods to use on what URIs of interest
should be entirely defined within the scope of the processing rules
for a media type (and, in most cases, already defined by existing
media types).
Read more here: http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven
That is from Roy Fielding, the man who defined REST. In general, your media types should be extensible -- that is, any changes should add on and not break older clients unless necessary.
I always assumed that "form" as such is not a resource, so /<name>/new is okay - forms are not usual elements of APIs. Author of the slides put that on a "bad" list, but didn't provide a correct one - I assume he was so RESTful that he forgot to think about such cases.