Re: Cache validators

> The biggest problem I have with If and logic bags is that you want to
> _require_ servers to implement them.  The implementation of all
> proposed conditional modifiers (If-modified-since, If-validator-valid,
> Variant-Set, Alt-Header) is _optional_, because they are only there as
> optimization mechanisms.  Server authors could implement none of them
> and still comply to HTTP/1.1.

That is a reasonable criticism.  However, an extensible mechanism would
allow implementors to extend the preconditions in order to obtain
functionality without having to go through the standards process.
Furthermore, it allows us to place an ordering on the evaluation
of multiple preconditions within the syntax, rather than as notes
within the text description of each additional header field.
Finally, not all preconditions are optional; what do we do when the
implementors need a mandatory precondition?  Do we repeat this whole
process again?

> I guess this is a good time for me to restate some comments on the
> implementation of Unless that I sent to this list shortly before the
> Dallas IETF, and to which I have had no reply since then.  I would
> have a lot more faith in your opinion if you were to actually attempt
> to address these comments, but I can't force you to do that.

I have already addressed all of these comments before; I am sorry that
you didn't see them addressed on the WG list.

> 1) The relational operators like 'gt' in logic bags have big problems
> when used with undefined headers.  Your default does not make these
> problems go away.  There are three important ways of comparing:
> 
>   numeric  (2 < 10)
>   lexical  (ba < c)
>   date     (Mon, 04 Dec 1995 01:23:45 GMT < Mon, 04 Dec 1995 01:23:55 GMT)
> 
> and the defined default, 'numeric comparison (for values consisting of
> 1*DIGIT) and lexical comparison (for all others)', would break on
> undefined headers that carry a date.  I therefore propose to define
> three `greater than` operators:
> 
>   gtn   greater than, numeric
>   gtl   greater than, lexical
>   gtd   greater than, date.
> 
> and maybe, but not required:
> 
>   gt   greater than, with field-name dependent function (use only with
>        field-names defined in HTTP/1.1).
> 
> (of course, the same for ge, lt, le). 

My answer was that the server would not send any header fields for which
the comparison function was truly unknown (i.e., other than the default).

We could reduce this concern by requiring only a minimal subset of
the proposed operators and leaving the rest as optional (with an appropriate
error code to indicate that the server did not support the given
precondition).  The subset would be {and, or, not, eq, ne}.

> Another question: what is the
> `appropriate comparison function' server authors are supposed to use
> for `Content-Version'?  Do we really want to open this can of worms?

The field is defined as being opaque, which means "eq" and "ne".

