Performs an HTTP request.

Performs an HTTP request.

This is a flexible and powerful HTTP client implementation. Correctly handles GET, POST, PUT or any other HTTP requests. Handles redirects.


EvanDonovan’s picture

See my comment on the D6 version of this function for information on how to use with HTTP Basic Authentication. (From the code above, it appears that part is unchanged between versions.)

Diogenes’s picture

D7 is a significant rewrite from D6, and things can go wrong.

Drupal relies on this function for a number of things, including available update info from drupal.org. The Drupal system module does a check that the hosting system can fetch outside info by checking for the php function ftp_connect() using the php function function_exists(). Don't ya just love this stuff?

D6 uses the functions fsockopen() fread() and fwrite()

D7 uses the functions stream_socket_client(), fread(), fwrite(), stream_set_timeout(), and stream_get_meta_data(). It also does some kind of funky chicken dance for handling timeouts.

In both cases, the functions to open the connection are prefixed with '@' characters, which suppresses error messages and inhibits fatal errors.

All worked fine on the dev machine, but when I uploaded to the host server, I started to get peppered with errors like these:

Notice: Undefined variable: errno in drupal_http_request() (line 829 of /foobar.com/includes/common.inc).
Notice: Undefined variable: errstr in drupal_http_request() (line 830 of /foobar.com/includes/common.inc).

In my case (as it turns out), my hosting provider had disabled a whole basket of php functions (41 in total) for security reasons. One of the disabled functions was stream_socket_client().

My host provider was kind enough to enable this function (after I told them it was now part of Drupal 7 core) but they offered the opinion that this was a security compromise.

I will leave that point for the experts to debate. In the meantime, checking for ftp_connect() and then using stream_socket_client() as the function is probably not the best practice. This error was a bugger to figure out.

iamsuriyan’s picture

I am also get the same error.How to resolve that.

Thanks in advance.

sethviebrock’s picture

$data = 'name=value&name1=value1';

