Subject: Test cases for "If" header checks

From: Julian Reschke <[email-masked]>
Date: Sat, 22 Oct 2005 21:45:17 +0200

Hi.

Below is a test script (for Microsoft's XMLHTTPRequest component) that 
tests various forms of "If" headers.

Basically it does some sanity checks first, and then tries the new 
syntax allowing comma-separated lists (or multiple headers).

Of the servers I tested, none supported the new format (not 
surprisingly), but most (*) replied with 400 (bad request). This means 
clients can test that, and there doesn't seem to be any need for a new 
compliance class just for this use case.

Best regards, Julian

(* I notified the maintainers of the other two servers, one of which 
happens to be myself)

--

var req = new ActiveXObject ("MSXML2.ServerXMLHTTP");

if (WScript.Arguments.length == 0) {
   WScript.Echo("Test case If header eval");
   WScript.Echo("Usage: cscript if_fail.js URI {username} {password}");
   WScript.Quit(2);
}

var uri = WScript.Arguments(0);
var user = null;
var pwd = null;

function dumpResponse(r) {
   WScript.Echo(r.status);
   WScript.Echo(r.getAllResponseHeaders());
   WScript.Echo(r.responseText);
}

if (WScript.Arguments.length > 1) {
   user = WScript.Arguments(1);
}

if (WScript.Arguments.length > 2) {
   pwd = WScript.Arguments(2);
}

var x = 1;

function testPut(ifheader, desc) {

   WScript.Echo("\n\n\nTest case " + x + ", If header: " + ifheader);
   WScript.Echo("(" + desc + ")");
   req.open("PUT", uri, false, user, pwd);
   if (ifheader != null) req.setRequestHeader("If", ifheader);
   req.send("test case " + x);
   dumpResponse(req);
   x += 1;
}

// delete content
WScript.Echo("DELETE " + uri);
req.open("DELETE", uri, false, user, pwd);
req.send("foobar");
dumpResponse(req);

testPut(null, "initial content");
if (req.status < 200 || req.status >= 300) {
   WScript.Echo("unexpected status upon PUT");
   WScript.Quit(2);
}

testPut("(<DAV:no-lock>)", "const false");
if (req.status != 412) {
   WScript.Echo("unexpected status upon PUT");
}

testPut("(Not <DAV:no-lock>)", "const true");
if (req.status != 204 && req.status != 200) {
   WScript.Echo("unexpected status upon PUT");
}

testPut("(<DAV:no-lock> Not <DAV:no-lock>)", "const false");
if (req.status != 412) {
   WScript.Echo("unexpected status upon PUT");
}

testPut("(<DAV:no-lock>), (Not <DAV:no-lock>)", "const true using comma 
notation");
if (req.status == 200 || req.status == 204) {
   WScript.Echo("Server seems to understand ',' in If-List as per 
RFC2518bis");
}
else if (req.status == 400) {
   WScript.Echo("Server seems not to understand ',' in If-List as per 
RFC2518bis, rejecting the request with 400");
}
else {
   WScript.Echo("unexpected status upon PUT");
}

testPut("(Not <DAV:no-lock>), (Not <DAV:no-lock>)", "const false using 
comma notation");
if (req.status == 412) {
   WScript.Echo("Server seems to understand ',' in If-List as per 
RFC2518bis");
}
else if (req.status == 400) {
   WScript.Echo("Server seems not to understand ',' in If-List as per 
RFC2518bis, rejecting the request with 400");
}
else {
   WScript.Echo("unexpected status upon PUT");
}

---

From: Julian Reschke <[email-masked]>
Date: Sun, 23 Oct 2005 14:43:07 +0200

Hi,

I think there's an issue with the new If header syntax defined in 
RFC2518bis 
(<http://greenbytes.de/tech/webdav/draft-ietf-webdav-rfc2518bis-07.html#rfc.section.9.5>), 
allowing comma separation and consequently multiple instances of "If" 
headers.

In section 4.2, RFC2616 says 
(<http://greenbytes.de/tech/webdav/rfc2616.html#rfc.section.4.2.p.5>):

"Multiple message-header fields with the same field-name MAY be present 
in a message if and only if the entire field-value for that header field 
is defined as a comma-separated list [i.e., #(values)]."

RFC2518bis currently defines the grammar below:

    If = "If" ":" ( 1*No-tag-list | 1*Tagged-list)
    No-tag-list = List
    Tagged-list = Resource 1*List
    Resource = Coded-URL
    List = #( "(" List | Clause ")" )
    Clause = ["Not"] State-token | State-token
    State-token = Coded-URL  | "[" entity-tag "]"
    Coded-URL = "<" absoluteURI ">"

which clearly is different from what RFC2616 requires.

It may be possible to fix this, but as nobody seems to have implemented 
this yet, we should also think about whether it's really needed:

1) Did we ever *see* an interop problem because of message header 
lengths? Was it ever reported to the mailing list?

2) If there is indeed a problem, is this about the total length of a 
single header, or the length of each individual line? I'm asking because 
it is possible to split a *single* request header across multiple lines 
already.

Looking at 
<http://greenbytes.de/tech/webdav/draft-ietf-webdav-rfc2518bis-07.html#rfc.section.9.5.2>:

If: <http://www.example.com/resource1> (<locktoken:a-write-lock-token>
      [W/"A weak ETag"]), (["strong ETag"]),
      <http://www.bar.bar/random>(["another strong ETag"])

I think what we want is that this is the same thing as:

If: <http://www.example.com/resource1> (<locktoken:a-write-lock-token>
      [W/"A weak ETag"])
If: (["strong ETag"])
If: <http://www.bar.bar/random>(["another strong ETag"])

Which could also be written as:

If: <http://www.example.com/resource1> (<locktoken:a-write-lock-token>
      [W/"A weak ETag"])
     (["strong ETag"])
     <http://www.bar.bar/random>(["another strong ETag"])

today.

Feedback appreciated, Julian