Suppose I have a RESTful API for managing orders which uses HAL to facilitate HATEOAS:
GET /orders/2
{
"_links": {
"self": "/orders/2",
"items": "/orders/2/items"
},
"subtotal": 30.0,
"shipped": false
}
I want to write my client (application) using a set of interfaces so that, assuming that implementations of these interfaces are DI-d/built by DI-d factories, etc., I don't really (want to) have to care that they're backed by my RESTful API. As an example (pseudo C#/Java):
public interface Order {
public void addItem(Item item);
public float getSubtotal();
public boolean getShipped();
}
Order order = ...;
Item item = ...;
order.addItem(item);
...(order.getSubtotal())...;
My question is: can I/does it make sense to generate implementations of the Order/Item interface from the API? By this I mean in a manner similar to that offered with C#/web services which export WSDLs.
I've been thinking about implementing OPTIONS for resources such as /orders and /orders/{id} so that I'd effectively have a HATEOAS API for traversing the schema of the API:
GET /orders/* (I'd need a suitable wildcard of course)
{
"_links": {
"addItem": {
"href": "/orders/{id}/items",
"templated": true,
"type": "method"
}
}
}
Of course I could make this part of the _links object returned with any given resource (/orders/2, for instance) but that precludes static code generation.
I'm wondering if there's a sensible way to encapsulate the fact that if a particular link is provided, the related action should be available/performed, otherwise not.
Note: In case it matters, I'm actually working in JavaScript (specifically with AngularJS). However, I'd still like to write my application using a set of conceptual interfaces/contracts.
My question is: can I/does it make sense to generate implementations
of the Order/Item interface from the API? By this I mean in a manner
similar to that offered with C#/web services which export WSDLs.
It partially makes sense. By a simple CRUD API you can map the resources to the entities. By complex applications it does not work, because you map URIs to resources and METHOD URI pairs to operations. So every time if you need an operation not defined by HTTP, you have to create a new resource or at least a new URI for an already existing resource.
Some examples:
transfer money from one account to another: POST /transfer [acc1, acc2, amount, currency] - the transfer does not necessary exist as an entity in your domain logic (don't try that kind of solution in production code unless you want bankruptcy :D)
sending an email to another user: POST /messages [recipient, message]
you can map resources to value objects too: GET /users/123/address
you can use URIs to map reduce a collection: GET /users?name="John"
you can use PUT /users/123 [details] instead of POST /users [details] to create a new user
you can use POST /player/123/xp/increment 10 instead of PUT /player/123/xp [xp+10] to update the experience points of a player
About the WSDL like solutions you can read alot more here: Third Generation Web APIs - Markus Lanthaler.
My personal opinion that it does not worth the effort to build such a system, because it has more drawbacks than advantages.
Related
Suppose I have a RESTful HATEOAS API which has /posts endpoint which lists posts with a query shortcut /posts/new. How do I query the API to discover /posts/new?
My ideas:
1) Query /posts and get links from _links attribute (and the entities listed are necessary overhead):
GET /posts
{
"docs": [
...
]
"_links": {
"new": { "rel": "posts", "href": "/posts/new" }
}
}
2) Provide this in the API root together with list of resources:
GET /
{
"resources": {
"posts": {
"_links": {
"self": { "rel": "posts", "href": "/posts" }
"new": { "rel": "posts", "href": "/posts/new" }
}
}
}
}
3) I should not use the /posts/new query and instead use /posts and query params. However, if I change my server logic I would have to change client logic too and that would be serve-client coupling. For example:
New messages will be requested by client by somehow providing parameter timestamp > (today - 30)
I introduce draft property and change my idea that new are only the posts with timestamp > (today - 30) && draft = false
I have to change client to add drafts constraint
Note: posts is just an example I am asking in general.
In a REST architecture URIs should be discovered via their accompanying link-relation name. On interpreting your examples above as HAL the URI /post/new has a link-relation name of new. Link relation names provide semantics to URIs which allow clients to determine when to invoke these URIs. HAL is just one of a handful JSON-based media types that support HATEOAS. There are further media-types available that provide a similar job with slightly different syntax and capabilities.
Upon receiving such a document a client would parse the message and build some context for the message containing the actual content including additional metadata like links and further embedded data. If it wants to retrieve the list of the most recent posts it basically needs to look up the key (link-relation name) that expresses the intent (new in your case) from the before-mentioned context in order to retrieve the assigned value (URI). How a client maintains this context is some implementation detail. It might build up a tree-map for easier lookup of "link-relation" keys and their values (URIs) or use some totally different approach.
The knowledge what key to use needs to be present somehow. As link relations express certain semantics they need to be specified somewhere. This can happen in industry standards or media-type definitions. IANA maintains a list of standardized link-relation names and their semantics. On examining the list probably the most likely match according to your specification is current which is defined as
Refers to a resource containing the most recent item(s) in a collection of resources.
I'd therefore propose to change the link-relation name from new to current.
Well, the whole point of the RESTFUL is to make the links discovery easy by making them correspond to the HTTP method used by the client. That means all your links would be simply named /post, the only thing that would change is the htpp method and the parameters they take, which your server would use to determine the actual operation the client wants.
This is a sample from a C# project (notice that the links are all the same, the only changes are the HTTP_METHOD and/or the parameter passed):
List of common http methods: POST, GET, PUT, DELETE
I am struggling with a design aspect of my restful api for templating collections of resources.
The endpoint calls for a json with the name to a particular template and a collections of tokens. The API will then create entries into numerous tables and use the tokens where appropriate.
A very simple example is:
*{
'template': 'DeviceTemplate'
'tokens': [
'customer': 1234,
'serial_number': '12312RF3242a',
'ip_address': '1.1.1.1'
]
}*
This creates a new device for the customer with that ip address along with several other objects, for instance interfaces, device users etc etc. I use the tokens in various places where needed.
I'm not sure how to make this endpoint restful.
The endpoint for /device is already taken if you want to create this resource individually. The endpoint I need is for creating everything via the template.
I want to reserve the POST /template endpoint for creating the actual template itself and not for implementing it with the tokens to create the various objects.
I want to know how to call the endpoint without using a verbs.
I also want to know if its a good idea to structure a POST with a nested JSON.
I'd suggest that you create an action on the template object itself. So right now if you do /templates/<id> you are given an object. You should include in that object a url endpoint for instantiating an instance of that template. Github follows a scheme that I like a lot [1] where within an object there will be a key pointing to another url with a suffix _url. So for instance, your response could be something like:
{
"template": "DeviceTemplate",
"id": "127",
...
"create_url": "https://yourdomain.com/templates/127/create",
...
}
Then this way you treat a POST to that endpoint the same as if this template (DeviceTemplate) was its own resource.
The way to conceptualize this is you're calling a method on an object instead of calling a function.
[1] - For example https://developer.github.com/v3/#failed-login-limit
I was wondering if there were any features hidden in Angular or exposed by some 3rd-party libraries to easily create HATEOAS-compliant Restful clients.
On backend side, I am using Spring Data/REST to produce an HATEOAS JSON API.
Consuming it, though, is quite another story.
For instance, I've got those 3 entities:
Company {name, address}
Employee {firstName, lastName, employer[Company]}
Activity {rate, day, employee[Employee], client[Company]}
and requesting an activity (the most complex entity of the model) produces something like this:
{
links: [],
content: [{
rate: 456,
day: 1366754400000,
links: [{
rel: "self",
href: "http://localhost:8080/api/activities/1"
},
{
rel: "activities.activity.client",
href: "http://localhost:8080/api/activities/1/client"
},
{
rel: "activities.activity.employee",
href: "http://localhost:8080/api/activities/1/employee"
}]
}]
}
My API talks in terms of REST (resources identified by links).
An Activity has an Employee for instance. What I really want to use is : {rate: 456, day: 1366754400000, employee: {firstName:"xxx", lastName:"xxx" ...}}.
However, as you can see in the first output, my Activity only contains a link to the employee, not its data. Is there anything in Angular or in a 3rd-party library to resolve those links and embed the resulting data instead?
Any input on this?
Thanks in advance!
Checkout angular-hateoas. ITs an AngularJS module for using $resource with a HATEOAS-enabled REST API.
You could write a Response Transformation that would inspect your returned object, check for links, and resolve them before returning the response. See the section "Transforming Requests and Responses" in the $http service documentation.
Something like this:
transformResponse: function(rawData) {
var json = JSON.parse( rawData );
forEach( json.content.links, function(link) {
// resolve link...
});
return json;
}
Since the "resolve link" step is itself an $http call, sub-references would also be resolved. HOWEVER, since these are asynchronous, you would likely return a promise instead of the real value; I don't know if the transform function is allowed to do this.
As #charlietfl pointed out, however, please note that this will result in several HTTP calls to return a single entity. Even though I like the concept of HATEOAS, this will likely result in sluggishness if too many calls are made. I'd suggest that your server return the data, or some of it, directly, PLUS the link for details.
Based on your comment about wanting to work with data as against links on the client, I think Restangular would be a good fit.
I've been using angular-hal for one of my projects. It was a Spring HATEOAS backend. And I didn't run into any issues. It handles parametrized resources. I suspect it only supports HAL so since you're using Spring Data Rest you probably have to configure it to generate HAL compliant responses.
I think the confusion may be that you are asking for an Angular solution, when what you really want to do is have Spring Data send a more complete JSON response. I.e, you really just want the server to return the employee data as part of the response JSON, rather than having the client perform extra steps to look it up. I don't know what data store you are using in Spring Data, but the general solution would be to add public getEmployee() method to your Activity class and then annotate the method with #RelatedTo and #Fetch (this would be the setup for Neo4J -- may be different annotations for your flavor of Spring Data). This should cause Spring HATEOAS to include the Employee record within the response for /activity. Hope this helps.
I'm working a REST-ful API in which resources which are fairly interrelated. Resources reference each other, and these references may be created or deleted. I'm a little uncertain how to support associating resources together when they reference each other using hyperlinks.
A simple example follows with two resources, A and B.
Resource A:
name: integer
list_b: [list of resource B]
Resource B:
id: integer
description: String
Now, A does not include B in its document, but rather links to it. When using hypermedia, it might look something like this:
Resource A:
{
id: 1,
list_b: [
{ id: 1, href: "https://server/api/b/1" },
{ id: 2, href: "https://server/api/b/2" }
]
}
If a user wants to add or delete one of the B references in A's list, how do they do so, taking into account the presence of the hyperlink? I want the user to be able to update the entire A resource in one PUT operation, but nothing in the output indicates which value for B is required. It make sense to me for the user to perform PUT with content like this:
Resource A:
{
id: 1,
list_b: [
{ id: 1, href: "https://server/api/b/1" },
{ id: 2, href: "https://server/api/b/2" },
{ id: 3 },
]
}
and receive the updated resource (in the response) like this:
Resource A:
{
id: 1,
list_b: [
{ id: 1, href: "https://server/api/b/1" },
{ id: 2, href: "https://server/api/b/2" },
{ id: 3, href: "https://server/api/b/3" }
]
}
My concern is that the user won't necessarily know what to include in the resource when updating resource A's list_b.
When dealing with hyperlinks from one resource to another, how should creates and updates work? Should clients be allowed to update part of the link (the id), or should they be required to update both parts of the link?
Note: I know another approach might be exposing a sub-url for resource A. It could expose list_b as a resource which is operable via HTTP (allowing clients to use POST, PUT, and DELETE on the list resource itself). But this seems less reasonable when A contains multiple references to other resource types. Each field which references another would potentially require a sub-url, which, if there are 10+ fields, is unwieldy, and requires multiple HTTP requests to update the resource.
HATEOAS connects resources together in a RESTful interface, and it's not clear here whether or not the subsidiary objects you're describing really make sense as independent resources. The "AS" part of HATEOAS reminds us of the role that Web pages play as "resources" in a Web application. Each Web page is really an interactive representation of application state (the "application" in this case being a classical, multiple-page Web application), and the hyperlinks to other resources provide the user with transitions to other application states.
A RESTful Web API, having JavaScript code rather than human beings as its client, is naturally data-access-oriented, so few if any of its resources take the form of "application state," per se. In a tradition Web application, you can draw a state transition diagram and clearly see the connections among states, and thus among resources. In a RESTful API, the boundaries among passive data resources are motivated more by the efficiencies of client/server interactions and other subtle forces.
So do your subsidiary objects ("B") here really need to be represent as first-class resources? Are there instances where the front end will enumerate or otherwise access them independent of the aggregates in which they participate ("A")?
If the answer is "no," then they obviously shouldn't be represented hyptertextually in the "A" structure. I presume that the answer is "yes," however, and that you also have good reason to offer all of the other subsidiary objects to which you refer as independent resources. In this case, there's some amount of interface work in the form of routes and controllers that is necessary to support all of those resources no matter what, because your application is presumably providing a means to manipulate them each on their own, or at least query them (through hyperlinks such as those in your example).
This being the case, a POST to the path representing your collection of "B" objects (e.g., "server/api/b") can return a URL in the response's "location" header value as POSTs that create new resources are supposed to do. When your user interactively adds a new "B" to a list belonging to an "A" on your Web page, your front end can first POST the new "B," getting its URL back through the location header on success. It can then incorporate that link into the list representation inside its "A" object before PUTting the updated "A."
The ID value is a bit of a wrinkle, as you'll be tempted to break the encapsulation of the back end by extracting the ID value from the text of the URL. True HATEOAS zealots make their RESTful APIs produce obfuscated, hashed or otherwise unintelligible URLs specifically to frustrate such encapsulation-breaking on the part of clients. Better that the POST of the new "B" object returns a complete representation of the new "B" object, including its ID, in its response body, so that the client can reconstitute the full object and extract the ID from it, thus narrowing the coupling to the resource itself and not the details of the RESTful interface through which it is obtained.
You should also look at the LINK method:
LINK /ResourceA/1 HTTP/1.1
Link: <http://example.com/ResourceB/3>; rel="list_b"
...
204 Yeah Fine, Whatever
This tells /ResourceA/1 to link to /ResourceB/3 using the relationship "list_b".
I am writing a RESTful service for a customer management system and I am trying to find the best practice for updating records partially. For example, I want the caller to be able to read the full record with a GET request. But for updating it only certain operations on the record are allowed, like change the status from ENABLED to DISABLED. (I have more complex scenarios than this)
I don't want the caller to submit the entire record with just the updated field for security reasons (it also feels like overkill).
Is there a recommended way of constructing the URIs? When reading the REST books RPC style calls seem to be frowned upon.
If the following call returns the full customer record for the customer with the id 123
GET /customer/123
<customer>
{lots of attributes}
<status>ENABLED</status>
{even more attributes}
</customer>
how should I update the status?
POST /customer/123/status
<status>DISABLED</status>
POST /customer/123/changeStatus
DISABLED
...
Update: To augment the question. How does one incorporate 'business logic calls' into a REST api? Is there an agreed way of doing this? Not all of the methods are CRUD by nature. Some are more complex, like 'sendEmailToCustomer(123)', 'mergeCustomers(123, 456)', 'countCustomers()'
POST /customer/123?cmd=sendEmail
POST /cmd/sendEmail?customerId=123
GET /customer/count
You basically have two options:
Use PATCH (but note that you have to define your own media type that specifies what will happen exactly)
Use POST to a sub resource and return 303 See Other with the Location header pointing to the main resource. The intention of the 303 is to tell the client: "I have performed your POST and the effect was that some other resource was updated. See Location header for which resource that was." POST/303 is intended for iterative additions to a resources to build up the state of some main resource and it is a perfect fit for partial updates.
You should use POST for partial updates.
To update fields for customer 123, make a POST to /customer/123.
If you want to update just the status, you could also PUT to /customer/123/status.
Generally, GET requests should not have any side effects, and PUT is for writing/replacing the entire resource.
This follows directly from HTTP, as seen here: http://en.wikipedia.org/wiki/HTTP_PUT#Request_methods
You should use PATCH for partial updates - either using json-patch documents (see https://datatracker.ietf.org/doc/html/draft-ietf-appsawg-json-patch-08 or http://www.mnot.net/blog/2012/09/05/patch) or the XML patch framework (see https://www.rfc-editor.org/rfc/rfc5261). In my opinion though, json-patch is the best fit for your kind of business data.
PATCH with JSON/XML patch documents has very strait forward semantics for partial updates. If you start using POST, with modified copies of the original document, for partial updates you soon run into problems where you want missing values (or, rather, null values) to represent either "ignore this property" or "set this property to the empty value" - and that leads down a rabbit hole of hacked solutions that in the end will result in your own kind of patch format.
You can find a more in-depth answer here: http://soabits.blogspot.dk/2013/01/http-put-patch-or-post-partial-updates.html.
I am running into a similar problem. PUT on a sub-resource seems to work when you want to update only a single field. However, sometimes you want to update a bunch of things: Think of a web form representing the resource with option to change some entries. The user's submission of form should not result in a multiple PUTs.
Here are two solution that I can think of:
do a PUT with the entire resource. On the server-side, define the semantics that a PUT with the entire resource ignores all the values that haven't changed.
do a PUT with a partial resource. On the server-side, define the semantics of this to be a merge.
2 is just a bandwidth-optimization of 1. Sometimes 1 is the only option if the resource defines some fields are required fields (think proto buffers).
The problem with both these approaches is how to clear a field. You will have to define a special null value (especially for proto buffers since null values are not defined for proto buffers) that will cause clearing of the field.
Comments?
RFC 7396: JSON Merge Patch (published four years after the question was posted) describes the best practices for a PATCH in terms of the format and processing rules.
In a nutshell, you submit an HTTP PATCH to a target resource with the application/merge-patch+json MIME media type and a body representing only the parts that you want to be changed/added/removed and then follow the below processing rules.
Rules:
If the provided merge patch contains members that do not appear within the target, those members are added.
If the target does contain the member, the value is replaced.
Null values in the merge patch are given special meaning to indicate the removal of existing values in the target.
Example test cases that illustrate the rules above (as seen in the appendix of that RFC):
ORIGINAL PATCH RESULT
--------------------------------------------
{"a":"b"} {"a":"c"} {"a":"c"}
{"a":"b"} {"b":"c"} {"a":"b",
"b":"c"}
{"a":"b"} {"a":null} {}
{"a":"b", {"a":null} {"b":"c"}
"b":"c"}
{"a":["b"]} {"a":"c"} {"a":"c"}
{"a":"c"} {"a":["b"]} {"a":["b"]}
{"a": { {"a": { {"a": {
"b": "c"} "b": "d", "b": "d"
} "c": null} }
} }
{"a": [ {"a": [1]} {"a": [1]}
{"b":"c"}
]
}
["a","b"] ["c","d"] ["c","d"]
{"a":"b"} ["c"] ["c"]
{"a":"foo"} null null
{"a":"foo"} "bar" "bar"
{"e":null} {"a":1} {"e":null,
"a":1}
[1,2] {"a":"b", {"a":"b"}
"c":null}
{} {"a": {"a":
{"bb": {"bb":
{"ccc": {}}}
null}}}
For modifying the status I think a RESTful approach is to use a logical sub-resource which describes the status of the resources. This IMO is pretty useful and clean when you have a reduced set of statuses. It makes your API more expressive without forcing the existing operations for your customer resource.
Example:
POST /customer/active <-- Providing entity in the body a new customer
{
... // attributes here except status
}
The POST service should return the newly created customer with the id:
{
id:123,
... // the other fields here
}
The GET for the created resource would use the resource location:
GET /customer/123/active
A GET /customer/123/inactive should return 404
For the PUT operation, without providing a Json entity it will just update the status
PUT /customer/123/inactive <-- Deactivating an existing customer
Providing an entity will allow you to update the contents of the customer and update the status at the same time.
PUT /customer/123/inactive
{
... // entity fields here except id and status
}
You are creating a conceptual sub-resource for your customer resource. It is also consistent with Roy Fielding's definition of a resource: "...A resource is a conceptual mapping to a set of entities, not the entity that corresponds to the mapping at any particular point in time..." In this case the conceptual mapping is active-customer to customer with status=ACTIVE.
Read operation:
GET /customer/123/active
GET /customer/123/inactive
If you make those calls one right after the other one of them must return status 404, the successful output may not include the status as it is implicit. Of course you can still use GET /customer/123?status=ACTIVE|INACTIVE to query the customer resource directly.
The DELETE operation is interesting as the semantics can be confusing. But you have the option of not publishing that operation for this conceptual resource, or use it in accordance with your business logic.
DELETE /customer/123/active
That one can take your customer to a DELETED/DISABLED status or to the opposite status (ACTIVE/INACTIVE).
Things to add to your augmented question. I think you can often perfectly design more complicated business actions. But you have to give away the method/procedure style of thinking and think more in resources and verbs.
mail sendings
POST /customers/123/mails
payload:
{from: x#x.com, subject: "foo", to: y#y.com}
The implementation of this resource + POST would then send out the mail. if necessary you could then offer something like /customer/123/outbox and then offer resource links to /customer/mails/{mailId}.
customer count
You could handle it like a search resource (including search metadata with paging and num-found info, which gives you the count of customers).
GET /customers
response payload:
{numFound: 1234, paging: {self:..., next:..., previous:...} customer: { ...} ....}
Use PUT for updating incomplete/partial resource.
You can accept jObject as parameter and parse its value to update the resource.
Below is the Java function which you can use as a reference :
public IHttpActionResult Put(int id, JObject partialObject) {
Dictionary < string, string > dictionaryObject = new Dictionary < string, string > ();
foreach(JProperty property in json.Properties()) {
dictionaryObject.Add(property.Name.ToString(), property.Value.ToString());
}
int id = Convert.ToInt32(dictionaryObject["id"]);
DateTime startTime = Convert.ToDateTime(orderInsert["AppointmentDateTime"]);
Boolean isGroup = Convert.ToBoolean(dictionaryObject["IsGroup"]);
//Call function to update resource
update(id, startTime, isGroup);
return Ok(appointmentModelList);
}
Check out http://www.odata.org/
It defines the MERGE method, so in your case it would be something like this:
MERGE /customer/123
<customer>
<status>DISABLED</status>
</customer>
Only the status property is updated and the other values are preserved.
Regarding your Update.
The concept of CRUD I believe has caused some confusion regarding API design. CRUD is a general low level concept for basic operations to perform on data, and HTTP verbs are just request methods (created 21 years ago) that may or may not map to a CRUD operation. In fact, try to find the presence of the CRUD acronym in the HTTP 1.0/1.1 specification.
A very well explained guide that applies a pragmatic convention can be found in the Google cloud platform API documentation. It describes the concepts behind the creation of a resource based API, one that emphasizes a big amount of resources over operations, and includes the use cases that you are describing. Although is a just a convention design for their product, I think it makes a lot of sense.
The base concept here (and one that produces a lot of confusion) is the mapping between "methods" and HTTP verbs. One thing is to define what "operations" (methods) your API will do over which types of resources (for example, get a list of customers, or send an email), and another are the HTTP verbs. There must be a definition of both, the methods and the verbs that you plan to use and a mapping between them.
It also says that, when an operation does not map exactly with a standard method (List, Get, Create, Update, Delete in this case), one may use "Custom methods", like BatchGet, which retrieves several objects based on several object id input, or SendEmail.
It doesn't matter. In terms of REST, you can't do a GET, because it's not cacheable, but it doesn't matter if you use POST or PATCH or PUT or whatever, and it doesn't matter what the URL looks like. If you're doing REST, what matters is that when you get a representation of your resource from the server, that representation is able give the client state transition options.
If your GET response had state transitions, the client just needs to know how to read them, and the server can change them if needed. Here an update is done using POST, but if it was changed to PATCH, or if the URL changes, the client still knows how to make an update:
{
"customer" :
{
},
"operations":
[
"update" :
{
"method": "POST",
"href": "https://server/customer/123/"
}]
}
You could go as far as to list required/optional parameters for the client to give back to you. It depends on the application.
As far as business operations, that might be a different resource linked to from the customer resource. If you want to send an email to the customer, maybe that service is it's own resource that you can POST to, so you might include the following operation in the customer resource:
"email":
{
"method": "POST",
"href": "http://server/emailservice/send?customer=1234"
}
Some good videos, and example of the presenter's REST architecture are these. Stormpath only uses GET/POST/DELETE, which is fine since REST has nothing to do with what operations you use or how URLs should look (except GETs should be cacheable):
https://www.youtube.com/watch?v=pspy1H6A3FM,
https://www.youtube.com/watch?v=5WXYw4J4QOU,
http://docs.stormpath.com/rest/quickstart/