#2438 Removing quotes from Set-cookie headers

Jeremy Criquet Tue 28 Jul 2015

I'm curious why these lines are in Cookie.fan: (lines 40 and 41)

if (val.size >= 2 && val[0] == '"' && val[-1] == '"')
  val = WebUtil.fromQuotedStr(val)

I made a WebClient that (after sending a request) receives a response that looks something like:

...
Set-cookie: abc=123; expires=Wed, 27-Jul-2016 22:58:25 GMT; Path=/
Set-cookie: def=456; expires=Wed, 27-Jul-2016 22:58:25 GMT; Path=/
Set-cookie: ghi="789"; expires=Wed, 27-Jul-2016 22:58:25 GMT; Path=/
...

Now, when I make this request in my browser (Chrome, in this case), the Cookie header looks something like:

Cookie: abc=123; def=456; ghi="789"

Yet, the WebClient is instead sending something like:

Cookie: abc=123; def=456; ghi=789

This may seem insignificant. However, this particular web-server (and I've found this in more then one scenario) relies on the quotes remaining in place. With them stripped, I'm getting a response that my browser isn't supported (because they don't understand the cookie being sent). If I add the quotes to every cookie, then they give me an internal service error.

In the past, I've simply hard-coded special cases into my code to handle these particular cookies. However, I'm trying to generalize things now and really need a way to keep the cookies in their original form.

I would just parse the Set-cookie header, yet since it gets a simple "join(,)" used to generate it, it mucks up my split results because there are other commas in the Set-cookie string.

There's tons of ways to fix this in the source code, yet I really don't see why quotes need to be removed in the first place. This has been like this for a while though so changing that particular piece could potentially be a breaking change.

SlimerDude Wed 29 Jul 2015

As mentioned in the RFC 6265 section 4.1.1, Cookie values may optionally be surrounded in Double Quotes. So lines 40 and 41 simply remove them should they exist.

This, very old, stackoverflow question sheds some light on why double quoting is optional. (Essentially, it's evolving standards.)

Why do cookie values with whitespace arrive at the client side with quotes?

Further more, the above RFC link stipulates that double quote characters are not allowed as cookie value octets (characters):

cookie-value      = *cookie-octet / ( DQUOTE *cookie-octet DQUOTE )
cookie-octet      = %x21 / %x23-2B / %x2D-3A / %x3C-5B / %x5D-7E
                     ; US-ASCII characters excluding CTLs,
                     ; whitespace DQUOTE, comma, semicolon,
                     ; and backslash

(So arguably Cookie.make() should be more strict on this.) Percent encoding of cookie values seems to be the way forward.

Back to your problem, I'm a bit confused as to who is setting cookie values with quotes. Is it the (Fantom?) server or the browser?

brian Wed 29 Jul 2015

So just to be clear, we are talking about WebClient sending cookies to the server correct?

What server is not properly handling them?

The existing cookie code is pretty well field testing, so I'd hate to change the behavior - especially since I'm pretty sure we are adhering to the spec, and it sounds like your server is not.

Jeremy Criquet Wed 29 Jul 2015

It's a utility meter website which I have no control over. Yes, I'm talking about WebClient. The external server sets the cookie with a response header Set-cookie and subsequent requests that I make need to send that cookie in a Cookie header. Hopefully this clears any confusion?

I see that the point is to fit the spec, however we are not behaving as modern browsers are. My example shows that what the server sends me is being modified and not sent back as intended. Even if it fits the spec, Chrome and Firefox both do not modify the cookies like so (they send the quotes if they were supplied the quotes). I'm not saying we need to change the cookies, per-say. But it would at least be good to know if the server sent me a Set-cookie header with quotes in it or not.

Maybe if the cookie removes the quotes, a boolean can be set?

SlimerDude Wed 29 Jul 2015

As a workaround, could you not manipulate the request / response headers yourself? Using reqHeaders and resHeaders?

Jeremy Criquet Wed 29 Jul 2015

Like I said, since they are concatenated together with comma's, I have no way of telling if a comma separates a cookie or was in the original Set-cookie header.

Another thing I noticed (this is something I can work around but still want to mention) is that Fantom is sending a cookie header like so:

Cookie: abc=123,def=456,ghi=789

When it should be (if we want to mimic modern browsers):

Cookie: abc=123; def=456; ghi=789

Sites like http://myhttp.info/ show a set of cookies all as 1 cookie with a bunch of commas in it.

I think the internet convention is to fit was modern browsers want, even if the standards define something else. For this reason, I think it important that we follow the trend or our WebClient will often not be able to work with certain sites.

matthew Mon 3 Aug 2015

Ticket promoted to #2438 and assigned to matthew

Opening a ticket for this. The planned resolution is to adhere more closely to RFC6265

  1. Change WebClient to encode "Cookie" request header with cookies separated by semicolon (;) instead of comma (,)
  2. Change Cookie.fromStr to not strip double-quotes (") from cookie value. Implement the suggested algorithm from section 5.2 of the RFC for parsing the cookie-name-value pair.

Jeremy Criquet Mon 3 Aug 2015

Thanks so much. As far as I can tell, this should make Cookies function much closer to an actual modern web browser.

matthew Mon 3 Aug 2015

Ticket resolved in 1.0.68

Resolved per steps outlined in earlier comment, with this additional change:

  1. Cookie.toStr no longer uses WebUtil.toQuotedStr to encode the value. The value is written "as-is".

Login or Signup to reply.