Fielding constraints, web frameworks
in a recent IRC convo on the #REST channel i ended up spilling out an overview of Fielding's constraint list as it relates to common Web frameworks and development practices. i've been playing w/ this material for quite a while (close to a year, based on some of my notes) and didn't really give much thought to posting it on the channel. turns out i got a handful of positive reactions to the summary and i figured i'd blog it here in order to give a bit wider exposure.
Fielding constraints
lately, i've been referring to the defintion of the REST style as "Fielding Constraints." i do this to replace the overloaded term 'REST' with something more specific and direct. not only does this cause listeners to 'perk up' when i say it ("um, WTH did he just say?") but it does a pretty god job of 'short circuiting' the 'meme-brain' and avoids bumping up against the mixed meanings and assumptions many in my audience carry with them when they process the word 'REST.'
so, for the rest of this blog post, i'll be talking about "Fielding Constraints."
Web Frameworks
because of the kind of work i do right now (helping companies design, implement, and maintain APIs for the Web), i get to see a wide variety of programming languages, development environments, and Web frameworks. most of the stuff i see is dang cool. some of the things i encounter, however, are a bit clunky; frameworks that make it 'hard' to 'do the right thing' when it comes to creating solid, scalable, maintainable solutions for HTTP.
sometimes things can 'get better' by just ignoring some aspects of the Web framework in use. sometimes folks need to change habits when designing and implementing solutions. occasionally, i encourage folks to just plain stop using a tool or framework and migrate to others that make things easier in the long run. in all those cases, my usual measure is whether a particular "Fielding Constraint" is important to the implementation and whether the framework makes supporting that constraint easy or not.
so, with that in mind, let's go through the list of "Fielding Constraints" and see where most Web frameworks fall in supporting them.
primary constraints
First, when crafting his REST style, Fielding selected six primary constraints that should be adhered to in order to elicit the Architectural Properties of Key Interest and one of them (Code On Demand) is optional; that leaves five.
if the five remaining primary constraints, three of them (Client-Server, Cache, and Layered System) are mostly beyond the bounds of a typical dev environment. it's true that dev tools can do some things to make supporting caching (both marking and validating requests) easier, but for the most part, this can be handled outside the direct dev space using Squid and other similar stand-alone tools.
that leaves only two other primary constraints: Stateless and Uniform Interface. supporting the Stateless constraint is easy, but is rarely "ON" by default in most Web frameworks. all that is needed is to turn "OFF" support for "session state" on the server and almost all frameworks support this switch.
so there is only one constraint left (Uniform Interface) and that's the one most all Web frameworks focus upon. that makes sense since this constraint depends heavily on the details of implementation. it also turns out to be the most interesting constraint in Fielding's list. so interesting, Fielding added four additional 'sub-constraints' to the Uniform Interface in order to better describe and define it.
uniform interface sub-constraints
The Uniform Interface constraint is made up of four 'sub-constraints' and they are:
- identification of resources
- manipulation of resources through representations
- self-descriptive messages
- hypermedia as the engine of application state
from the above list, most Web frameworks devote a great deal of time to #1 (identification of resources) and almost no time to #4 (hypermedia as the engine of application state). in HTTP #1 is expressed via URIs. Web frameworks fall all over themselves trying to automate the generation and parsing of URIs; often to their detriment. instead of providing a clear, powerful abstraction of identifiers for mapping to private components, most frameworks create restrictive rules that couple internal classes or functions directly to public URIs such that even minor changes in the structure of the source code can result in breaking existing public URIs and/or forcing both clients and servers to adhere to an overly-constrained interface that essentially negates the "uniform" aspect of Fielding's model and creates "snowflake" API designs that reduce re-usability and limit evolvability.
HTTP supports #2 (manipulation of resources through representations) through the
use of
negotiated media types
at runtime. IOW, clients and servers have the
ability in HTTP to choose the format in which server data will be represented.
This is unlike FTP, DNS, IRC, and other layer 7 protocols that pre-define the
allowed formats for exchanging messages.
while most frameworks today support some level of representation abstraction, many
do it in rather odd ways (i.e. adding query string arguments such as format=xml
,
instead of using the existing Accept
and Content-Type
headers).
also, only a few frameworks "build in" support for
handling content-negotiation at runtime. instead, devs are often required to declare
special URIs (or URI construction rules) for each representation format of the same resource.
this can lead to URI explosion and maintainability problems both at run time
(cache invalidation) and at design time (code maintainence).
the support for self-descriptive messages (#3) deals with the ability of user agents (clients) and intermediaries (proxies) to succesfully 'replay' a stored message w/o the need to contact the origin server first. basically, this is where HTTP headers (metadata) and the payload come together to form a complete message that can "stand alone" over time. this ties directly to supporting two of Fielding's primary constraints (Caching and Layered System) and happens w/o much fanfare in most Web frameworks. there are times when design decisions by devs and architects can impinge on this constraint (usually in cases where payload information 'leaks' into metadata collections or vice-versa), but most of the time implementation details don't wander into this space often.
that leaves only one more sub-constraint: the crazy cousin no-one wants to talk about at family gatherings...
hypermedia
proly the most mis-understood and ignored of Fielding Constraints, it turns out hypermedia as the engine of application state is the most unique and powerful of them all. it doesn't help that there is precious little information about hypermedia within Fielding's dissertation; the one line included in this blog post is all that appears in the text. Fielding, himself, admitted this regrettable outcome:
To some extent, people get REST wrong because I failed to include enough detail on media type design within my dissertation.
since so little was initially written about the details of hypermedia, Web frameworks have (to date) simply ignored this constraint.
not long ago, Fielding provided additional information on the use of hypermedia as an architectrual element and this has, in part, spurred renewed interest in hypermedia as a method for implementing Web solutions. however, i have yet to find a Web framework that elevates hypermedia as a "first-class" element the way URI-construction is a first class element. hopefully, additional research will encourage product improvements and we'll soon see real hypermedia development enviroments become available.
therefore...
when you reduce it down, there are only a small set of Fielding Constraints that directly apply to the typical "coding" space: Stateless and Uniform Interface. and, of those two, it is the sub-constraints of Uniform Interface which we most deal w/ when building real live apps for the Web. so far, frameworks (IMO) over-constrain the use of identifiers (URIs), fall short on supporting representation abstractions, and completely ignore the use of hypermedia.
it's not only my hope but one of my goals that development environments will continue to evolve and improve in order to make it easier to build powerful hypermedia applications for the Web. and i see some encouraging signs from both the Rails and Microsoft WebAPI communities in this regard.
and i suspect i'm not the only one!