If you want a less formal look at what this is about, see my note on how containers work., or a closely related specification/framework I developed called RDF Forms.

An RDF view of REST


Traditional interfaces to Web resources such as WIDL, WSDL, or WRDL, are very API-centric; they focus on explaining which methods are supported on a resource. I feel that while this approach is useful, that it's missing a lot of information that would be useful to developers and to others; specifically, why those particular methods are supported and what their role is. In the world of OO programming, this would be roughly analogous to saying that an Object implements some particular Interface, rather than this method, and that method, etc..

I made an attempt at producing a taxonomy of Web resources as part of my Abstract Model for HTTP Resource State. It is a useful start, but isn't complete, nor is it yet in a machine processable format. This document addresses both issues in part, and in doing so ends up asserting some of the contraints of REST. This was mostly unintentional, but it may be something that would be useful to continue with.

It should be noted that REST != HTTP. I've got a basic attempt at distilling REST concepts from HTTP that I'm using to define the scope of this work. I don't want to get into the nitty gritty of HTTP, just focus on REST. Though some names such as ":contentLocation" are taken from headers of the same name in HTTP, I believe that the relationship it represents is an artifact of REST, not of HTTP.

Completing the Taxonomy

The following classes of resources were identified in my abstract model, though renamed;

To complete the list, we need to incorporate the full set of functions of POST defined in RFC 2616. Luckily, the only one of the four that isn't specifically accounted for in the abstract model is annotation. It may be described in this taxonomy as an "annotating container".

This list is really only "complete" with respect to the methods defined in HTTP 1.1 that operate on resources directly and are not optimizations (GET/PUT/POST/DELETE). For extension methods, it may be desirable to define new classes. For example, somebody might want to define additional classes for WebDAV, perhaps for "Lockable" resources, etc.. Personally though, I'm not a fan of using extension methods where extension headers would work just as well, so it may be "complete" in that sense. But it certainly does not pretend to capture all of REST - as I said above, it was unintentional that anything of REST was captured at all.

Machine Processable Form

I'll start with Notation3 syntax for convenience.

@prefix : <http://www.markbaker.ca/2002/03/RestRDF/> .
@prefix rdf:  <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix log: <http://www.w3.org/2000/10/swap/log#> .
@prefix daml: <http://www.daml.org/2001/03/daml+oil#> .

# Our definition of resource, as a thing that can be poked with HTTP
# or any other application protocol which operates on things with
# identity.  Not sure of the relationship with other things with the
# same name in other namespaces.  All Resources support GET.
:Resource rdfs:subClassOf rdf:Resource .

# A bag of resources.
:ResourceBag rdfs:subClassOf :Resource ; rdfs:subClassOf rdf:Bag .

# A property representing the relationship between a resource and all
# resources created by it.  Used by Container.
:created a rdfs:Property ; rdfs:Domain :Resource
                         ; rdfs:Range  :ResourceBag .

# A property representing the HTTP redirection relationship (permanent,
# temporary) on all resources.
:redirectsTo a rdfs:Property ; rdfs:Domain :Resource
                             ; rdfs:Range  :Resource .

# Try to model permanent redirection.  Incomplete, since it doesn't
# model the "move" part of the relationship.  Arguably useless.
:redirectsToPermanently rdfs:subPropertyOf :redirectsTo ;
                        rdfs:subPropertyOf daml:equivalentTo .

# A property that can be used to expose query parameters.  Doing it
# this way makes an assumption about resources that isn't backed up
# RFC 2396, but it isn't disallowed either; that a URI with a query
# term implies the existence of a resource identified by that same
# URI without the query term.  I think that's a safe assumption.
:queryableBy a rdfs:Property ; rdfs:Domain :Resource
                             ; rdfs:Range  :QueryParamSeq .

# how do you type a container, i.e. say "sequence of ?"
:QueryParamSeq a rdf:Seq .

# Declare our "base types" from the Abstract Model for HTTP Resource State;
# Resource (declared above), Container, Replaceable, Deleteable.

# Some resources can be deleted (supports DELETE)
:Deleteable rdfs:subClassOf :Resource .

# Simple mutable resource (supports PUT)
:Replaceable rdfs:subClassOf :Resource .

# Container resource (supports POST, and includes the property that
# lists all created "sub"-resources).
:Container rdfs:subClassOf :Resource .
:created rdfs:Domain :Container .

# State-preserving resource. not sure how best to assert "state
# preserving".  You need to read my Abstract Model for HTTP Resource
# State to understand what this is - though I changed "identity
# preserving" to "state preserving".
:StatePreservingContainer rdfs:subClassOf :Container .

# Annotateable resource
:Annotateable rdfs:subClassOf :Container .

# Processing container
:Processor rdfs:subClassOf :Container .

# Let's talk about representations and the resources
:Representation a rdfs:Class .

# ... and their relationship to resources.  ":contentLocation"
# is named that way to reflect that it means the same thing
# as the HTTP Content-Location header.
:contentLocation rdfs:Property ; rdfs:Domain :Representation
                               ; rdfs:Range  :Resource .
# { :repr :contentLocation :res } log:implies { } - ugh, need to tie to GET somehow

# Methods ... getting into W*DL land here.  Should try integrating
# Eric's work.
:Method a rdfs:Class .
:implements rdfs:Property ; rdfs:Domain :Resource
                          ; rdfs:Range  :Method .

# Necessary methods for REST (a subset of HTTP's methods)
:Get rdf:type :Method .
:Put rdf:type :Method .
:Post rdf:type :Method .
:Delete rdf:type :Method .
:Head rdf:type :Method .

# Bind them. For example, containers implement POST, and all resources
# which implement POST are containers.
:Resource :implements :Get .
:Resource :implements :Head .
:Container :implements :Post .
:Replaceable :implements :Put .
:Deleteable :implements :Delete .
{ :x :implements :post } log:implies { :x a :Container } . this log:forAll :x .
{ :y :implements :put } log:implies { :y a :Replaceable } . this log:forAll :y .
{ :z :implements :delete } log:implies { :z a :Deleteable } . this log:forAll :z .


There's an example at the end of my How Post Works note. The only thing that's missing to tie it back here, is;

<http://retail-standards.org/order-acceptor/> rdf:subClassOf <http://www.markbaker.ca/2002/03/RestRDF#Container> .

Future directions

Some possible directions for where this work can go ... Despite the name, I don't intend that all REST architectural principles be captured here, though I suppose there's no reason why many of them couldn't be. The main intent was just to capture a taxonomy for classifying REST components based upon their roles.

A good source of ideas would obviously be Roy's dissertation or TimBL's design issues.

Also have to find a way to bind this to a W*DL document, so it can be asserted in a machine processable way that a :Resource supports GET, a :Container supports GET and POST, the different types of supported representations, etc.. Or else recast W*DL in RDF, like the attempt with WSDL.


Thanks to Sean Palmer for the log:forAll help

Related work

Revision History

2002 03 01; created

2002 03 09; added assertions that enable resources implementing methods directly to be used as one of our base types

2002 03 11; built redirectsToPermanently with daml:equivalentTo, started work on modelling queryable resources

2002 08 20; changed "identity preserving" to "state preserving" re Paul's feedback