Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Hypermedia-friendly REST pattern for creating and updating a resource

I am trying to design a RESTful service that makes a good use of the Hypermedia.
Preferably, the user agent should only know the root URI in order to be able to explore all the functionality of the service - that is, I would like it to be in the 3rd level in the maturity model.

Now, the user agent should be able to create some resources and also edit them at a later time. At create / edit time, the user agent needs access to some other resource / enumerations.

foo resource:

{
    "category" : "category chosen from an enumeration of possible categories",
    "color" : "color chosen from an enumeration of possible colors",
    "aRelatedResource" : "resource identifier from chosen from a collection"
}


Given the previously mentioned requirements, I have come up with the following pattern:

Have a fooRoot resource:

{
    // no properties, only links
    "_links" : { 
        "foos" : { "href" : "URI-to-foos" },
        "fooCreator" : { "href" : "URI-to-plain-fooWriter" }
    }
}

Include a link to a fooWriter in the foo resource:

foo resource:

{
    "category" : "category chosen from an enumeration of possible categories",
    "color" : "color chosen from an enumeration of possible colors",
    "aRelatedResource" : "resource identifier from chosen from a collection",
    "_links" : {
        "self" : {...},
        "fooEditor" : { "href" : "URI-to-fooWriter-initialized-for-current-foo" }
    }
}

A fooWriter would look as follows:

{
    "fooPayload" : {
        "category" : "NULL or pre-initialized",
        "color" : "NULL or pre-initialized",
        "aRelatedResource" : "NULL or pre-initialized"
    },
    "_links" : {
        "fooPayloadDestination" : { "href" : "URI-to-foos-or-foo" },
        "categoryEnum" : { "href" : "URI-to-categories" },
        "colorEnum" : { "href" : "URI-to-colors" },
        "availableResourcesToRelateWith" : { "href" : "some-other-URI" },
        ....
        .... and even something useful for pre-validation etc.
        "validator" : { href : "URI-to-some-resource-or-service" }
    }
}

To sum up, any resource that can be created and edited may have an associated writer resource.
By GET-ting the writer, the user agent can create / edit the resource in a quite convenient manner.
The payload embedded in the writer gets POST-ed to its destination and voilà :)

Also, there should be a root container holding links to both the resource and its writer for new resources (see fooRoot in the example above).



The questions are...

...does the pattern described above have a well-known name?
...is there a better way to solve the create / edit problem, where adjacent resources are required at create / edit time and the 3rd level of maturity still "holds"?

Some references:

  • The Hypermedia scale
  • Richardson Maturity Model
  • A REST API leveraging the hypermedia quite well
like image 359
turdus-merula Avatar asked Aug 28 '14 19:08

turdus-merula


People also ask

What is Hypermedia in REST API?

Hypermedia is an important aspect of REST. It lets you build services that decouple client and server to a large extent and let them evolve independently. The representations returned for REST resources contain not only data but also links to related resources.

What does Hateoas stand for?

Hypermedia as the Engine of Application State (HATEOAS) is a constraint of the REST application architecture that distinguishes it from other network application architectures.

Why use Hypermedia?

One of the key benefits of using hypermedia as opposed to traditional XML-based APIs is that, in addition to providing common parameters for all developers to code within, the server hosting a hypermedia API can also generate a complete list of options (or link relations) available to the client, which can then be ...

What is a REST API stackoverflow?

What is a REST API? A REST API is an application programming interface that conforms to specific architectural constraints, like stateless communication and cacheable data. It is not a protocol or standard.


1 Answers

What you describe reminds me a bit of create and edit form link relations. If you're building an API, however, its use is fairly limited, as you are going to need to someone to program to it regardless of how it's defined.

In my opinion, the easiest way to organize the example you gave above is to define a root menu like this:

GET / HTTP/1.1
Accept: application/hal+json
----
HTTP/1.1 200 OK
Content-Type:application/hal+json

{
    "_links" : { 
        "plants" : { "href" : "/plants" }
    }
}

The plants relation would hold a collection of plant resources defined by a given media type (let's say it's application/vnd.biology-example-org.plant):

GET /plants HTTP/1.1
Accept: application/hal+json
----
HTTP/1.1 200 OK
Content-Type:application/hal+json

{
    "_links" : { 
        "self" : { "href" : "/plants" },
        "plant": [
          {
            "href" : "/plants/parsnip",
            "title" : "The Parsnip",
            "type" : "application/vnd.biology-example-org.plant+json"
          }
        ]
    }
}

TO add a new plant to the collection that's related to the parsnip, POST to the plants collection resource and relate to the parnsip via its link:

POST /plants HTTP/1.1
Content-Type: application/vnd.biology-example-org.plant+json

{
    "title" : "The Carrot - a cousin of the Parsnip",
    "category" : "vegetable",
    "color" : "orange",
    "related" : [ "/plants/parsnip" ]
}
----
HTTP/1.1 201 Created
Location: http://biology.example.org/plants/carrot

To subsequently modify the carrot, issue a PUT to the URL that was returned:

PUT /plants/carrot HTTP/1.1
Content-Type: application/vnd.biology-example-org.plant+json

{
    "title" : "The Carrot - the orange cousin of the Parsnip",
    "category" : "vegetable",
    "color" : "orange",
    "related" : [ "/plants/parsnip" ]
}
----
HTTP/1.1 200 OK

The above example uses the Hypertext Application Language (HAL) to communicate "Level 3" REST semantics using JSON. HAL is simple yet very powerful. One of the conventions I really like is using the relation name as a URI which, when dereferenced, points directly to the documentation about that relation and the resources it can return.

If you want to play around with a live API like this, I'd strongly suggest looking at HALtalk, which is a live demo API of HAL.

like image 68
Jonathan W Avatar answered Sep 21 '22 13:09

Jonathan W