HTTP Headers

I’m not sure yet of the exact form this will take, but we’ll use HTTP headers to tell clients about the field names available for a resource type, and the fields in a particular record that have valid values. Clients can also request only certain fields, in case they won’t use some of the data, since there’s no point in compressing, shipping, and decompressing it if we know ahead of time that it’s going to be ignored.

We can probably include more information here too.

The HTTP/1.1bis headers are specified in RFC 7230, S. 3.2. The IANA also maintains a list of standard headers.

Permanent Headers

These are given in the IANA’s “Permanent Message Header Field Names” list.

Accept

Although Cantus servers are only required to supply response bodies in application/json format, for completeness all Cantus user agents MUST provide a Accept header with that value.

While, in accordance with RFC 7231, user agents are not required to include this header, the API may provide additional response formats in the future (in particular application/xml and text/xml) and may even change the default format, so user agents are strongly recommend to specify Accept to ensure forward compatibility.

Accept-Charset

Cantus user agents MUST use UTF-8; for completeness this must be indicated in the Accept-Charset header as utf-8.

Accept-Encoding

Cantus user agents and servers MAY use data compression whenever possible, so the recommended value for the Accept-Encoding header is gzip.

Allow

When a client invokes the OPTIONS method on a resource, the Allow header in the response indicates which other methods may be invoked on that resource.

Example:

OPTIONS /(browse.chant) HTTP/1.1
HTTP/1.1 200 OK

Allow: GET, HEAD, OPTIONS

Content-Encoding

The Content-Encoding header tells a user agent the encoding of the response (i.e., whether its requested data compression algorithm was available and used).

Content-Length

The Content-Length is a decimal number indicating the number of octets expected in the response body. This is used by clients (probably automatically by an HTTP library) to determine when all data has been received.

Content-Type

Cantus server MUST provide a Content-Type header with every response, including the “charset” parameter. Response bodies are formatted in JSON, with the UTF-8 character set, so the value of this header will almost invariably be application/json; charset=utf-8.

Future versions of the API may permit or require different response formats, in particular application/xml and text/xml, and may also change the default response format. Therefore, user agents are strongly recommended to provide the Accept header for forward compatibility.

Cross-Origin Resource Sharing (CORS) Headers

The following headers are used for Cross-Origin Resource Sharing requests. In practice for Cantus, server-to-server requests will not be CORS requests, but requests sent with a Web browser as the user agent are likely to be CORS requests. In everyday use, most browser-sent requests are not CORS requests. Because we expect the Cantus server and user-facing Web app to be served on different hosts (or at least on different ports) it is likely that a user-facing Web app will be submitting CORS requests.

The user agent’s implementation will be handled automatically by the user agent (being the browser). Thus CORS is primarily a concern for the server implementation. Do note that, while Cantus server implementations MAY support the following CORS headers, it is not strictly necessary to have a useful server implementation.

When implementing CORS support, we strongly recommend server authors to follow the specification’s Resource Processing Model, which is both quite precise and relatively easy to understand and follow.

In the context of this section, a pre-flight request is an OPTIONS request submitted before the actual request, with the intent of determining whether the actual reqeust will succeed according to the provided CORS header values.

Note there is an example at the end of this section.

Access-Control-Allow-Origin

The Access-Control-Allow-Origin response header contains a single hostname, the value of the Origin request header, if that host is permitted to use the Cantus server.

This header is required in both the pre-flight and actual request.

Access-Control-Expose-Headers

The Access-Control-Expose-Headers response header holds a list of the header names that Cantus user agents will want to read. In practice, these are the Cantus-specific extension headers. This will be used in both the

This header is required in both the pre-flight and actual request.

Access-Control-Max-Age

To reduce server traffic, the Cantus server MAY include the Access-Control-Max-Age header in the response to a pre-flight request indicating the number of seconds for which the CORS headers will be valid.

This header may only appear in the pre-flight request.

Access-Control-Allow-Methods

The Access-Control-Allow-Methods response header is a response to the Access-Control-Request-Method request header. This response header will contain the value of the request header if it is permitted for this resource and it is not a simple method (i.e., GET, HEAD, or POST).

