DOIP API for HTTP Clients

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.

Request format

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.

POST for long query strings

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

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.

Response format

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.

Summary of 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

Aliases

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

Digital Object JSON Structure

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”.

Operation Details

Access Token Operations

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

Create a new access token: 20.DOIP/Op.Auth.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"
}

Check the status of an access token: 20.DOIP/Op.Auth.Introspect

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"
}

Delete specified access token: 20.DOIP/Op.Auth.Revoke

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"
}

CRUD Operations

Object creation: 0.DOIP/Op.Create

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"
        }
    }
}

Object retrieval: 0.DOIP/Op.Retrieve

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"
        }
    }
}

Object update: 0.DOIP/Op.Update

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"
        }
    }
}

Object deletion: 0.DOIP/Op.Delete

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

Cordra Specific Operations

Batch Upload: 20.DOIP/Op.BatchUpload

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"
            ]
        }
    }
]

Reindex Batch: 20.DOIP/Op.ReindexBatch

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"
]

Get Relationships: 20.DOIP/Op.Relationships.Get

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
                }
            }
        }
    }
}

Publish Version: 20.DOIP/Op.Versions.Publish

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
}

Get Versions: 20.DOIP/Op.Versions.Get

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
    }
]

Design Approach

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.

Request Mapping

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

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.

JSON Query Parameters

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.

Non-reserved Query Parameters

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}}.

Attributes from headers

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.

POST for long query strings

See POST for long query strings above.

Input

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.

Response Mapping

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.

Headers from attributes

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.

Output

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.