$options = array(
                'method' => 'POST',
                'data' => $data,
                'timeout' => 15,
                'headers' => array('Content-Type' => 'application/x-www-form-urlencoded'),

$result = drupal_http_request('http://somewhere.com', $options);
opdavies’s picture

Thank you!! :D

Liam Morland’s picture

Use http_build_query() to create the $data string.

snufkin’s picture

Note that if you want to perform a GET requests then $options['data'] does not make any sense, since GET requests do not have a body.

For example:

$url = 'http://example.com';
$data = array(
'key1' => $value1,
'key2' => $value2,

$full_url = url($url, array('query' => $data));

pal4life’s picture

Yes this helped me, using the previous one gave me errors in the response, so paying attention to whether making a get or post call is important

Jaypan’s picture

I was getting a strange error when trying to authenticate with the Youtube API:

The request method <code>post</code> is inappropriate for the URL <code>/accounts/ClientLogin</code>. <ins>That’s all we know.</ins>

AKA (adding html free version to help with searches):

The request method post is inappropriate for the URL /accounts/ClientLogin. That’s all we know.

The problem was that I was setting the method as 'post' rather than 'POST'. Setting it to uppercase solved the problem.

mikeytown2’s picture

If you're looking for an alternative (that has very similar syntax) to what's in core, checkout the HTTP Parallel Request Library. It fixes a couple of bugs that I've encountered with core and is generally faster. The best part is it can issue multiple http requests at the same time and you can issue non-blocking requests.

a_thakur’s picture

If you want to send XML data by drupal_http_request, the following function might help. Apache Solr Module works this way and used the same concept in my work.

  $url = 'http://example.com/';
  $first_name = "Test";
  $age = "25";
  $data = '' . $first_name . '';
  $data .= '' . $age '';
  //You can concatenate more tags to the data.
  $options = array(
    'method' => 'POST',
    'data' => $data,
    'headers' => array('Content-Type' => 'text/xml; charset=UTF-8'),
  $result = drupal_http_request($url, $options);

Hope this helps somene.

kwfinken’s picture

This comment helped me a ton. I only wish I had stumbled on it a week ago, it would have saved me hours of research!

stickywes’s picture

My first experience trying to use this function instead of using something that takes a few more lines is not promising. There might be a hard to pin down bug in the implementation somewhere.

I tried to use this function to get a JSON response from an Arduino unit and consistently would lose a chunk of the JSON at the end. The problem completely ceased once I went back to using cURL.

R-omk’s picture

When hostname could not be resolved to DNS need use IP, but option 'Host' in 'Headers' always overridden.

$options['headers']['Host'] = $uri['host'] . ($port != 80 ? ':' . $port : '');
$options['headers']['Host'] = $uri['host'] . ($port != 443 ? ':' . $port : '');
pwaterz’s picture

I agree, you can NOT set the host header with this function.

mvc’s picture

See https://www.drupal.org/node/2555649 for a patch which permits setting the Host header.

sunset_bill’s picture

I was looking at http://www.mugginsoft.com/content/getting-and-setting-cookies-drupalhttp... which shows how to get cookies with an initial drupal_http_request in Drupal 6, but I'm having no luck yet adapting it to the Drupal 7 version. I'm guessing I need to put something in $options['headers'], but what?

dgtlmoon’s picture

Correct, cookie's are just another header item

texas-bronius’s picture

Yes, and that cookies array is stil part of the headers is part of the options array, so at simplest it would look like:

drupal_http_request($url, array(
  'headers' => array(
    'Cookies' => ...

Side note: To pass client browser cookies to persist local session with remote sites, check out http://www.bronius.com/pass-browser-cookie-values-drupal-http-request-us...

enrique.delgado’s picture

It it possible to send a multipart/form-data (enctype HTTP header) POST that includes a file using drupal_http_request? I don't seem to see anything in the code about it, but wanted to make sure.

Like an HTML form on a web page, I want to perform a POST with a file as one of the pieces of data to post into a server.

kemsnake’s picture

i have 2 servers local and dev. i am try to get avatar from facebook

$photo = drupal_http_request('https://graph.facebook.com/100001258517356/picture');

in my local server all ok - i get photo. but on dev - Connection timed out. Looks like server configuration problem.... What it can be?

jos_s’s picture

I was having Access Denied errors when using the Echo Module. It appeared that the Apache mod_security.c module was in the way.

I could then solve it by adding the following lines to the .htaccess:

<IfModule mod_security.c>
  SecFilterEngine Off
  SecFilterScanPOST Off
Andrea Gobetti’s picture

Hi, the module mod_security is there for a reason, I suggest you to investigate on the exact cause of the Access Denied errors and disable just the single rule that triggers the errors (with SecRuleRemoveById or SecRuleRemoveByTag), instead of disabling the entire module, exposing your website to possible attacks...

alabandit’s picture

I personally find echo's a little out of place, and normally use drupal_set_message
or for an array
drupal_set_message(''. print_r($_SESSION, true) .'');
It doesn't break the page layout, and is easy to read, and loads before default php errors.

wMarius’s picture

Hi guys, i have a problem, when i trie to use this drupal_http_request function its return /login page with redirected response 302. Can i send some data that shows that user is logged, or to escape this redirect and get the page i need?

me-taras’s picture

$response = \Drupal::service('http_default_client')

Xalk’s picture

Notice: Undefined offset: 1 в функции drupal_http_request() (строка 989 в файле /home//public_html//includes/common.inc).

Notice: Undefined offset: 2 в функции drupal_http_request() (строка 993 в файле /home//public_html//includes/common.inc).

Notice: Undefined offset: 1 в функции drupal_http_request() (строка 993 в файле /home//public_html//includes/common.inc).

list($response, $result->data) = preg_split("/\r\n\r\n|\n\n|\r\r/", $response, 2);
$response = preg_split("/\r\n|\n|\r/", $response);

// Parse the response status line.
list($protocol, $code, $status_message) = explode(' ', trim(array_shift($response)), 3);
$result->protocol = $protocol;
$result->status_message = $status_message;

tassaf’s picture


When I try to read this URL: "https://www.exporttrader.com"
using drupal_http_request('https://www.exporttrader.com') I got this error: "Error opening socket ssl://www.exporttrader.com:443"

any idea please?

ivanstegic’s picture

I've been getting the same error, and as mentioned below, it is related to SSL V3. There is an issue that patches core that seems to fix it https://drupal.org/node/1879970

exbuzz’s picture

This cropped up with PHP 5.6. Openssl was enabled, and the problem wasn't happening on 5.3. I tried the patch and forced it to use sslv3 and tls, but it did not do the job for me. I switched to the chr module, but as of now, SSL posts using drupal_http_request under PHP 5.6 is not working for me.

yookoala’s picture

This usually happens if the SSL cert is expired, self-signed or otherwise invalid.

You may just fix it by giving it a stream context that omits the peer check:

drupal_http_request('https://www.exporttrader.com', array(
  'context' => stream_context_create(array(
    'ssl' => array('verify_peer' => FALSE, 'verify_peer_name' => FALSE), // omit peer check in the stream context

tassaf’s picture

OOOOH finally I found the solution.. it's by using SSL v3

curl_setopt($ch, CURLOPT_SSLVERSION, 3);

arthur_drupal’s picture

Thanx man ! End of 6 hours headache to enable nodejs on my local via https !!!!

vks7056’s picture

I want to know that does drupal_http_request use curl to send http request? If we disabled curl, will drupal_http_request work or not?

sri20198’s picture

It does not use cURL.

Looking at the function code, it uses a socket connection with the method stream_socket_client(). The working of this function will depend on how the sockets related functions are configured on your server. Also look up the comment by Diogenes.

a.ross’s picture

While debugging various unexpected error codes, I found out that $result->code can actually contain far more things than merely the HTTP response codes. The documentation does not make this very clear:

code: An integer containing the response status code, or the error code if an error occurred.

Here's a list of error codes you may encounter, with their meaning ($result->error), grouped by source:

  • Error codes stemming from the function itself:
    • -1 (request timed out)
    • -1001 (unable to parse URL)
    • -1002 (missing schema)
    • -1003 (invalid schema [schema])
  • HTTP response codes (if an error, it will be the name of the HTTP status message as returned by the web server):
    • 200
    • 404 (Not Found)
    • 500 (Internal Server Error)
    • etc...
  • Error codes returned by stream_socket_client(), negated to prevent clashing with HTTP status codes. God knows if they may collide with the negative error codes the function itself can return, though. As per the docs, most of the time errors from this will be the error from the actual <a href="http://www.tutorialspoint.com/unix_system_calls/connect.htm">connect()</a> system call. The actual numerical values of the errors are listed here. I've also seen error code 0 and I have no idea what that could mean:
    • -110 (Connection timed out)
    • -111 (Connection refused)
    • etc...
    • 0 (????)
a.ross’s picture

This lists the errors of the actual connect() system call.

hgoto’s picture

Thank you for your helpful comment on code list.

crystaldawn’s picture

I was getting a lot of timeout problems with a client's site to an offsite REST API so to help it out I added a timeout to drupal_http_request thinking that the timeout value would be exactly what I set it to. HAH fat chance. As Diogenes note's above, D7 does a chicken dance for timeouts, I think it should be renamed to "The fail dance" hehe. Anyway, setting a time out of 10, you'd think it would timeout after 10 seconds. But it doesnt. It times out after 20 seconds which is exactly double what I put. So to test this theory I used a brand new D7 and made it connect to the SAME server hitting a test.php in it that had nothing other than a sleep(30); echo "hi"; in it. Then I set the timeout to 20. Sure enough, it displayed "hi" when it SHOULD have timed out. So, I lowered it to 15. It then started showing "hi" intermittantly. Sometimes it would show, others it wouldnt. Lowered it to 10 and it timed out after 20 seconds each time. I used chrome's network console to see the times before it timed out.

So word to the wise, if you use timeout's, remember that they are DOUBLED for whatever reason.

taggartj’s picture

ok so say you are trying to use drupal_http_request with in your own site
to a protected menu path ...but getting access denied ... but you are lodged ?!
well have a look at this ...

Cookie userSessionName = userSessionId

global $user;
$long_url = 'http://SOME PROTECTED DRUPAL URL YOU ARE TRYING TO MAKE A drupal_http_request to on your site ';
$session_name = ini_get('session.name'); 
$headers = array('headers' => array('Cookie' => $session_name.'='.$user->sid));
$request = drupal_http_request( $long_url , $headers);

Pravin Ajaaz’s picture

I need to know only the status message of a list of URLs. Whether it is accessible or Not Found. So that the data can be retrieved much faster. How can I do that.

dgtlmoon’s picture

Please note, this call does NOT yet support HTTP/1.1! Specifically 1.1 requires handling of chunked encoding

[#2242123] [#106506]

This is probably fixed in D8

mizage’s picture

We are sending data to a salesforce API and they are seeing long messages get cut. Is there a size limit for posts? When I run it through a debugger everything seems ok coming in to this function so I'm not sure where the data is being truncated.

charlesj’s picture

I am calling a translation API that requires the payload of the GET request to be in the body.
I've tried the sample code from above, changing POST to GET, but no luck.

(I am able to do this through cURL, but I'd like to see if it is possible through http_drupal_request)

Hs anyone else had any luck doing this?

colepacak’s picture

I'm in the same boat where the following worked:

drupal_http_request($url . '?key=value');

But it didn't work to pass in the query params as the data property. Take a look at Snufkin's response above - four years ago and still relevant :)

nvahalik’s picture

Using Drupal 7.36, this function returns an error code of -60, which appears to be PHP's SOCKET_ETIMEDOUT value of 60 sign-inverted by this function. If you're writing code and depending on HTTP_REQUEST_TIMEOUT to let you know that you're request timed out, you better check for this value as well.

$response = drupal_http_request($url, array('timeout' => 7, 'headers' => array('Accept-Encoding' => 'gzip')));
if ($response->code == -SOCKET_ETIMEDOUT || $response->code == HTTP_REQUEST_TIMEOUT) {
  // Add timeout handling here...
sanduhrs’s picture

ws.agency’s picture

In Drupal 8 this function is replaced with Guzzle HTTP client

$client = \Drupal::httpClient();
$request = $client->createRequest('GET', $feed->url);
danisha’s picture

This function does not return the data when called inside any ajax submit.

I am using hook_search_form_submit_ajax($form, &$form_state) but its returning the empty data string. The status comes as OK but the data is unavaiable. I have used both php curl functions and drupal_http_request but nothing works. Both the functions works correct for normal php functions.

Can someone help me with this?

dazweeja’s picture

It should be mentioned in the description that this does not support HTTPS when also using a proxy. This is a very significant limitation.