drupal_http_request - case sensitive HTTP header field names
Aron Novak - September 4, 2008 - 08:48
| Project: | Drupal |
| Version: | 7.x-dev |
| Component: | base system |
| Category: | bug report |
| Priority: | normal |
| Assigned: | Unassigned |
| Status: | needs review |
Description
Problem:
http://www.alphagalileo.org/rss_channels/?feed=all . This URL uses redirect.
The redirect happens in this way:
GET /rss_channels/?feed=all HTTP/1.0
User-Agent: Wget/1.10.2 (Red Hat modified)
Accept: */*
Host: www.alphagalileo.org
Connection: Keep-Alive
HTTP/1.1 307 Temporary Redirect
Connection: close
Date: Thu, 04 Sep 2008 08:25:16 GMT
Server: Microsoft-IIS/6.0
X-Powered-By: ASP.NET
Set-Cookie: CFID=4574600;expires=Sat, 28-Aug-2038 08:25:16 GMT;path=/
Set-Cookie: CFTOKEN=67833421;expires=Sat, 28-Aug-2038 08:25:16 GMT;path=/
location: http://www.alphagalileo.org/rss_channels/all.xml
Content-Type: text/html; charset=UTF-8wget handles http response header field names differently as Drupal does. (see resp_header_locate in http.c at wget source code)
Drupal treats these field names case sensitive, wget does the opposite. I read the RFC 2616, but it's not clear me that Drupal does or does not follow the RFC in the question. But for practical reasons it should work as wget.
I attached a patch to fix this issue. It basically makes all the header field names lowercase and fix the places in drupal core where it matters.
| Attachment | Size | Status | Test result | Operations |
|---|---|---|---|---|
| http_case_insensitive_fields.patch | 4.01 KB | Idle | Failed: Failed to apply patch. | View details | Re-test |

#1
Let's write a simpletest for this?
#2
I wrote a test for this bug. I re-rolled the patch, now it contains the test too.
#3
I rerolled the patch to make it apply without any notices.
#4
The last submitted patch failed testing.
#5
See: #335122: Test clean HEAD after every commit and http://pastebin.ca/1258476
#6
The last submitted patch failed testing.
#7
Rerolled against HEAD.
#8
The last submitted patch failed testing.
#9
Message header field names are case insensitive (see Message Headers in RFC 2616), so it looks like wget got it right:
I'm confused about the patch though:
If we just established that header field names are case insensitive, then why are we changing the case of these field names, especially since the RFC uses capitalized field names itself (for example: If-Modified-Since)? Note: I'm not saying it's the wrong approach, I'm just not sure I fully understand the problem.
#10
Well, you can do the strtolower() at every comparison, but this sucks. I think the right approach is to use it always lower-case in Drupal (except when we issue a request) and use strtolower() only when parsing the http requests.
I have to take a look why the patch failed.
#11
I looked closer at your patch and the test and think I now understand the problem a bit better. I also agree that using strtolower() or strcasecmp() isn't the most elegant solution. I can't shake off the feeling that the proposed patch treats the symptoms rather than the actual problem though, but I understand your reasoning.
And now on to the actual patch:
if (isset($result->headers[$header]) && $header == 'Set-Cookie') {// RFC 2109: the Set-Cookie response header comprises the token Set-
// Cookie:, followed by a comma-separated list of one or more cookies.
- $result->headers[$header] .= ',' . trim($value);
+ $result->headers[strtolower($header)] .= ',' . trim($value);
}
I think this can become a bit messy: if I'm not mistaken, we can end up with two values, $result->headers['Set-Cookie'] and $result->headers['set-cookie'] which have different values?
* - headers* An array containing the response headers as name/value pairs.
as well as when the actual lowercase conversion happens.
#12
Well, I think the actual problem is that PHP doesn't support an array-like datatype with case-insensitive keys. The strtolower() approach is also used in SimpleTest in DrupalWebTestCase::drupalGetHeaders().
- $headers['If-None-Match'] = $feed->etag;+ $headers['if-none-match'] = $feed->etag;
#13
Updated patch.
#14
The last submitted patch failed testing.
#15
Ahem.
#16
The last submitted patch failed testing.
#17
It's been a while, but here is a reroll.