dev@jsr311.java.net

Re: JSR311: Limit extensions pre-processing

From: Roy T. Fielding <fielding_at_day.com>
Date: Wed, 9 Jul 2008 11:30:51 -0700

On Jul 9, 2008, at 5:31 AM, Marc Hadley wrote:
> I'm curious, wouldn't it also break URI opacity if you could:
>
> GET /foo.html
>
> but only
>
> DELETE /foo
>
> I.e. the client would have to know that the .html isn't part of the
> resource identifier ?

Yikes, multiple terminology breakdowns here. First, URI opacity is
irrelevant
to origin servers (they obviously need to know how to interpret their
own
space of names). Second, each is a unique URI with its own resource.

If we have a space like

    /foo/bar
    /foo/bar.html
    /foo/bar.xml

then under sane circumstances those three URI paths would identify three
*different* resources. Resources are what the client perceives as
available
sources of information/work with the same semantics over time. Each
of those
is going to have distinct semantics even when they share
representations.

Content negotiation is only relevant to the first resource (because
that's
the way we've implemented extensions in this origin server, not
because of
any inherent meaning in the extension itself). bar.html is limited
to HTML
formats. bar.xml is limited to XML formats. bar is not limited,
which means
its value set can include any format. Each of those are distinct
semantics
and therefore distinct resources. The first resource is often called a
negotiated or generic resource, whereas the other two would be specific
resources (note that you could negotiate over multiple dimensions, so
this is really a tree of levels with generic at the root and specific
at the leaves).

Perhaps it would help to think of it like a Unix filesystem. We own the
meaning of directory listing, so we get to state the rules for when
names
appear in that listing and when they disappear. Generally, names are
always created as a specific representation is added/enabled, like
bar.html,
by either creating a "file" or defining a program that maps to a
specific
name. Generic/negotiated resources are like symbolic links -- they are
names that are created (sometimes automatically) to provide the generic
alternative resource to any given set of specific representations.
This mapping and unmapping of URIs to representations is all defined
by the origin server resource framework (JSR311 in our case) and is
independent of content negotiation. Each URI is a different resource.
"resource" has nothing whatsoever to do with "storage".

Content negotiation in HTTP only impacts the selection of the content
of the response message. It NEVER changes the target of a method.
To put it another way, if content negotiation is used to select the
target resource for a method then the origin server is violating HTTP
requirements and RESTful design.

Likewise, DELETE in HTTP means "unlink this name from your namespace".

If DELETE is applied to a specific resource, the action should cause
that specific representation to be unmapped and, by side-effect, also
be removed from the value set of any generic resource that maps to it
indirectly, which may lead to the corresponding "removal" of any
generic resource that is left with no remaining representations after
that DELETE. ("removal" is in quotes because an unmapped name in
HTTP just means that a 404 response will be returned to a subsequent
non-PUT request -- it has nothing to so with storage. since most
systems implement generic names as simple look-up algorithms, there
is no need to "remove" names that will result in a 404 on look-up).

If DELETE is applied to a generic resource, the action should be to
remove the symbolic link association (turn off negotiation on that
name).
If that's not allowed by the origin server, then the DELETE should
result
in a 300 redirection to the more specific resources; i.e., the client
needs to be told that it must delete the specific resources if it want
the generic resource to disappear. A DELETE on a generic resource
must not have the effect of deleting the specific resources directly
because that isn't what the client requested.

Having said all that, it is the responsibility of the web framework
to map those HTTP semantics onto the actual actions taken to reflect
those requests within its internal values and configuration. The best
way to do that is to treat each URI as an individual resource first
and use the method to select the handler defined by that resource.
For example, a specific resource would have specific implementations
of GET, PUT, DELETE, ... whereas a generic resource would have a very
different implementation of those methods. AFAICT, that should be
easy for JSR311 to provide through inheritance and overrides.

....Roy