Re: URI Templates - optional variables?

Big +1 to limiting templates to a declarative syntax for simple  
string operations.

I realize most folks are focussed on the template->URI conversion  
process but I'm currently most interested in matching URIs to  
templates and if we introduce the need to refer to external  
processing extensions I don't see how such matching can be  
implemented in the general case. I'd rather not have to profile the  
spec for my use case if that can be avoided.

Thanks,
Marc.

On Oct 15, 2007, at 5:11 PM, Roy T. Fielding wrote:
>
> I think it is critical to limit the potential operations to
> typical string operations, both for simplicity of implementation
> and also for our capacity to understand the template without
> needing to refer to external rules or processing.  There is no
> reason to have URI templates if we don't limit them to a
> declarative syntax
>
> In particular, anything turing complete would be way out of
> bounds because that would cross from an in-band description
> language to an out of band processing language.  URI templates
> lose their value as a declarative syntax if they try to do what
> javascript already does well enough.  Even regex would be far
> more complex than any of the use cases require.  And I don't
> want to see URI templates on the side of a bus -- that would
> reintroduce long-term client/server coupling.
>
> The characters I chose for delimiters are not important.  If we
> want to avoid URI characters, then Joe's variation is good,
> though it will make life slightly harder on XML config authors.
> I think the set below is very easy to read, keeping in mind
> that human language is not universal.
>
> To tie this back to my earlier messages on Aug 1, substituting
> pipe ("|") for ":", "<" for "?", adding ">" for suffix, and
> "+" for simple joins:
>
>    {variable}                                   (substitute)
>       Substitute the value of variable.
>
>    {=default|variable}                          (sub w/default)
>       If variable is defined and non-empty, then substitute the
>       value of variable.  Otherwise, substitute with the default
>       value defined by the string of non-pipe characters between
>       the '=' and '|', if any.
>           E.g.,  {=red|favoritecolor}  = "value" or "red"
>
>    {<prefix|variable}                           (prefixed sub)
>       If variable is defined and non-empty, then substitute the
>       string of non-pipe characters between the '<' and '|', if
>       any, followed by the value of variable.  Otherwise,
>       substitute with the empty string.
>          E.g.,   {</|variable}       = "/value"      or ""
>                  {<;name=|variable}  = ";name=value" or ""
>                  {<#|variable}       = "#value"      or ""
>
>    {>suffix|variable}                           (suffixed sub)
>       If variable is defined and non-empty, then substitute the
>       value of variable followed by the suffix string of non-pipe
>       characters between the '>' and '|', if any.  Otherwise,
>       substitute with the empty string.
>          E.g.,   {>/|variable}       = "value/"      or ""
>                  {>.html|variable}   = "value.html"  or ""
>
>    {+separator|var1,var2,var3,...}              (join)
>       For each variable named in the comma-separated list,
>       if the named variable is defined and non-empty, then
>       substitute the concatenation of variable values separated,
>       if more than one substitution is made, with the string of
>       non-pipe separator characters between the '+' and '|'.
>          E.g., name     = "Fred"
>                age      = "41"
>                zip      = ""
>                location = "USA"
>         {+,|name,age,zip,location}    = "Fred,41,USA"
>         {+ish;|name,age,zip,location} = "Fredish;41ish;USA"
>         {+/|location,age}             = "USA/41"
>
>    {,separator|var1,var2,var3,...}              (param=value sub)
>       For each variable named in the comma-separated list,
>       if the named variable is defined and non-empty, then
>       substitute the concatenation of variable name, "=",
>       variable value.  If more than one substitution is made,
>       separate each substitution with the string of non-pipe
>       separator characters between the ',' and '|'.
>          E.g., name     = "Fred"
>                age      = "41"
>                zip      = ""
>                location = "USA"
>         {,&|name,age,zip,location} = "name=Fred&age=41&location=USA"
>         {,;|name,age,zip,location} = "name=Fred;age=41;location=USA"
>
>    {-offset|variable}
>    {-offset-length|variable}                    (substring sub)
>       Substitute a substring of the value of variable, as delimited
>       by the non-negative integer offset from the beginning of the
>       value string (0 = start of string) and including the remaining
>       characters (if any) up to the maximum given by the positive
>       integer length.  offset must be in the range [0-255].  length
>       must be in the range [1-256].
>           E.g.,  {-0-3|variable}   = "val"   or ""
>                  {-3-2|variable}   = "ue"    or ""
>                  {-3-8|variable}   = "ue"    or ""
>                  {-2|variable}     = "lues"  or ""
>
> The main use case for substring substitution is to describe
> automated resource hierarchies that aren't flat, such as lists of
> users within a large intranet that are tree-balanced by splitting
> into sub-collections by the first character of the last name (this
> is a very common case at my work where thousands of users are often
> stored within a tree of JCR-based content).  Caches frequently do
> the same type of content balancing by splitting stored messages by
> the first few characters in a hash of the URI.  As Mark said, this
> could be accomplished by external processing of the original
> variable value, thereby defining a new variable to be used in the
> template, but then how do we describe such processing to readers
> of the URI template?  IMO, mapping values to identifier string is
> the whole point of this exercise, so any case that we don't handle
> within the declarative syntax is the same as punting to javascript.
>
> One variation that might be worth considering:  If all of the map
> operators are delimited on both sides by a pipe character, as in
>
>     {variable}                  = "value"        or "red"
>     {|=red|favoritecolor}       = "value"        or "red"
>     {|<;name=|variable}         = ";name=value"  or ""
>     {|>.html|variable}          = "value.html"   or ""
>     {|+,|name,age,zip,location} = "Fred,41,USA"
>     {|,&|name,age,zip,location} = "name=Fred&age=41&location=USA"
>     {|-0-3|variable}            = "val"          or ""
>
> then the template processor need only special-case the pipe "|"
> and some people may find that easier to read.  *shrug*
>
> ....Roy
>

---
Marc Hadley <marc.hadley at sun.com>
CTO Office, Sun Microsystems.

Received on Tuesday, 16 October 2007 03:13:12 UTC