drupal_http_request() adds 'Content-Length' header even if there's no content in the request

skiminki - July 9, 2008 - 07:15
Project:Drupal
Version:5.x-dev
Component:base system
Category:bug report
Priority:normal
Assigned:Unassigned
Status:patch (to be ported)
Issue tags:needs backport to D6
Description

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

AttachmentSizeStatusTest resultOperations
drupal_http_request_content_length_0.patch897 bytesIdleFailed: Failed to apply patch.View details | Re-test

#1

skiminki - July 9, 2008 - 07:21
Status:active» needs review

#2

Damien Tournoud - July 9, 2008 - 10:24
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?

#3

casperbiering - February 12, 2009 - 12:46
Status:patch (to be ported)» active

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

AttachmentSizeStatusTest resultOperations
drupal_http_request_content_length_0_for_7x-dev.patch692 bytesIdleFailed: 10366 passes, 0 fails, 1 exceptionView details | Re-test

#4

lilou - February 12, 2009 - 14:28
Status:active» needs review

#5

c960657 - February 14, 2009 - 11:47
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

#6

casperbiering - February 17, 2009 - 08:34
Status:needs work» needs review

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.

AttachmentSizeStatusTest resultOperations
drupal_http_request_content_length_0_for_7x-dev_2.patch1.04 KBIdleFailed: Failed to apply patch.View details | Re-test

#7

System Message - February 17, 2009 - 08:50
Status:needs review» needs work

The last submitted patch failed testing.

#8

casperbiering - February 17, 2009 - 09:20
Status:needs work» needs review

Patch contained "incorrect" file path (i believe)

AttachmentSizeStatusTest resultOperations
drupal_http_request_content_length_0_for_7x-dev_3.patch1.01 KBIdleFailed: 10618 passes, 1 fail, 0 exceptionsView details | Re-test

#9

c960657 - February 25, 2009 - 21:42

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.

#10

System Message - March 19, 2009 - 10:40
Status:needs review» needs work

The last submitted patch failed testing.

#11

c960657 - March 24, 2009 - 17:23
Status:needs work» needs review

Reroll.

AttachmentSizeStatusTest resultOperations
drupal_http_request_content_length_0_for_7x-dev_4.patch1.79 KBIdleFailed: Failed to apply patch.View details | Re-test

#12

System Message - April 4, 2009 - 00:45
Status:needs review» needs work

The last submitted patch failed testing.

#13

c960657 - April 25, 2009 - 14:32
Status:needs work» needs review

#14

Dries - April 26, 2009 - 15:56

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().

#15

c960657 - April 26, 2009 - 21:58

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

AttachmentSizeStatusTest resultOperations
drupal_http_request_content_length_0_for_7x-dev_5.patch1.79 KBIdleUnable to apply patch drupal_http_request_content_length_0_for_7x-dev_5.patchView details | Re-test

#16

sun - May 3, 2009 - 04:30
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.

#17

c960657 - May 4, 2009 - 18:39
Status:needs work» needs review

Thanks for the review. This patch addresses your comments.

AttachmentSizeStatusTest resultOperations
drupal_http_request_content_length_0_for_7x-dev_6.patch1.78 KBIdleFailed: Failed to apply patch.View details | Re-test

#18

Dries - May 9, 2009 - 18:53
Status:needs review» needs work

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

#19

c960657 - May 9, 2009 - 20:35
Status:needs work» needs review

Reroll.

AttachmentSizeStatusTest resultOperations
drupal_http_request_content_length_0_for_7x-dev_7.patch2.05 KBIdleFailed: Failed to apply patch.View details | Re-test

#20

Dries - May 9, 2009 - 22:16
Status:needs review» fixed

Committed to CVS HEAD. Thanks!

#21

andypost - May 10, 2009 - 12:18
Version:7.x-dev» 6.x-dev
Status:fixed» needs review

It's easy to port first to 6.x

AttachmentSizeStatusTest resultOperations
drupal_http_request_content_length_D6.patch1.25 KBIgnoredNoneNone

#22

c960657 - May 18, 2009 - 20:56
Status:needs review» needs work

+    $defaults['headers']['Content-Length'] = strlen($data);
should be
+    $defaults['Content-Length'] = strlen($data);

#23

andypost - May 18, 2009 - 21:43
Status:needs work» needs review

Here reroll with #22 and against current DRUPAL-6

AttachmentSizeStatusTest resultOperations
drupal_http_request_content_length_D6.patch1.24 KBIgnoredNoneNone

#24

c960657 - June 11, 2009 - 17:36
Status:needs review» needs work

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

#25

andypost - June 12, 2009 - 13:57
Status:needs work» needs review

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

<?php
 
// 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

<?php
drupal_http_request
('http://www.drupal.org/');
?>

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

<?php
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

AttachmentSizeStatusTest resultOperations
drupal_http_request_content_length_D6.patch1.25 KBIgnoredNoneNone

#26

c960657 - June 14, 2009 - 12:55
Status:needs review» reviewed & tested by the community

Looks good now.

#27

pwolanin - June 16, 2009 - 20:23

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;
+  }
+

#28

sun - June 16, 2009 - 20:28
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).

#29

pwolanin - June 16, 2009 - 20:43
Status:needs work» reviewed & tested by the community

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

#30

sun - June 16, 2009 - 21:08

oopsie. sorry, I'm slow.

#31

andypost - June 17, 2009 - 07:54

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

#32

Damien Tournoud - June 17, 2009 - 08:27
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'.

#33

andypost - June 17, 2009 - 08:53
Status:needs work» needs review

Fixed as @pwolanin proposed

AttachmentSizeStatusTest resultOperations
drupal_http_request_content_length.patch1.01 KBIdlePassed: 11116 passes, 0 fails, 0 exceptionsView details | Re-test
drupal_http_request_content_length_D6.patch1.28 KBIgnoredNoneNone

#34

Dries - June 17, 2009 - 11:08
Version:7.x-dev» 6.x-dev

Committed to CVS HEAD. Thanks!

#36

pwolanin - July 5, 2009 - 16:14
Status:needs review» patch (to be ported)

needs to be ported for D6

#37

andypost - July 5, 2009 - 16:35
Status:patch (to be ported)» needs review

Look at #33 thare's a D6 patch

#38

andypost - July 5, 2009 - 16:40

Reroll

AttachmentSizeStatusTest resultOperations
drupal_http_request_content_length_D6.patch1.73 KBIgnoredNoneNone

#39

c960657 - July 9, 2009 - 21:19
Status:needs review» reviewed & tested by the community

Looks good.

#40

Gábor Hojtsy - August 10, 2009 - 10:56
Status:reviewed & tested by the community» fixed

Committed to Drupal 6, thanks!

#41

pwolanin - August 10, 2009 - 13:12
Version:6.x-dev» 5.x-dev
Status:fixed» patch (to be ported)

backport for Drupal 5? http://api.drupal.org/api/function/drupal_http_request/5

 
 

Drupal is a registered trademark of Dries Buytaert.