1

Following examples found here and in API, I tried 2 methods, both return a bad request status message.

First method

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

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

$result = drupal_http_request('http://example.com/foo', $options);

dpm($result);

Second method

$data = array(
  'key1' => $value1,
  'key2' => $value2,
);

$full_url = url('http://example.com/foo', array('query' => $data));

$options = array(
  'method' => 'GET',
  'timeout' => 15,
  'headers' => array('Content-Type' => 'application/x-www-form-urlencoded'),
);
$result = drupal_http_request($full_url, $options);

dpm($result);

Which one is the good one and what's wrong ? Thank you

Edit

This is dpm($result)

enter image description here

1 Answer 1

3

The first method is correct; you should not use url() for an external URL that is passed to drupal_http_request(), except (for example) when you want other modules to alter the hook via their hook_url_outbound_alter() implementations, or you want to let url() split off the fragment (or the query) from the URL. (The fragment is used to set $options['fragment'], when it's not already set; the query is added to $options['query'].

The code run by url() for an external URL is the following one. (I showed only the relevant code; where I omitted code, I used an // Omissis comment. I also removed the original comments from the code and added mine to evidence some code parts.)

if (!isset($options['external'])) {
  $options['external'] = $path === $_GET['q'] ? FALSE : url_is_external($path);
}

// Omissis

if ($options['external']) {
  if (strpos($path, '#') !== FALSE) {
    list($path, $old_fragment) = explode('#', $path, 2);
    if (isset($old_fragment) && !$options['fragment']) {
      $options['fragment'] = '#' . $old_fragment;
    }
  }

  if ($options['query']) {
    $path .= (strpos($path, '?') !== FALSE ? '&' : '?') . drupal_http_build_query($options['query']);
  }

  // Change the URL protocol basing on a Drupal local setting.
  if (isset($options['https']) && variable_get('https', FALSE)) {
    if ($options['https'] === TRUE) {
      $path = str_replace('http://', 'https://', $path);
    }
    elseif ($options['https'] === FALSE) {
      $path = str_replace('https://', 'http://', $path);
    }
  }

  return $path . $options['fragment'];
}

Apart from what I reported before, there isn't much any pro in using url() when used for a string you already know it contains an external URL. The part commented with Change the URL protocol basing on a Drupal local setting. only changes the used protocol basing on the value of $options['https'], when a local Drupal settings has been set to TRUE. For a string that contains already an external URL, which is then passed to drupal_http_request(), that code isn't much helpful; you would know already if the external URL needs to be accessed via https:// or http://, and you would not want to change the used protocol basing on a local setting.

application/x-www-form-urlencoded is the content type used when POSTing data, while you are GETting data.

To build the query data, you could also use drupal_http_build_query(), which the same function used from url() for the same purpose.

$data = array('name' => 'value', 'name1' => 'value1');

$options = array(
  'method' => 'GET',
  'data' => drupal_http_build_query($data),
  'timeout' => 15,
);

$result = drupal_http_request('http://example.com/foo', $options);
4
  • Thanks a lot. I added dpm($result) in the question. So if this is correct, does the bad request means that the code is ok, but the target website was expecting another query ?
    – Kojo
    Dec 6, 2015 at 14:02
  • Bad request means the server cannot understand the request, which could simply be because you are setting the content type that is expected from a POST, or because you are passing the wrong data for example.com/foo. I would think it is the first case.
    – apaderno
    Dec 6, 2015 at 15:13
  • All rights, I'll check better the remote expected configuration. Grazie mile per il suo tempo ;)
    – Kojo
    Dec 6, 2015 at 17:04
  • The second method is correct if you're wanting to pass the data as query parameters: $full_url = url('http://example.com/foo', array('query' => $data)); The 'data' option only refers to the body of the request, not the query parameters. See: api.drupal.org/api/drupal/includes%21common.inc/function/…
    – imclean
    Dec 12, 2018 at 21:55

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.