Supporting Client-side API and Linked Data Consumption

In my post on consuming of linked data using Javascript, I talked about a couple technologies that are critical to being able to use linked data in client-side applications. Making an API or linked data friendly for client-side consumers requires support for a variety of technologies. In this post, I'm going to explore key technologies for supporting client-side applications.

General JSON Support

JSON stands for JavaScript Object Notation. It is a human-readable text data serialization format that is designed to transmit data objects consisting of attribute–value pairs. JSON developed as a way to more easily encode data because it has a lower overhead than encoding data as XML. JSON provides a simple serialization that can be used to send data as a response to remote calls being made by client applications.

JSON Support is fairly critical to providing support for client-side API consumers for two reasons. First, while JavaScript can process and interact with XML, doing so is more difficult than interacting with JSON. Second, if an API wants to support JSONP, then a JSON serialization of the API’s data is mandatory.

JSONP Support

JSONP is JSON with padding. The purpose of JSONP is to allow JavaScript code on one server to access data on a separate server. Normally, browsers enforce a same-origin policy. This policy limits the resources the JavaScript can access to those on the same server as the JavaScript. If a JavaScript tries to access another resource, then browsers will throw what is called a cross-server scripting error. JSONP wraps the JSON data in a "callback" function, allowing it to be accessed via another server. This technique only works when a client is sending an HTTP GET request. For REST APIs, this limits the developer to reading data.

Support of JSONP and/or CORS is essential for any API that should be available to client-side consumers. Without one of these technologies, API data is inaccessible to clients due to cross-server scripting errors.

CORS

CORS is cross-origin resource sharing. CORS builds on the use cases supported by JSONP but adds the ability for API creators to support clients by reading and writing data via JavaScript. CORS is a specification that allows API providers to support client-side applications by interacting with client data in a variety ways. Through CORS, a server can specify which clients can perform which actions on which resources the server offers. This is done by returning specific HTTP headers.

All responses from the server must return at least an Access-Control-Allow-Origin header in order to allow client-side applications to interact with the data. This header specifies which domains the server is willing to interact with. Often the value of this header is set to "*", which means any domain may interact with the data. To control which actions a client can take, the server returns an Allow-Control-Allow-Methods header. Here, a server can specify which HTTP methods a client is allowed to perform.

In turn, clients should send an Origin header to the server in order to signal that a CORS request is being performed and by whom. Without this header, the server may deny the client request because the server does not know who is sending it. Luckily, web browsers and JavaScript libraries automatically add this header so developers don't need to worry about it. However, it is important to know that sending this is part of the CORS workflow.

In order to facilitate clean error catching and messaging to users, JavaScript code often makes a "preflight" check when making cross-domain requests. A preflight request is always done when the request will write data. Preflight requests are done by performing an HTTP OPTIONS request.

Request Example

OPTIONS /
Host: viaf.org 
Origin: http://www.librarywebchic.net/ 

The server will respond with a set of headers that tell the client which operations it is allowed to perform on that resource.

Response Example

Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET

However, GET and HEAD requests from a JavaScript don't typically do the preflight check.

CORS has several advantages over JSONP.

  1. It gives API developers the ability to make both read and write operations available to client-side API consumers.
  2. It gives API developers the ability to tightly control which client-side application can perform particular operations on particular resources. For example, you may only want domains you control to be able to write data via CORS.

For a more in depth look at CORS, take a look at the HTML5 Rocks site's Using CORS Tutorial.

JSON-LD Support

JSON-LD stands for JavaScript Object Notation for linked data. It is a way of encoding linked data using JSON. The goal of JSON-LD is to allow developers to transform their existing JSON documents to JSON-LD with as little effort as possible. We've talked about techniques for doing this in an earlier post, "Retrofitting an Existing API with JSON-LD".

JSON-LD can be consumed in a couple ways. First, if a client wants to treat the JSON-LD as a graph, then it can consume JSON-LD using a linked data JavaScript library, such as rdflib.js. Second, if the JSON-LD is framed in an object-oriented fashion, clients can consume it using typical JavaScript JSON parsing techniques. Consuming JSON-LD in a graph-oriented way has many advantages, including the ability to expand the scope of the graph on demand.

Cache-Control

Cache-Control is a header that allows API developers to define which resources can be cached, by whom and for how long. This is done via the Cache-Control header, which contains a number of directives. A few key directives are as follows:

  • Max-age: The period of time that the response may be cached for, in seconds
  • No-cache: Response can be cached, but requests for the same URL must check with the server to see if response has changed
  • No-store: Response cannot be cached
  • Public: Response can be cached (this typically doesn’t appear in responses because the presence of a max-age directive implies that a response is cacheable)
  • Private: Responses can only be cached in a browser but not in an immediate cache (this typically is a response that contains user data)

When a client application makes a request to an API, the API returns a response with a specific Cache-Control header.

Example

Request

GET /viaf/102333412/ HTTP/1.1
Host: www.viaf.org 
Accept: application/ld+json

Response

HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
Content-Location: viaf.jsonld
Cache-Control: max-age=604800
Expires: Thu, 04 Aug 2016 17:49:05 GMT
Content-Type: application/ld+json
Transfer-Encoding: chunked
Date: Thu, 28 Jul 2016 17:49:05 GMT

Cache-Control is very useful for client-side applications because it allows developers to store data locally. By storing data locally, client-side applications are able to improve the performance of their applications.

In my next post, I'll look at an example application that leverages the fact that VIAF has added support for these technologies.

  • Karen Coombs

    Karen Coombs

    Senior Product Analyst