This page contains a list of things we check when creating or extending a platform service.
URIs are structured consistently
Platform URIs follow the container/item pattern. The first component of the URI path is the container, the next component an item in that container, the next component a collection of sub-items etc.
For example in the URI "/stores/ukbib/services/sparql" there is a container called stores, an item in that container called "ukbib" which has a container called "services" which, in turn, has an item called "sparql"
URIs follow a naming policy
All platform URIs are defined to be lowercase and, apart from URI syntax such as "/" and "?" may only contain the letters a to z, the numbers 0 to 9 and the hyphen -
Every service has a human interface too
- A human should be able to get an HTML form to fill in by accessing the service URI without any parameters
- The HTML form should be obtainable by specifying 'text/html' or 'application/xhtml+xml' as a media type in the request's accept header
- Some services may also present the HTML form if the accept header contains "*/*" or is missing
- All HTML documents should be well-formed, semantic XHTML 1.0
- Every parameter supported by the service must be listed in the HTML form
- All names of form elements that correspond to service parameters must be in lower case
Services allow you to choose the best format (Content Negotiation)
- Every service has a list of named output types which correspond to output formats. See Output Types for full details.
- Services with more than one output type must support a query parameter called "output" which allows the user to select the format they want without using Accept headers.
- If the output parameter is supplied in a request, ignore the Accept header
- If there is no output paremeter, use the Accept header to determine which output type should be selected
Services are tolerant in what they receive, but strict in what they send
- If the Accept header is missing from the request, treat it as though it had a value of "*/*"
- If additional, unknown, query parameters are sent, ignore them
- If the service accepts RDF ignore any triples that are not understood by the service
Services use HTTP response codes appropriately
- If a required parameter is missing, use code 400 plus a message saying which parameter was missing
- If a parameter is malformed, use code 400 plus a message saying which parameter was wrong and what can be done to fix it
- If an HTTP method is used that isn't supported by a service (e.g. PUT), use code 405 plus a message. Also the Allow HTTP header MUST be sent containing a list of methods that are supported.
- None of the values in the Accept header match an output type supported by the service, use code 406 plus a message saying that the format requested is not supported.
- If an item is POSTed to a container the service adds it straight away the response code should be 201 and include a Location header containing the URI that the server gave to the new item
- If an item is POSTed to a container the service adds queues it for processing then the response code should be 202. If possible the service should include a Location header containing the URI that the server gave to the new item. Retrieving this URI may give a 404 until the item has been processed.
- If a service accepts XML but the client POSTs or PUTs malformed XML, use code 400 Bad Request
- If a service accepts XML/RDF but the client POSTs or PUTs XML that doesn't parse as RDF, use code 400 Bad Request
- If a service accepts some type of RDF but the client POSTs or PUTs RDF that doesn't conform to internal constraints (such as URI naming conventions, or expected triples), use code 422 Unprocessable Entity
- If the client POSTs or PUTs content with an unsupported media type, use 415 Unsupported Media Type
- If the server cannot accept content from the client because it is low on storage capacity, use 507 Insufficient Storage
Services are used by machines but debugged by humans
- Error responses (i.e. any response code starting with 4 or 5) MUST include a textual message of the problem. This must be plain text and be sent with a content type header with a value of "text/plain"
- All error messages should include a statement of the problem in terms of the input the user gave, plus a suggestion on how to fix it.
- Stack traces are never, ever sent in the response to a request
Services should be Cacheable
Whereever possible services should emit HTTP caching headers, e.g ETags, for types of responses.
Similarly, whenever data is added to the service, ETags should be generated for later responses.
Services should be Symmetrical
For services that accept both inputs and outputs, the list of machine-processable formats should be identical for each request operation. For example if a service can output RDF/XML and RDF-in-JSON, then its input operations should also accept both formats.
Service resources should be Manageable
Wherever possible, e.g. not limited by security or practical reasons, resources exposed by the Platform should be manageable by the client, i.e. they should offer the full suite of Create, Read, Update, and Delete operations (appropriately mapped to RESTful operations). This allows clients to have full control over resources that they create in the service.
Service representations should by Hyperlinked
Representations retrieved from services should be hyperlinked to other relevant services (i.e. the API should follow the "hypermedia as engine of application state" principle of REST).
So, e.g. query profiles and field predicate maps should point to the store with which they are associated.
The Platform should be a good User Agent
Some services allow clients to trigger the fetch of remote data sources, e.g XSLT stylesheets, RSS feeds, etc.
On these occasions, where it is acting as an agent for clients, the Platform should act as a good HTTP User Agent, e.g. obeying HTTP redirects, it should attempt to cache data, should advertise itself (via HTTP header), etc.