Skip to content

Introduction to Content Negotiation

alangrafu edited this page Mar 10, 2012 · 11 revisions

Information versus non-information resources

In this site and many others we tend to refer to things like http://example.org/thing as URI (Uniform Resource Identifier) instead of URL (Uniform Resource Locator). The different is in its purpose: To name a thing is different to know how to reach it. For example, in a certain context, the string Alvaro's car define unequivocally a thing (my car) but it doesn't make it clear how to access or reach it. A more general identifier could be the serial number of my laptop: this number is unique in the world, so when I use it, it should be clear for everybody that I'm talking about a specific laptop. Again, this doesn't give us any information how to reach or access that laptop.

However on the traditional web, identifier and location are the same: I can name my webpage as http://example.org/index.html and I can also retrieve it using the same string. When things can be identified and accessed by the same identifier on the Web using the HTTP protocol, we call them Information Resources.

I can however give an identifier to other things besides webpages and images: For example, my car can be http://graves.cl/mycar while I can identify myself using http://alvaro.graves.cl. Since you cannot retrieve or access my car or myself using HTTP, we call them Non-information Resouces

How does LODSPeaKr bridge the gap between IR and NIR?

RDF in general and Linked Data in particular are aimed to describe information about lots of things that are not necessarily information resources, from US States to people. However, it is not possible to access states or people through the HTTP protocol, what can we do about it?

The de facto standard to do this is to use content negotiation (conneg) which is a mechanism to obtain a suitable representation of a resource, based on what the client will accept.

Thus, if a client requests http://example.org/myCar which is not an information resource, LODSpeaKr will return an HTTP code 303 (See Other) which will redirect to a document with information related to http://example.org/myCar. Depending on the Accept header sent by the client, LODSPeaKr will try to server the best possible representation (RDF/XML, Turtle, N-Triples or HTML+RDFa). A diagram can be seen in Figure 1.

Content Negotiation in LODSPeaKr

Content negotiation in services

Services are information resources by definition (their URI doesn't identify an entity from the triple store, but they deliver documents that can be transmitted via HTTP). Thus, when requesting a particular representation for a service, LODSPeaKr will NOT do a 303 redirection, but it will simply deliver the content using the best representation possible.

$ curl -H 'Accept: application/rdf+xml' -i http://foo.com/classes


Date: Sat, 10 Mar 2012 17:09:37 GMT
Server: Apache/2.2.20 (Ubuntu)
Accept-Ranges: bytes
X-Powered-By: PHP/5.3.6-13ubuntu3.6
Transfer-Encoding: chunked
Content-Type: application/rdf+xml

<?xml version="1.0" encoding="UTF-8"?>
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">

  <rdf:Description rdf:about="http://data.semanticweb.org/conference/iswc/2010/break-2010-11-09T10-00-00">
    <rdf:type rdf:resource="http://data.semanticweb.org/ns/swc/ontology#BreakEvent"/>
  </rdf:Description>

  <rdf:Description rdf:about="http://data.semanticweb.org/conference/iswc/2011/break-2011-10-24T12:30:00">
    <rdf:type rdf:resource="http://data.semanticweb.org/ns/swc/ontology#BreakEvent"/>
  </rdf:Description>
...

Forcing a particular representation

It is possible to obtain a particular representation despite what the client's Accept header by adding an extension to the service name. This is particularly useful when we want to obtain JSON representation in the browser (despite the fact that application/json is not usually part of the Accept string in a modern browser)

$ curl -H 'Accept: application/rdf+xml' -i http://foo.com/classes.ttl

HTTP/1.1 200 OK
Date: Sat, 10 Mar 2012 17:11:46 GMT
Server: Apache/2.2.20 (Ubuntu)
Accept-Ranges: bytes
X-Powered-By: PHP/5.3.6-13ubuntu3.6
Transfer-Encoding: chunked
Content-Type: text/n3

@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix ns0: <http://data.semanticweb.org/ns/swc/ontology#> .

<http://data.semanticweb.org/conference/iswc/2010/break-2010-11-09T10-00-00> rdf:type ns0:BreakEvent .

<http://data.semanticweb.org/conference/iswc/2011/break-2011-10-24T12:30:00> rdf:type ns0:BreakEvent .

<http://data.semanticweb.org/conference/iswc/2010/break-2010-11-11T15-30-00> rdf:type ns0:BreakEvent .

Example: creating bibtex service

Suppose we want to create an API that delivers bibtex files based on Linked Data. Thus, we have information about meetings, people, etc.

First, we need to tell LODSPeaKr that we want to serve data in a new content type. In settings.inc.php we add the following line:

$conf['http_accept']['bib'] = array('application/x-bibtex');

In this way, we are telling LODSPeaKr how it must accept that particular content type.

We have a service where queries/main.query retrieves the relevant information and html.template displays it in HTML form. We than add a new template, called bib.template, that will serve all the content types related to bib (right now is only application/x-bibtex but it could be multiple content types)

componens/services/papers/
                         |
                         |-> html.template
                         |
                         |-> bib.template
                         |
                         |-> queries/
                                    |
                                    |->main.query

In bib.template we will create a template that matches the Bibtext format. We will add values using Haanga as we usually do in the html case (lets assume query contains values such as paperId, author, title, etc)

{%for i in models.main%}
@article{ {{i.paperId.value}},
 author    = "{{i.author.value}}",
 title     = "{{i.title.value}}",
 journal   = "{{i.journal.value}}",
 year      =  {{i.year.value}},
}
{%endfor%}

We can later request $ curl -H 'Accept: application/x-bibtex' -i http://foo.com/papers to obtain the bibtex file. Since browsers usually don't request application/x-bibtex, we can force to obtain that content simply by pointing it to http://foo.com/papers.bib.

We can also request application/x-bibtex to single URIs. We just need to create a new bib.template for the types and uris previously defined.

Clone this wiki locally