Supported from Cordra v2.3.0.
This section describes the Digital Object Interface Protocol (DOIP) API that HTTP clients can use to interact with Cordra. DOIP API is an RPC-style API designed to be comfortable to develop against, with easy-to-construct URLs and JSON message bodies that convey the essence of DOIP requests and responses. Readers familiar with the DOIP v2 specification may refer to Design Approach to learn how the DOIP message model is mapped to this API.
This documentation is available as an OpenAPI specification, either in HTML or JSON form.
The design of this API is a manifestation of the Digital Object Architecture in which all API requests are seen uniformly as
a specified client
performing a specified operation
on a specified digital object
where a digital object conforms to a specified data model presenting an identifier, a type, and a collection of attributes and elements. The service (Cordra, in this case) managing the digital objects is also considered a digital object.
In all cases, identification of the digital object, operation, service, or client is as a Handle:
the client identifier is the identifier of its User digital object in the system
the Cordra service identifier is a fixed identifier (<prefix>/service for purposes of this document)
the identifiers of the available operations are documented below
the identifier of the target digital object is the identifier of the relevant object in the system.
A request can be made with either GET or POST. Only some operations
(generally read-only operations) allow GET. Requests target a URL, which
is <base URL>/doip
. The base URL is constant and will be the domain name
(and optionally port) where Cordra is made available (e.g., https://localhost:8443). The examples in
this document will use /doip
as a shorthand for the target URL.
The query string (after ?) of the URL accepts the following parameters:
operationId
, or o
: required, the identifier of the operation to perform; can also be sent in the path after /doip/
targetId
, or t
: required, the identifier of the target object
clientId
, or c
: the identifier of the caller; this can be implicit in the
authentication header sent, in which case it need not be included as
a query parameter
attributes
, or a
: arbitrary JSON to inform the operation
For convenience, attributes as a JSON object can be expressed as multiple properties with dot separated names. Each such property is combined into the structure of a JSON object. Additionally, query parameters which are not reserved (see Non-reserved Query Parameters) are also combined into the attributes.
For example, all of the following represent the same request:
GET /doip?...&attributes={"query":"foo","pageSize":10}
GET /doip?...&a={"query":"foo","pageSize":10}
GET /doip?...&attributes.query=foo&attributes.pageSize=10
GET /doip?...&a.query=foo&a.pageSize=10
GET /doip?...&query=foo&pageSize=10
If the value of a query parameter for attributes is valid JSON, then it is parsed as JSON. Otherwise, the value is interpreted as a string.
Finally the “input” to the operation is the POST body, when present. In
general it does not matter which Content-Type header is sent, except to
avoid certain tools defaulting to the special value
application/x-www-form-urlencoded
. See next section for more details
about this special value.
In certain circumstances (for example, very complicated search queries),
it is possible for the query string of the URL to become long enough to
potentially be an issue for HTTP servers or middleware. In such a
circumstance the same request can be sent using POST with Content-Type:
application/x-www-form-urlencoded
, as is common in HTTP APIs. Such a
POST behaves as if the POST body were appended to the query string of
the URL.
For example
GET /doip?...&attributes.query=something%20very%20long
could be equivalently sent as
POST /doip?...
Content-Type: application/x-www-form-urlencoded
attributes.query=something%20very%20long
For this reason it is important to set an appropriate Content-Type
header for a POST body intended to be the input to an operation; often
this will be Content-Type: application/json
.
Authentication can be sent using the standard HTTP Authorization: header, which is translated into the “authentication” property of the DOIP request.
For example, authentication via username and password uses the standard HTTP Basic auth:
Authorization: Basic dXNlckBleGFtcGxlLm9yZzpwYXNzd29yZA==
and authentication can use an access token (bearer token) acquired using the Access Token operations:
Authorization: Bearer 1frevxlceojr3ylc92q2awh3e
See below for detail on acquiring access tokens.
The response will include a header Doip-Response, the value of which is a JSON object, which has a “status” property indicating the DOIP status of the response, and sometimes an “attributes” property with additional data about the response.
The HTTP status code of the response will be set as appropriate for the DOIP status code, and will be one of
200 |
The request was processed successfully |
400 |
There was something wrong with the structure or content of the request |
401 |
The client must authenticate to perform the attempted operation |
403 |
The client was not permitted to perform the attempted operation |
404 |
The requested digital object could not be found |
500 |
There was an internal server error |
The DOIP status code (and corresponding HTTP status code) indicates the
nature of the response; responses with DOIP status code other than
“0.DOIP/Status.001” (HTTP status code other than 200) are error
responses. Error responses will return a response body of Content-Type:
application/json
which is an object with (at minimum) the property
“message”, a description of the error.
The output of a successful response is contained in the response body.
It will often have Content-Type: application/json
. Details about the
structure of the response body is given in the description of each of
the operations.
A summary of various operations along with their identifiers and descriptions is listed below. Operation identifiers that begin with 0.DOIP are defined in DOIP v2 specification. Operation identifiers that begin with 20.DOIP represent Cordra-specific operations.
Operation |
Target |
Description |
---|---|---|
20.DOIP/Op.Auth.Token |
Service |
Create a new access token |
20.DOIP/Op.Auth.Introspect |
Service |
Get access token information |
20.DOIP/Op.Auth.Revoke |
Service |
Invalidate access token |
20.DOIP/Op.BatchUpload |
Service |
Batch upload a list of digital objects |
20.DOIP/Op.ReindexBatch |
Service |
Causes the specified objects to be reindexed |
20.DOIP/Op.Relationships.Get |
Object |
Get the list of objects related by handles to the target object |
20.DOIP/Op.Versions.Publish |
Object |
Publish a new version of the target object |
20.DOIP/Op.Versions.Get |
Object |
Get the published versions of the target object |
20.DOIP/Op.GetDesign |
Service |
Get the design and schemas for the system |
20.DOIP/Op.GetInitData |
Service |
Get a summary of server version, design and current session |
0.DOIP/Op.Hello |
Service |
Get a hello response from the service |
0.DOIP/Op.ListOperations |
Object |
Get the list of operations the caller can perform on the target object |
0.DOIP/Op.Create |
Service |
Create a digital object |
0.DOIP/Op.Retrieve |
Object |
Retrieve a digital object |
0.DOIP/Op.Update |
Object |
Update a digital object |
0.DOIP/Op.Delete |
Object |
Delete a digital object |
0.DOIP/Op.Search |
Service |
Search for digital objects |
For the convenience of users, short aliases are enabled for referring to the service identifier and to operation identifiers.
In the case of the service identifier, targetId=service
is considered to
be a shortcut for targetId=<prefix>/service
.
The following table shows operation aliases usable with Cordra.
Operation Alias |
Operation Handle |
---|---|
Auth.Token |
20.DOIP/Op.Auth.Token |
Auth.Introspect |
20.DOIP/Op.Auth.Introspect |
Auth.Revoke |
20.DOIP/Op.Auth.Revoke |
Create |
0.DOIP/Op.Create |
Retrieve |
0.DOIP/Op.Retrieve |
Update |
0.DOIP/Op.Update |
Delete |
0.DOIP/Op.Delete |
Many of the operations shown below work with the structure of a Digital Object. In general, a Digital Object has a unique resolvable identifier under “id”, a “type”, further JSON called “attributes”, and metadata about “elements” which are (in general) binary payloads associated with the object such as images.
As used with Cordra, “attributes” will always have two top-level properties “content” (the actual type-specific JSON content of the digital object) and “metadata” which is Cordra-maintained metadata such as creation and modification timestamps. Note that depending on the authenticated user, some of the information may be omitted.
For many applications, the most useful part of the structure will be the JSON content of the digital object under “content”.
The access token operations can be used to obtain an access token, check its status, and delete it.
A valid access token can be provided, instead of authentication credentials, for various operations. The system provides an access token only after a successful authentication, and by default the token is valid for 30 minutes from last use. Each valid use renews the lifetime.
Security and performance improvements are usually noted with the use of tokens instead of authentication credentials.
Access token may be sent to operations (other than create access token operation) using an Authorization Bearer header. For example:
Authorization: Bearer ACCESS_TOKEN
Only POST. Target is the service.
The operation input is a JSON object specifying “grant_type”: “password”, to indicate that the user is authenticating via username/password, together with the user object identifier (or username) and the password. Note that the HTTPS transport ensures that this is sent encrypted over the network.
The operation output is a JSON object specifying the “access_token” together with certain other informative fields notably “userId”.
The properties of the response object:
access_token: The newly created access token.
token_type: Always “Bearer”.
active: Whether or not the token is active; always “true” for successful calls of the /auth/token API.
username: Username of the authenticated user
userId: UserId of the authenticated user
Example request:
POST /doip?operationId=20.DOIP/Op.Auth.Token&targetId=service&attributes.full=true
Content-Type: application/json;charset=utf-8
{
"grant_type": "password",
"username": "test@example.org",
"password": "password",
}
Response:
HTTP/1.1 200 OK
Content-Type: application/json;charset=utf-8
{
"access_token": "14f874o9i4ohgjv19bds6wvov",
"token_type": "Bearer",
"active": "true",
"username": "test@example.org",
"userId": "<prefix>/NVSJGF5G"
}
Only POST. Target is the service.
The operation input is a JSON object specifying “token”, the access token to introspect.
The operation output is a JSON object specifying whether the supplied token is “active” and also certain other informative fields notably “userId”.
The properties of the response object:
active: Whether or not the token is active.
username: Username of the authenticated user
userId: UserId of the authenticated user
Example request:
POST /doip?operationId=20.DOIP/Op.Auth.Introspect&targetId=service&attributes.full=true
Content-Type: application/json;charset=utf-8
{
"token": "14f874o9i4ohgjv19bds6wvov"
}
Response:
HTTP/1.1 200 OK
Content-Type: application/json;charset=utf-8
{
"active": "true",
"username": "test@example.org",
"userId": "<prefix>/NVSJGF5G"
}
Only POST. Target is the service.
Token revocation would typically occur when a user logs out of the system.
Example request:
POST /doip?operationId=20.DOIP/Op.Auth.Revoke&targetId=service
Content-Type: application/json;charset=utf-8
{
"token": "14f874o9i4ohgjv19bds6wvov"
}
Response:
HTTP/1.1 200 OK
Content-Type: application/json;charset=utf-8
{
"active": "false"
}
Only POST. Target is the service.
Creation of objects sends operation 0.DOIP/Op.Create to the service object. Regardless of the type of the digital object in the system, the same operation is used. The input should be a Digital Object specifying the “type” to be created and the “content”. The output will be the Digital Object with its new “id” and “metadata” and possibly changes to the “content” automatically populated by the system.
Example request:
POST /doip?operationId=0.DOIP/Op.Create&targetId=service
Content-Type: application/json;charset=utf-8
{
"type": "Document",
"attributes": {
"content": {
"name": "My Document",
...
}
}
}
Response:
HTTP/1.1 200 OK
Content-Type: application/json;charset=utf-8
{
"id": "<prefix>/MZ6W9D3T",
"type": "Document",
"attributes": {
"content": {
"id": "<prefix>/MZ6W9D3T",
"name": "My Document",
...
},
"metadata": {
"createdOn": 1607709592349,
"createdBy": "admin",
"modifiedOn": 1607709906109,
"modifiedBy": "admin"
}
}
}
Allows GET or POST. Target is the specific digital object to be retrieved.
Retrieval of objects from the system is done using the operation 0.DOIP/Op.Retrieve. Regardless of the type of the digital object in the system, the same operation is used. Retrieval returns a JSON response with a Digital Object structure, which includes the identifier, the type, system-maintained metadata, plus of course the type-specific content of the object.
An element (instead of object metadata) can be retrieved using the
request attribute attributes.element=elementName
.
Example request:
GET /doip?operationId=0.DOIP/Op.Retrieve&targetId=<prefix>/MZ6W9D3T
Response:
HTTP/1.1 200 OK
Content-Type: application/json;charset=utf-8
{
"id": "<prefix>/MZ6W9D3T",
"type": "Document",
"attributes": {
"content": {
"id": "<prefix>/MZ6W9D3T",
"name": "My Document",
...
},
"metadata": {
"createdOn": 1607709592349,
"createdBy": "admin",
"modifiedOn": 1607709906109,
"modifiedBy": "admin"
}
}
}
Only POST. Target is the digital object to be updated.
To update an object send operation 0.DOIP/Op.Update with the target the object to be updated. Regardless of the type of the digital object in the system, the same operation is used. The input should be a Digital Object specifying the new “content” (keeping the “id”, “type”, and other properties not in the content is fine but optional) as a complete replacement. The output will be the Digital Object with its new “metadata” and possibly changes to the “content” automatically populated by the system.
Example request:
POST /doip?operationId=0.DOIP/Op.Update&targetId=<prefix>/MZ6W9D3T
Content-Type: application/json;charset=utf-8
{
"attributes": {
"content": {
"name": "My Document",
"description": "Updated description",
...
}
}
}
Response:
HTTP/1.1 200 OK
Content-Type: application/json;charset=utf-8
{
"id": "<prefix>/MZ6W9D3T",
"type": "Document",
"attributes": {
"content": {
"id": "<prefix>/MZ6W9D3T",
"name": "My Document",
"description": "Updated description",
...
},
"metadata": {
"createdOn": 1607709592349,
"createdBy": "admin",
"modifiedOn": 1607899161123,
"modifiedBy": "admin"
}
}
}
Only POST. Target is the digital object to be deleted.
To delete an object send operation 0.DOIP/Op.Delete with, as the targetId, the id of the object to be deleted. Regardless of the type of the digital object in the system, the same operation is used. The input and output (in the case of success) are empty.
Example request:
POST /doip?operationId=0.DOIP/Op.Delete&targetId=<prefix>/MZ6W9D3T
Response:
HTTP/1.1 200 OK
Allows GET or POST. Target is the service.
Request attributes (send as query parameters, or in a POST body of
Content-Type: application/x-www-form-urlencoded
, or in a POST body of
Content-Type: application/json
):
“query”: the search to be performed, in Lucene syntax; see below
“pageNum”: the page number to be returned, starting with 0
“pageSize”: the page size to be returned; if missing or negative, all results will be returned; if zero, no results are returned, but the “size” and, if requested, the “facets” are still returned
“sortFields”: a comma-separated list of sort specifications, each of which is a field name optionally followed by ASC or DESC
“type”: either “id”, to return just object ids, or “full”, to return full object data; defaults to “full”
“facets”: a JSON array of objects that contain the fields to facet results by
“filterQueries”: a JSON array of query strings to filter the results by
“includeScore”: a boolean which if true will cause the results to include attributes “responseContext” with “score” properties, populated by the index service
“includeVersions”: a boolean which if true will cause the results to include Cordra version objects which (see Digital Object Versioning)
Output is a JSON object with top-level properties:
“size”: the number of results across all pages
“facets”: only included if “facets” are specified in the request. A list of counts by bucket for each facet in the request. Each bucket for a facet also includes a “filterQuery” that can be sent in a subsequent request under “filterQueries” to further restrict the results
“results”: a list of results, each of which is either a string (the object id) or the JSON structure of a digital object
The query syntax is the Lucene syntax used by Lucene, Solr, and Elasticsearch. Here are three versions of the equivalent documentation from the three providers:
This syntax supports fielded search, where the fields use JSON Pointer (RFC 6901) format to specify locations in the structure of the object “content” (but the field names for JSON Pointers into arrays have particular indices replaced with underscore _ in order to allow searching the entire array).
For more information and detailed examples about the query syntax see Query Syntax.
Example request:
GET /doip?operationId=0.DOIP/Op.Search&targetId=service&attributes.query=%2Btype:Document%20%2B/name:My
Response:
HTTP/1.1 200 OK
Content-Type: application/json;charset=utf-8
{
"size": 123,
"results": [
{
"id": "<prefix>/MZ6W9D3T",
"type": "Document",
"attributes": {
"content": {
"id": "<prefix>/MZ6W9D3T",
"name": "My Document",
...
},
"metadata": {
...
}
}
},
...
]
}
Request attributes:
“format”: optional, may take the value “ndjson” to send objects as newline separated JSON objects. If omitted the request body should either be an array of Digital Objects or an object containing a “results” property that contains an array of Digital Objects. The three input formats are shown below:
New line separated objects:
{}
{}
{}
Array of objects:
[
{}
{}
{}
]
An object containing a results array:
{
"results": [
{}
{}
{}
]
}
“pageNum”: the page number to be returned, starting with 0
If an object in the request contains an id the operation will either update the corresponding object or create a new one with the specified id. Whereas if an object in the request does not contain an id a create will be performed by the server assigning a new id to the object.
Example request:
POST /doip?operationId=20.DOIP/Op.BatchUpload&targetId=service
Content-Type: application/json;charset=utf-8
POST Data:
[
{
"type": "Foo",
"attributes": {
"content": {}
}
},
{
"id": "test/e4673f57012b544e72af",
"type": "Foo",
"attributes": {
"content": {}
}
}
]
Response:
{
"results": [
{
"position": 0,
"responseCode": 200,
"response": {
"id": "test/6c02a2e0fe9914fca063",
"type": "Foo",
"content": {},
"metadata": {
"createdOn": 1657222566407,
"createdBy": "admin",
"modifiedOn": 1657222566407,
"modifiedBy": "admin",
"txnId": 1657222566407004
}
}
},
{
"position": 1,
"responseCode": 200,
"response": {
"id": "test/e4673f57012b544e72af",
"type": "Foo",
"content": {},
"metadata": {
"createdOn": 1657222541865,
"createdBy": "admin",
"modifiedOn": 1657222566421,
"modifiedBy": "admin",
"txnId": 1657222566408005
}
}
}
],
"success": true
}
The data of an element can be included in the json as a base64 string:
Example request:
POST /doip?operationId=20.DOIP/Op.BatchUpload&targetId=service
Content-Type: application/json;charset=utf-8
POST Data:
[
{
"id": "test/e4673f57012b544e72af",
"type": "Foo",
"attributes": {
"content": {}
},
"elements": [
{
"id": "element1",
"type": "text/plain",
"base64Element": "SGVsbG8sIGVsZW1lbnRzIQ=="
}
]
}
]
The special attribute “elementsToDelete” can be set on the object to list the elements that should be deleted from an existing object.
Example request:
POST /doip?operationId=20.DOIP/Op.BatchUpload&targetId=service
Content-Type: application/json;charset=utf-8
POST Data:
[
{
"id": "test/e4673f57012b544e72af",
"type": "Foo",
"attributes": {
"content": {},
"elementsToDelete": [
"element1"
]
}
}
]
Given an array of object ids in the POST body the server will retrieve those objects from storage and caused them to be reindexed by the indexing service.
Request attributes:
“lockObjects”: optional boolean, defaults to true. If true the ids from the batch of objects are locked while being reindexed.
“query”: optional string. Instead of supplying a list of ids to reindex a query can be sent instead. The query will be run server side and the results will be reindexed.
“all”: optional boolean. Instead of supplying a list of ids to reindex, all stored objects will be reindexed.
Example request:
POST /doip?operationId=20.DOIP/Op.ReindexBatch&targetId=service
Content-Type: application/json;charset=utf-8
POST Data:
[
"test/bc8e231bb247ce2a2a76",
"test/dd36b5b638e97e6c608f"
]
Request attributes:
“outboundOnly”: optional boolean, defaults to false. By default the response will show objects that the target object points at as well as objects that point at the target. Setting this attribute to true restricts the results to only those the target points at.
Example request:
POST /doip/?targetId=test/d39366ae3f76b6f41384&operationId=20.DOIP/Op.Relationships.Get
Response:
{
"nodes": [
{
"id": "test/d39366ae3f76b6f41384",
"label": "test/d39366ae3f76b6f41384"
},
{
"id": "test/55de0539eb1e14f26a04"
}
],
"edges": [
{
"from": "test/d39366ae3f76b6f41384",
"to": "test/55de0539eb1e14f26a04",
"style": "arrow",
"jsonPointer": "/ACTED_IN/0"
}
],
"results": {
"test/55de0539eb1e14f26a04": {
"id": "test/55de0539eb1e14f26a04",
"type": "Movie",
"attributes": {
"content": {
"title": "Top Gun",
"released": "1986"
},
"metadata": {
"createdOn": 1655743375214,
"createdBy": "admin",
"modifiedOn": 1656429032809,
"modifiedBy": "admin",
"txnId": 1656429032800092
}
}
},
"test/d39366ae3f76b6f41384": {
"id": "test/d39366ae3f76b6f41384",
"type": "Person",
"attributes": {
"content": {
"name": "Tom Cruise",
"born": "1964",
"ACTED_IN": [
"test/55de0539eb1e14f26a04"
]
},
"metadata": {
"createdOn": 1655743424735,
"createdBy": "admin",
"modifiedOn": 1657913699440,
"modifiedBy": "admin",
"txnId": 1657913699427000
}
}
}
}
}
Request attributes:
“clonePayloads”: optional boolean, defaults to true. If true the bytes of the objects elements will be copied into the new version object.
“versionId”: optional string. If supplied this will be the id for the new version object. If omited a
Example request:
POST /doip?operationId=20.DOIP/Op.Versions.Publish&targetId=test/e4673f57012b544e72af
Response:
{
"id": "test/63fcaf42ecde53b68b10",
"type": "Foo",
"versionOf": "test/e4673f57012b544e72af",
"publishedBy": "admin",
"publishedOn": 1657808342642,
"isTip": false
}
Example request:
POST /doip?operationId=20.DOIP/Op.Versions.Get&targetId=test/e4673f57012b544e72af
Response:
[
{
"id": "test/63fcaf42ecde53b68b10",
"type": "Foo",
"versionOf": "test/e4673f57012b544e72af",
"publishedBy": "admin",
"publishedOn": 1657808342642,
"isTip": false
},
{
"id": "test/e4673f57012b544e72af",
"type": "Foo",
"modifiedOn": 1657745478736,
"isTip": true
}
]
This section describes the design approach followed to map messages that conform to DOIP v2 specification to requests and responses as used by this DOIP API. Readers of this appendix are expected to be familiar with the DOIP v2 specification.
A request to this DOIP API can be made with either GET or POST, which gets mapped to request form defined in the DOIP v2 specification. Only some DOIP operations (generally read-only operations) allow GET; this is part of the specification of the operation.
The examples in this document will use /doip, but the full URL should be constructed using the endpoint of the Cordra service. For example, this could be a URL like https://domain.name/doip or https://domain.name/cordra/doip depending on the details of the Cordra installation.
The components of a DOIP request (section 7.2.1 of the DOIP v2 specification) are obtained from the HTTP request as follows. Each query parameter has both a long form and a short single-character form; multiple values is an error for parameters representing a string (requestId, operationId, targetId, clientId), and multiple values will be combined for parameters representing JSON values (authentication, attributes, input).
requestId: from the query parameter “requestId” or “r”. Can be omitted as the HTTP transport provides its own mechanisms for associating responses to requests.
operationId: from the query parameter “operationId” or “o”. If no operationId is given by the query parameters, the URI path after /doip with the initial slash omitted is used as the operationId.
targetId: from the query parameter “targetId” or “t”, required
clientId: from the query parameter “clientId” or “c”; can be omitted if the authentication provides it implicitly
authentication: from the standard HTTP Authorization: header, for which see details below; additional properties can be set from the query parameter “authentication” or “u” and related parameters as described below under JSON Query Parameters.
attributes: from the query parameter “attributes” or “a” and related parameters as described below under JSON Query Parameters; also from all non-reserved query parameters as described under Non-reserved Query Parameters.
input: from the HTTP POST body; see Input below. A single-segment JSON input can also be set from the query parameter “input” or “i” and related parameters as described below under JSON Query Parameters. If a JSON body is present along with “input” or “i” parameters the JSON is combined.
Authentication can be sent using the standard HTTP Authorization: header, which is translated into the “authentication” property of the DOIP request.
Authorization: Basic is translated into an “authentication” object with “username” and “password” properties.
Authorization: Bearer is translated into an “authentication” object with a “token” property.
For Authorization: Doip, the rest of the Authorization: header is Base64-decoded and parsed as JSON to provide an arbitrary “authentication” property for the request.
If an Authorization: header is present and an “authentication” or “u” query parameter is present, the properties from the query parameter are added to the object generated from the Authorization: header, with repeated properties treated as an error.
For convenience, properties of the DOIP request which represent JSON can be expressed as multiple properties in the API request with dot separated names. This is done for “attributes”, “authentication”, and “input” along with their short names “a”, “u”, and “i”.
Taking “attributes” as an example,
if the value of some attributes.prop
is valid JSON, then it is parsed as JSON.
Otherwise, the value is interpreted as a string. For example,
GET /doip?...&attributes={"query":"foo","pageSize":10}
is exactly the same as
GET /doip?...&attributes.query=foo&attributes.pageSize=10
Any further dot .
in the query parameter is interpreted as indicating a deeper subobject;
for example attributes.foo.bar=true
corresponds to the attributes {"foo":{"bar":true}}
.
Values from the long name of the query parameter and the corresponding short name are combined. Multiple properties with the same name is an error, and so is indicating properties of a JSON value which does not represent a JSON object at all.
For authentication, the values from the query parameters are combined with any JSON object generated from the Authorization: header. For input, the values from the query parameters will be combined with any JSON POST body.
The query parameters “requestId”, “operationId”, “targetId”, “clientId”, “authentication”, “attributes”, and “input” are reserved; every single-character query parameter is reserved; and any query parameter which starts with a reserved query parameter followed by a dot is reserved.
Every non-reserved query parameter will become part of “attributes”, following the same rules for dots as described in JSON Query Parameters. For example
GET /doip?...&query=foo&pageSize=10
represents the attributes {"query":"foo","pageSize":10}
; and foo.bar=true
represents the attributes {"foo":{"bar":true}}
.
For convenience, two standard HTTP headers map to specific DOIP request
attributes. The Content-Type:
header from the API request is copied into
an property “mediaType” of the attributes object, if the attributes do not already have a mediaType. The filename from a
Content-Disposition header is copied into a property “filename” of the
attributes object, if the attributes do not already have a filename.
See POST for long query strings above.
For a GET or a POST with empty body, the input property of the corresponding DOIP request is assumed to be empty.
If the Content-Type: of the HTTP request is
application/x-www-form-urlencoded
, the input will be assumed empty and
the POST body is used to populate the query string parameters.
If the Content-Type: of the HTTP request is application/json
or ends in
+json
, the entire body represents a DOIP input which is a single JSON
segment.
If the Content-Type: of the HTTP request is multipart/mixed
, the
body represents a multi-segment DOIP input. The content of each segment
is equivalent to the body of the corresponding part, and
each segment is JSON or bytes depending on whether the Content-Type
of the corresponding part is application/json
or ends in +json
.
If the Content-Type: of the HTTP request is multipart/form-data
, the
body represents a multi-segment DOIP input, with additional JSON parts
corresponding to the names of every part except the first. This allows
a particularly compact representation of the DigitalObject serialization
as defined in the DOIP v2 specification. In particular, every part of the
multipart request body except the first corresponds to two segments of
the DOIP request; the first of those two segments is a JSON segment of the form:
{"id":"name-of-the-part"}
where name-of-the-part comes from the name parameter of the part’s Content-Disposition: header:
Content-Disposition: form-data; name="name-of-the-part"
The second of the two segments corresponding to each part after the first,
and the only segment corresponding to the first part, has content equivalent
to the body of the part; each such segment is JSON
or bytes depending on whether the Content-Type of the corresponding part
is application/json
or ends in +json
.
If the Content-Type: is the HTTP request is neither JSON nor multipart, the entire body represents a DOIP input which is a single bytes segment.
The components of a DOIP response (section 7.2.2 of the DOIPv2 specification) are mapped into an API response as follows.
The DOIP response “requestId”, “status”, and “attributes” are mapped into the HTTP response header Doip-Response, the value of which is a JSON object serialized using only ASCII for maximum HTTP compatibility.
The HTTP status code of the response will be set according to the DOIP status code, and (for basic DOIP status codes) will be one of
200 |
0.DOIP/Status.001 |
The request was processed successfully |
400 |
0.DOIP/Status.101, 0.DOIP/Status.200 |
There was something wrong with the structure or content of the request |
401 |
0.DOIP/Status.102 |
The client must authenticate to perform the attempted operation |
403 |
0.DOIP/Status.103 |
The client was not permitted to perform the attempted operation |
404 |
0.DOIP/Status.104 |
The requested digital object could not be found |
409 |
0.DOIP/Status.105 |
There was a conflict preventing the request from being executed |
500 |
0.DOIP/Status.500 |
There was an internal server error |
Custom DOIP statuses need to specify the expected corresponding HTTP status code; otherwise 200 is used as a default.
For convenience, two standard HTTP headers are populated in the API response according to specific DOIP response attributes. A property “mediaType” of the response attributes is copied into the Content-Type: header. A property “filename” of the response attributes is copied into the Content-Disposition: header.
The DOIP response “output” is contained in the API response body. A JSON
segment is written with Content-Type: application/json
. Multiple
segments are written with a multipart Content-Type. Other Content-Type
values indicate a single bytes segment.