This header may only appear in the pre-flight request.

Access-Control-Allow-Headers

The Access-Control-Allow-Headers response header is a response to the Access-Control-Request-Headers request header. The response header will hold all the values of the request header that are allowed as header names for a CORS request.

This header may only appear in the pre-flight request.

Access-Control-Request-Method

The user agent submits the Access-Control-Request-Method header with the HTTP method that will be used in the actual request.

This header may only appear in the pre-flight request.

Access-Control-Request-Headers

The user agent submited the Access-Control-Request-Headers header with the header names that will be used in the actual request.

This header may only appear in the pre-flight request.

Origin

The user agent submited the Origin header with the hostname (and access scheme and, if it is not 80, the port) from which the user agent’s Web page came. If this header is part of a request, the server SHOULD add a Vary: Origin header, since a CORS request may receive a different response than an otherwise-identical non-CORS request. Also note that, if the Origin header is not present in a request, any other CORS request headers MUST be ignored.

This header is required in both the pre-flight request and the actual request.

Note

We recommend that server implementations check the value of the Origin header against a list of known Web app deployments, to prevent requests coming from unknown Web apps.

Example

In this example, we assume that Abbott (the Cantus API server) is operating at https://abbott.cantusproject.org:8888/ and that a user enters https://app.cantusproject.org/ in their browser to access the GUI Web app. From the perspective of the Cantus GUI Web app’s author, one single request has been submitted—the “actual” request—meaning the browser automatically creates the preflight request.

Preflight request:

OPTIONS https://abbott.cantusproject.org:8888/(browse.chants)/ HTTP/1.1
Access-Control-Request-Method: SEARCH
Access-Control-Request-Headers: X-Cantus-Page, X-Cantus-Garbage-Header
Origin: https://app.cantusproject.org/

...

Preflight response:

HTTP/1.1 200 OK
Allow: GET, HEAD, OPTIONS, SEARCH
Access-Control-Allow-Origin: https://app.cantusproject.org/
Access-Control-Allow-Headers: X-Cantus-Page
Access-Control-Allow-Method: SEARCH
Access-Control-Max-Age: 86400

...

Actual request:

SEARCH https://abbott.cantusproject.org:8888/(browse.chants)/ HTTP/1.1
X-Cantus-Page: 4
Origin: https://app.cantusproject.org/

{"query": "incipit:deus"}

Actual response:

HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://app.cantusproject.org/
Access-Control-Max-Age: 86400
Access-Control-Expose-Headers: X-Cantus-Page, X-Cantus-Per-Page, { others }
X-Cantus-Page: 4
X-Cantus-Per-Page: 10

{ /* chant data here */ }

Note that only a subset of the headers are shown, to emphasize the CORS behaviour.

Cantus-Specific Extension Headers

These headers extend the HTTP standard in ways specific to the Cantus API. We create extension headers only when no existing solution is sensible.

The server SHOULD return a 400 Bad Request response code for any Cantus-specific request headers that contain invalid values. However, for a request header that does not apply to the requested resource (like X-Cantus-Page for a “view” URL that will only return a single resource) the server MUST ignore the extraneous headers regardless of whether their value is valid.

X-Cantus-Version

Indicates the Cantus API version implemented by a client or server. For example, X-Cantus-Version: Cantus/0.0.1 is version 0.0.1, and X-Cantus-Version: Cantus/3.2.6-test is a version called “3.2.6-test.” Also refer to API Versions and Version Numbers.

X-Cantus-Include-Resources

Clients MAY include this header in a request, telling a server whether to include a “resources” member with hyperlinks to related resources. This can be “true” or “false” (but is case-insensitive). Servers MUST use this header to indicate whether “resources” members are included in a response.

X-Cantus-Fields

Clients MAY use this header to request only certain fields in the response. Servers MUST include this header, which lists the fields that are present in all returned resources. Fields that are only present in some of the returned resources belong in the X-Cantus-Extra-Fields header. For both headers, if there are no fields, the server MAY omit the header or return an empty header.

