Skip to content

Latest commit

 

History

History
147 lines (116 loc) · 3.98 KB

5.1.creating-event-with-put.md

File metadata and controls

147 lines (116 loc) · 3.98 KB

Creating event with PUT

Story

As an API publisher I want allow consumers to construct event identifiers So that they can control the URLs.

As an API consumer I want to be able to create new resources idempotently So I can retry safely.

Usage

const event = {
    "@context": "/api/context.jsonld",
    "@type": "schema:Event",
    "eventName": "My brand new event",
    "eventDescription": "Hope it will work",
    "startDate": "2017-04-19",
    "endDate": "2017-04-19"
};
const templateVariables = {
    slug: [
        "meeting",
        "with-will"
    ]
};

const operation = await hydraClient
    .getResource("http://example.com/events")
    .hypermedia
    .operations.ofType("http://schema.org/CreateAction")
    .withTemplate()
    .first();

await hydraClient.invoke(operation.expandTarget(templateVariables), event);

Details

To create an Event using PUT, the collection resource has to be linked to the actual target of the operation. The target of the operation can either be a concrete URL or an IriTemplate as shown in the example above. Concrete URLs are out of scope for this use case and might be discussed at a later point in a separate use case document.

GET /api/events
HTTP 200 OK
{
    "@context": "/api/context.jsonld",
    "@id": "/api/events",
    "@type": "Collection",
    "manages": {
      "property": "rdf:type",
      "object": "schema:Event"
    },
    "totalItems": 0,
    "members": [ ],
    "memberTemplate": {
        "@type": "IriTemplate",
        "template": "http://example.com/api/event{/slug*}",
        "variableRepresentation": "BasicRepresentation",
        "mapping": [
            {
                "@type": "IriTemplateMapping",
                "variable": "slug",
                "property": "schema:name",
                "required": true
            }
        ],
        "operation": [
          {
            "@type": [ "Operation", "schema:CreateAction" ],
            "title": "Create new event",
            "method": "PUT",
            "expects": "schema:Event"
          }
        ]
    }
}

Upon executing the snippet above the following request will be sent to the server:

PUT /api/event/meeting/with-will HTTP/1.1
{
    "@context": "/api/context.jsonld",
    "@type": "schema:Event",
    "eventName": "My brand new event",
    "eventDescription": "Hope it will work",
    "startDate": "2017-04-19",
    "endDate": "2017-04-19"
}
HTTP/1.1 201 Created

Considerations

Requesting an existing URI

It is possible that the identifier constructed by filling in IriTemplate variables already contains a representation of an event. By definition of the PUT method the server would replace the resource if it already exists.

If that is not the intended behavior, the client should add If-None-Match: * to request headers. The asterisk value instructs the server to reject the update if any representation already exists.

client.invoke(operationWithTargetExpanded, event, {
    headers: {
        'If-None-Match': '*'
    }
});

In such case it would respond with HTTP/1.1 412 Precondition Failed status.

Advertising connection between collection and created event

The schema:CreateAction operation is attached to collection's memberTemplate which informs the client that the newly created event will become part of the collection, i.e. it's "member" property. However, such operation can have an effect on more that one related resource. Building upon this example, in a more elaborate setting creating a personal event could also add that event to the events collection of all participants.

There can be many such cases and defining all possible side effect is currently outside of Hydra's scope.

That said, this technique can be used also outside the scope od collections.