The function drupal_http_request() adds 'Content-Length' header even if there is no content in the request. Even if this should be ok, some web servers seem to have problems with it. For example, you cannot use aggregator to fetch feeds from http://www.yle.fi/uutiset/rss/ymparisto.xml .

The following patch makes 'Content-Length' header go away when there's no content in the request.

The patch command to run is: (run it in your drupal base dir)

patch -Np1 <drupal_http_request_content_length_0.patch
Support from Acquia helps fund testing for Drupal Acquia logo

Comments

skiminki’s picture

Status: Active » Needs review
Damien Tournoud’s picture

Version: 5.7 » 7.x-dev
Status: Needs review » Patch (to be ported)

The patch looks good, but bugs have to be fixed in the current development version (7.x) first, than backported. Can you reroll a patch for 7.x?

casperbiering’s picture

Status: Patch (to be ported) » Active
FileSize
692 bytes

Here is an updated patch which should work for 7.x-dev.

lilou’s picture

Status: Active » Needs review
c960657’s picture

Status: Needs review » Needs work

Some servers (e.g. Squid that is often used in a reverse proxy scenario) seems to require the Content-Length header for POST and PUT requests, even if the message body is empty. You can verify this by sending the following request to drupal.org:80 using a telnet client - the server responds with 411 Length Required:

POST /foo HTTP/1.0
Host: drupal.org

I suggest that Content-Length is also added if the request method is POST or PUT, even if $options['data'] is empty. I assume that the problem described in this issue only occurs with GET requests.

BTW, the HTTP spec isn't very clear about whether sending a Content-Length for GET requests is allowed:
http://lists.w3.org/Archives/Public/ietf-http-wg/2006AprJun/0103.html

casperbiering’s picture

Status: Needs work » Needs review
FileSize
1.04 KB