> 2) The biggest problem with Unless [If] is not the parsing of the
> logic bag, but causality.
> 
> Quoting from the Unless section in the draft 1.1 spec:
> 
> |   When a request containing an Unless header field is received, the 
> |   server must evaluate the expression defined by the listed 
> |   logic-bags (Section 3.11). If the expression evaluates to false, 
> |   then no change is made to the semantics of the request. If it 
> |   evaluates true and the request is not a conditional GET 
> |   (If-Modified-Since, Section 10.23) or a partial GET (Range, 
> |   Section 10.33), then the server must abort the request and respond
>                                     ^^^^^^^^^^^^^^^^^^^^^^
> |   with the 412 (unless true) status code.
> 
> There is a big problem here. Consider the following request:
> 
>   POST /bin/send_mail HTTP/1.1
>   Unless: {gt {Content-length 123}}
>   Accept: */*
>   <more request headers and the encoding of a form containing a mail
>   message follow>
> 
> Now, the draft says that `the server must abort the request' if the
> Content-length of the response would be bigger than 123.  The problem
> is: abort when?  Before or after the send_mail CGI script sends the
> mail?  As your use of examples in which Unless prevents operations
> that cost money shows, you seem to require `before'.

Yes, I require "before".  This does not mean that all possible implementations
will be capable of correctly handling all possible preconditions; the
assumption is that the client will only use a precondition which is
*sensible*.  A precondition on content-length is NOT SENSIBLE.  The fact
that you get the possibilty of a nonsensical result is the fault of the
client and there is nothing the protocol needs to do about that condition.

> My conclusions about implementability: having Unless will only be
> viable if Unless processing can be done transparently to CGI scripts.

That is wrong.  The CGI implementation, in order to be correct, would
have to check for preconditions before processing the request.
How the service is implemented has no effect on the HTTP semantics.

> 3) I observe that the above changes to make Unless implementable
> basically make it a bandwidth-saving device, not a device for
> preventing actions like sending mail from happening.  ...

Which explains why your changes would have been wrong.

> While we are counting...  Your `single syntax' of logic bags says:
> 
> |   Server implementors must use an appropriate 
> |   comparison function for each type of field-value given in this 
> |   specification.
> 
> so you are requiring them to think up and implement `appropriate
> comparison functions' (including `equals' and `less-than') for 21
> different headers, if I count correctly.  Exactly how is this supposed
> to be provably less work than optionally implementing 6 specialized
> precondition headers?  Not to mention that the number won't be 6, but
> less.

It is less work for any generic server.  Try it.  Even special-purpose
servers would only have to implement conditions for those fields actually
sent in their own responses.

Equally important -- you will only have to do that work once, and people
can easily provide utility functions to do it for you.  The alternative
proposals are additive in the work required to implement them and provide
no help for future extensibility.

>>On the other hand, I would also like to see HTTP/1.1 complete sometime
>>this century.
> 
> :-)
> 
>>So, if people would like a simple precondition syntax that is useful
>>for all of the currently identified protocol needs, including cache
>>validation, byte ranges, and content negotiation, then I have the following
>>suggestion:
>>
>>   1) Require Content-ID in HTTP/1.1 responses
>>
>>     Content-ID  =  "Content-ID" ":" cid
>>            cid  =  <a content-id as defined in RFC 1521>
> 
> Why require Content-ID to be present in all responses?

Ummmm, I forget.  I guess it would only be necessary for those in which
the server wanted to support cache validation and byte ranges w/validation.

>>   2) Implement the following precondition syntax:
>>
>>     If-ID  =  "If-ID" ":" 1#cid
>>
>>      wherein the condition evaluates to true if the response to the
>>      request would have had a Content-ID equal to one of the ones
>>      given in the If-ID header field value.  Like the current definition
>>      of Unless in draft 01, the response to a "false" evaluation
>>      depends on whether or not Range or IMS is also present.
> 
> I think this should be "Unless-ID" (you do a normal GET _unless_ the
> response will have one of these Content-IDs).

Shucks -- I also want it to mean "do this method if the resource's
Content-ID is one of these" for methods other than GET.
I tried both Unless-ID and If-ID, but they always lead to a conflict
between the name and the intended result.  How about something neutral
like Check-ID?

   Check-ID  =  "Check-ID" ":" 1#cid

Let's see what the semantics are for a request containing Check-ID:

                        ID is in    ID not in
                        Check-ID    Check-ID (or IMS true)
                        ---------   ---------
    GET                    200         412
    GET + IMS              304         200
    GET + Range            206         412
    GET + IMS + Range      206         200
    other methods       as normal      412

That would take care of Ari's desire for a "give me an error instead"
type of precondition for Range as well.

>>That should make a sufficient number of people happy to make the
>>overhead of doing it worthwhile.  If not, then the only reasonable
>>solution is to use an IF header field with a generic syntax.
> 
> Requiring If and logic bags is not a reasonable solution, they have
> far to many problems that need to be addressed first.  I'd rather have
> 6 specialized headers, though it seems that having 2 (Unless-ID and
> If-Modified-Since for compatibility) is also sufficient.

What I meant is that the only other reasonable solution is a generic syntax.
It is okay for the required comparisons to be limited to those we have
already identified to be needed.


 ...Roy T. Fielding
    Department of Information & Computer Science    (fielding@ics.uci.edu)
    University of California, Irvine, CA 92717-3425    fax:+1(714)824-4056
    http://www.ics.uci.edu/~fielding/

Received on Sunday, 25 February 1996 01:50:39 UTC