Both headers are a comma-separated list, like id, name, description.

Note that the “id” and “type” fields MUST be returned for every resource, since this is the minimum information required to find the resource again. If the X-Cantus-Extra-Fields request header does not contain the “id” and “type” fields, the server SHOULD include them anyway, and SHOULD NOT consider this an invalid value.

Refer also to the Example of Cantus Headers.

X-Cantus-Extra-Fields

If some, but not all, resources contain a field, the server MUST include that field name in this header. This field has no meaning in a request. Refer also to the Example of Cantus Headers.

X-Cantus-Total-Results

The total number of results that match a search query. The server MUST include this header in the response to every SEARCH request, and MAY also provide it in the response to a “browse” or “view” request.

X-Cantus-Per-Page

Clients MAY use this header to negotiate “paginated” results with the server, where queries matching a large number of resources will return information about only a portion of those resources. The value should always be a positive integer or zero. A zero symbolizes a request for non-paginated results—information for all matching resources. Servers MUST include this header if the X-Cantus-Total-Results is present and greater than 0 (i.e., for every search query that yields results).

If the server determines that the number of requested resources is too high, it MUST return a status code of 507 Insufficient Storage. The limit is determined by the server, and may change arbitrarily. However, the 507 response MUST include an X-Cantus-Per-Page header with a suggested value that the server determines it is likely to be capable of handling.

X-Cantus-Page

If the X-Cantus-Per-Page request header is non-zero, clients MAY include this header to indicate that the results should correspond to a particular sub-set of the full query. If a client provides a value for this header greater than the X-Cantus-Total-Results response header divided by the X-Cantus-Per-Page request header (i.e., greater than the total number of pages) the server MUST respond with 409 Conflict.

If a query is successful, servers MUST include this header in responses to indicate the effective page of the results.

Note that the first page is numbered 1, not 0.

X-Cantus-Sort

If the X-Cantus-Sort is present in a request, it SHOULD contain a list of 2-tuples of field names and direction indicators (asc or desc) separated by a semicolon, each separated by a comma. (For example: incipit;asc or incipit;asc,feast;desc). “Ascending” results put the numerical and textual results in canonical order (i.e., 1, 2, 3 or A, B, C). “Descending” is the opposite. Only the following characters are permitted: upper- and lower-case letters, _, ,, ;, and spaces.

Note

This list syntax may be unusual for developers not accustomed to HTTP. Take special note that commas are used to separate larger logical groups, and semicolons to separate smaller logical groups. This is the opposite of the English language!

Note

For search queries, we recommend that user agents rely on the default relevance-based sort order. This header makes sense when browsing through a category (e.g., a single resource type, a single Source, and so on).

For example: incipit;asc,description;desc. This means “sort alphabetically by the incipit field, and if there is a tie then sort reverse alphabetically by the description field.”

If a request does not have a X-Cantus-Sort header, the server MUST order results according to an appropriate relevance score, with the most relevant results returned first. If a sort field is not present in all (or any) search results, the server MAY choose a different field by which to sort, return a 409 Conflict response, or continue in another way. For every request including a X-Cantus-Sort header, the server MUST include an equivalent response header to indicate the actual sort field and direction used.

Example of Cantus Headers

A response.

HTTP/1.1 200 OK
Content-Type: application/json; charset="utf-8"
Content-Length: xxx
X-Cantus-Version: 1.0.0
X-Cantus-Include-Resources: false
X-Cantus-Fields: id,incipit
X-Cantus-Extra-Fields: cantus_id
X-Cantus-Total-Results: 10
X-Cantus-Per-Page: 3
X-Cantus-Page: 2
X-Cantus-Include-Resources: false

{"149243": {
    "id": "149243",
    "type": "chant",
    "inicipit": "Estote parati similes",
    "cantus_id": "002685"
    },
 "149244": {
     "id": "149244",
     "type": "chant",
     "incipit": "Salvator mundi domine qui nos",
    },
 "149245": {
     "id": "149245",
     "type": "chant",
     "incipit": "Estote parati similes",
     "cantus_id": "002685",
    }
}