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.