In my case (http://johannes.hansen.name/) it is at least HEAD and GET requests. POST and PUT works fine for me with zero-length content.

Status: Needs review » Needs work

The last submitted patch failed testing.

casperbiering’s picture

Status: Needs work » Needs review
FileSize
1.01 KB

Patch contained "incorrect" file path (i believe)

c960657’s picture

I tested this, and it works.

One teeny-weeny nit: Most short strings in Drupal use single quotes (unless they contain escaped characters like \n etc.), so for consistency I suggest you use that.

Status: Needs review » Needs work

The last submitted patch failed testing.

c960657’s picture

Status: Needs work » Needs review
FileSize
1.79 KB

Reroll.

Status: Needs review » Needs work

The last submitted patch failed testing.

c960657’s picture

Status: Needs work » Needs review
Dries’s picture

Two possible micro optimizations:

1. It is not clear whether strlen() is a fast operation (e.g. the length is cached) or a slow operation (e.g. we need to count all characters in the string), but we are calling it twice now on the same string.

2. It might be faster to check the request type before doing a strlen().

c960657’s picture

I couldn't find a good reference, but I think that if (!$foo) may be slightly faster than using strlen().

sun’s picture

Status: Needs review » Needs work
+  // Only add 'Content-Length' if we actually have any content or if it is a
+  // POST or PUT request. Some non-standard servers get confused by content length
+  // in at least HEAD/GET requests, and Squid always requires content length in
+  // POST/PUT requests.

Please use Content-Length consistently here.

+  if ($options['data'] ||
+      $options['method'] == 'POST' ||
+      $options['method'] == 'PUT') {

I don't see why that needs to be multi-line. Additionally, !empty() for $options['data'] wouldn't hurt for clarity.

c960657’s picture

Status: Needs work » Needs review
FileSize
1.78 KB

Thanks for the review. This patch addresses your comments.

Dries’s picture

Status: Needs review » Needs work

Unfortunately, this patch no longer applies. It needs a quick re-roll. I'll commit after reroll.

c960657’s picture

Status: Needs work » Needs review
FileSize
2.05 KB

Reroll.

Dries’s picture

Status: Needs review » Fixed

Committed to CVS HEAD. Thanks!

andypost’s picture

Version: 7.x-dev » 6.x-dev
Status: Fixed » Needs review
Issue tags: +Needs backport to D6
FileSize
1.25 KB

It's easy to port first to 6.x

c960657’s picture

Status: Needs review » Needs work
+    $defaults['headers']['Content-Length'] = strlen($data);

should be

+    $defaults['Content-Length'] = strlen($data);
andypost’s picture

Status: Needs work » Needs review
FileSize
1.24 KB

Here reroll with #22 and against current DRUPAL-6

c960657’s picture

Status: Needs review » Needs work

Seems my advice in #22 was bad. Now the Content-Length header isn't added at all.

andypost’s picture

Status: Needs work » Needs review
FileSize
1.25 KB

@c960657 This was my fault, in drupal 6 array of headers holds values same as keys

  // Create HTTP request.
  $defaults = array(
    // RFC 2616: "non-standard ports MUST, default ports MAY be included".
    // We don't add the port to prevent from breaking rewrite rules checking the
    // host that do not take into account the port number.
    'Host' => "Host: $host",
    'User-Agent' => 'User-Agent: Drupal (+http://drupal.org/)',
-    'Content-Length' => 'Content-Length: '. strlen($data)
  );

Here examples
drupal_http_request('http://www.drupal.org/');

GET / HTTP/1.0
Host: www.drupal.org
User-Agent: Drupal (+http://drupal.org/)

drupal_http_request('http://www.drupal.org/', array(), 'POST');

POST / HTTP/1.0
Host: www.drupal.org
User-Agent: Drupal (+http://drupal.org/)
Content-Length: 0

c960657’s picture

Status: Needs review » Reviewed & tested by the community

Looks good now.

pwolanin’s picture

there is a possible flaw here - I think I can't GET/DELETE/etc the character '0' as the entire entity-body.

However, that's probably irrelevant to normal operation.
if we care about that (maybe not) we want something like this change instead:

+  // Only add Content-Length if we actually have any content or if it is a POST
+  // or PUT request. Some non-standard servers get confused by Content-Length in
+  // at least HEAD/GET requests, and Squid always requires Content-Length in
+  // POST/PUT requests.
+  $content_length = strlen($data);
+  if ($content_length > 0 || $method == 'POST' || $method == 'PUT') {
+    $defaults['Content-Length'] = 'Content-Length: '. $content_length;
+  }
+
sun’s picture

Status: Reviewed & tested by the community » Needs work
+    $defaults['Content-Length'] = 'Content-Length: '. $content_length;

btw, also using wrong string concatenation (the patch, not pwolanin who just copied).

pwolanin’s picture

Status: Needs work » Reviewed & tested by the community

@sun - no this is the D6 backport, why is that wrong?

sun’s picture

oopsie. sorry, I'm slow.

andypost’s picture

POST with "0" is never happen because it's contents always name: value
http://en.wikipedia.org/wiki/HTTP_POST

Damien Tournoud’s picture

Version: 6.x-dev » 7.x-dev
Status: Reviewed & tested by the community » Needs work

The POST body in the general case is free-form, so we should allow posting '0'.

andypost’s picture

Status: Needs work » Needs review
FileSize
1.28 KB
1.01 KB

Fixed as @pwolanin proposed

Dries’s picture

Version: 7.x-dev » 6.x-dev

Committed to CVS HEAD. Thanks!

pwolanin’s picture

Status: Needs review » Patch (to be ported)

needs to be ported for D6

andypost’s picture

Status: Patch (to be ported) » Needs review

Look at #33 thare's a D6 patch

andypost’s picture

c960657’s picture

Status: Needs review » Reviewed & tested by the community

Looks good.

Gábor Hojtsy’s picture

Status: Reviewed & tested by the community » Fixed

Committed to Drupal 6, thanks!

pwolanin’s picture

Version: 6.x-dev » 5.x-dev
Status: Fixed » Patch (to be ported)
marcingy’s picture

Status: Patch (to be ported) » Closed (won't fix)

Marking as won't fix as d5 is end of life.