https://HTTP handling, _drupal_parse_response_status, drupal_parse_url, api.drupal.org/api/drupal/includes%21common.inc/group/http_handling/7

Public

function _drupal_parse_response_status

7 common.inc _drupal_parse_response_status($response)
Splits an HTTP response status line into components.

See the status line definition in RFC 2616.

Parameters

string $respone: The response status line, for example 'HTTP/1.1 500 Internal Server Error'.

Return value

array Keyed array containing the component parts. If the response is malformed, all possible parts will be extracted. 'reason_phrase' could be empty. Possible keys:

'http_version'
'response_code'
'reason_phrase'
Related topics

HTTP handling
Functions to properly handle HTTP responses.
2 calls to _drupal_parse_response_status()
File

includes/common.inc, line 1105
Common functions that many Drupal modules will need to reference.

</> CopyGet raw version
php
  1. function _drupal_parse_response_status($response) {
  2. $response_array = explode(' ', trim($response), 3);
  3. // Set up empty values.
  4. $result = array(
  5. 'reason_phrase' => '',
  6. );
  7. $result ['http_version'] = $response_array [0];
  8. $result ['response_code'] = $response_array [1];
  9. if (isset($response_array [2])) {
  10. $result ['reason_phrase'] = $response_array [2];
  11. }
  12. return $result;
  13. }

function drupal_parse_url

7 common.inc drupal_parse_url($url)
Parses a URL string into its path, query, and fragment components.

This function splits both internal paths like

node?b=c#d
and external URLs like

https://example.com/a?b=c#d
into their component parts. See RFC 3986 for an explanation of what the component parts are.

Note that, unlike the RFC, when passed an external URL, this function groups the scheme, authority, and path together into the path component.

Parameters

string $url: The internal path or external URL string to parse.

Return value

array An associative array containing:

path: The path component of $url. If $url is an external URL, this includes the scheme, authority, and path.
query: An array of query parameters from $url, if they exist.
fragment: The fragment component from $url, if it exists.
See also

drupal_goto()

l()

url()

http://tools.ietf.org/html/rfc3986

Related topics

HTTP handling
Functions to properly handle HTTP responses.
PHP wrapper functions
Functions that are wrappers or custom implementations of PHP functions.
6 calls to drupal_parse_url()
File

includes/common.inc, line 575

</> CopyGet raw version
php
  1. function drupal_parse_url($url) {
  2. $options = array(
  3. 'path' => NULL,
  4. 'query' => array(),
  5. 'fragment' => '',
  6. );
  7.  
  8. // External URLs: not using parse_url() here, so we do not have to rebuild
  9. // the scheme, host, and path without having any use for it.
  10. if (strpos($url, '://') !== FALSE) {
  11. // Split off everything before the query string into 'path'.
  12. $parts = explode('?', $url);
  13. $options ['path'] = $parts [0];
  14. // If there is a query string, transform it into keyed query parameters.
  15. if (isset($parts [1])) {
  16. $query_parts = explode('#', $parts [1]);
  17. parse_str($query_parts [0], $options ['query']);
  18. // Take over the fragment, if there is any.
  19. if (isset($query_parts [1])) {
  20. $options ['fragment'] = $query_parts [1];
  21. }
  22. }
  23. }
  24. // Internal URLs.
  25. else {
  26. // parse_url() does not support relative URLs, so make it absolute. E.g. the
  27. // relative URL "foo/bar:1" isn't properly parsed.
  28. $parts = parse_url('http://example.com/' . $url);
  29. // Strip the leading slash that was just added.
  30. $options ['path'] = substr($parts ['path'], 1);
  31. if (isset($parts ['query'])) {
  32. parse_str($parts ['query'], $options ['query']);
  33. }
  34. if (isset($parts ['fragment'])) {
  35. $options ['fragment'] = $parts ['fragment'];
  36. }
  37. }
  38. // The 'q' parameter contains the path of the current page if clean URLs are
  39. // disabled. It overrides the 'path' of the URL when present, even if clean
  40. // URLs are enabled, due to how Apache rewriting rules work.
  41. if (isset($options ['query']['q'])) {
  42. $options ['path'] = $options ['query']['q'];
  43. unset($options ['query']['q']);
  44. }
  45.  
  46. return $options;
  47. }

function drupal_http_request

7 common.inc drupal_http_request($url, array $options = array())
4.6 common.inc drupal_http_request($url, $headers = array(), $method = 'GET', $data = NULL, $retry = 3)
4.7 common.inc drupal_http_request($url, $headers = array(), $method = 'GET', $data = NULL, $retry = 3)
5 common.inc drupal_http_request($url, $headers = array(), $method = 'GET', $data = NULL, $retry = 3)
6 common.inc drupal_http_request($url, $headers = array(), $method = 'GET', $data = NULL, $retry = 3, $timeout = 30.0)
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.

Parameters

$url: A string containing a fully qualified URI.

array $options: (optional) An array that can have one or more of the following elements:

headers: An array containing request headers to send as name/value pairs.
method: A string containing the request method. Defaults to 'GET'.
data: A string containing the request body, formatted as 'param=value&param=value&...'. Defaults to NULL.
max_redirects: An integer representing how many times a redirect may be followed. Defaults to 3.
timeout: A float representing the maximum number of seconds the function call may take. The default is 30 seconds. If a timeout occurs, the error code is set to the HTTP_REQUEST_TIMEOUT constant.
context: A context resource created with stream_context_create().
Return value

object An object that can have one or more of the following components:

request: A string containing the request body that was sent.
code: An integer containing the response status code, or the error code if an error occurred.
protocol: The response protocol (e.g. HTTP/1.1 or HTTP/1.0).
status_message: The status message from the response, if a response was received.
redirect_code: If redirected, an integer containing the initial response status code.
redirect_url: If redirected, a string containing the URL of the redirect target.
error: If an error occurred, the error message. Otherwise not set.
headers: An array containing the response headers as name/value pairs. HTTP header names are case-insensitive (RFC 2616, section 4.2), so for easy access the array keys are returned in lower case.
data: A string containing the response body that was received.
Related topics

HTTP handling
Functions to properly handle HTTP responses.
16 calls to drupal_http_request()
File

includes/common.inc, line 782
Common functions that many Drupal modules will need to reference.

</> CopyGet raw version
php
  1. function drupal_http_request($url, array $options = array()) {
  2. // Allow an alternate HTTP client library to replace Drupal's default
  3. // implementation.
  4. $override_function = variable_get('drupal_http_request_function', FALSE);
  5. if (!empty($override_function) && function_exists($override_function)) {
  6. return $override_function($url, $options);
  7. }
  8.  
  9. $result = new stdClass();
  10.  
  11. // Parse the URL and make sure we can handle the schema.
  12. $uri = @parse_url($url);
  13.  
  14. if ($uri == FALSE) {
  15. $result->error = 'unable to parse URL';
  16. $result->code = -1001;
  17. return $result;
  18. }
  19.  
  20. if (!isset($uri ['scheme'])) {
  21. $result->error = 'missing schema';
  22. $result->code = -1002;
  23. return $result;
  24. }
  25.  
  26. timer_start(__FUNCTION__);
  27.  
  28. // Merge the default options.
  29. $options += array(
  30. 'headers' => array(),
  31. 'method' => 'GET',
  32. 'data' => NULL,
  33. 'max_redirects' => 3,
  34. 'timeout' => 30.0,
  35. 'context' => NULL,
  36. );
  37.  
  38. // Merge the default headers.
  39. $options ['headers'] += array(
  40. 'User-Agent' => 'Drupal (+http://drupal.org/)',
  41. );
  42.  
  43. // stream_socket_client() requires timeout to be a float.
  44. $options ['timeout'] = (float) $options ['timeout'];
  45.  
  46. // Use a proxy if one is defined and the host is not on the excluded list.
  47. $proxy_server = variable_get('proxy_server', '');
  48. if ($proxy_server && _drupal_http_use_proxy($uri ['host'])) {
  49. // Set the scheme so we open a socket to the proxy server.
  50. $uri ['scheme'] = 'proxy';
  51. // Set the path to be the full URL.
  52. $uri ['path'] = $url;
  53. // Since the URL is passed as the path, we won't use the parsed query.
  54. unset($uri ['query']);
  55.  
  56. // Add in username and password to Proxy-Authorization header if needed.
  57. if ($proxy_username = variable_get('proxy_username', '')) {
  58. $proxy_password = variable_get('proxy_password', '');
  59. $options ['headers']['Proxy-Authorization'] = 'Basic ' . base64_encode($proxy_username . (!empty($proxy_password) ? ":" . $proxy_password : ''));
  60. }
  61. // Some proxies reject requests with any User-Agent headers, while others
  62. // require a specific one.
  63. $proxy_user_agent = variable_get('proxy_user_agent', '');
  64. // The default value matches neither condition.
  65. if ($proxy_user_agent === NULL) {
  66. unset($options ['headers']['User-Agent']);
  67. }
  68. elseif ($proxy_user_agent) {
  69. $options ['headers']['User-Agent'] = $proxy_user_agent;
  70. }
  71. }
  72.  
  73. switch ($uri ['scheme']) {
  74. case 'proxy':
  75. // Make the socket connection to a proxy server.
  76. $socket = 'tcp://' . $proxy_server . ':' . variable_get('proxy_port', 8080);
  77. // The Host header still needs to match the real request.
  78. $options ['headers']['Host'] = $uri ['host'];
  79. $options ['headers']['Host'] .= isset($uri ['port']) && $uri ['port'] != 80 ? ':' . $uri ['port'] : '';
  80. break;
  81.  
  82. case 'http':
  83. case 'feed':
  84. $port = isset($uri ['port']) ? $uri ['port'] : 80;
  85. $socket = 'tcp://' . $uri ['host'] . ':' . $port;
  86. // RFC 2616: "non-standard ports MUST, default ports MAY be included".
  87. // We don't add the standard port to prevent from breaking rewrite rules
  88. // checking the host that do not take into account the port number.
  89. $options ['headers']['Host'] = $uri ['host'] . ($port != 80 ? ':' . $port : '');
  90. break;
  91.  
  92. case 'https':
  93. // Note: Only works when PHP is compiled with OpenSSL support.
  94. $port = isset($uri ['port']) ? $uri ['port'] : 443;
  95. $socket = 'ssl://' . $uri ['host'] . ':' . $port;
  96. $options ['headers']['Host'] = $uri ['host'] . ($port != 443 ? ':' . $port : '');
  97. break;
  98.  
  99. default:
  100. $result->error = 'invalid schema ' . $uri ['scheme'];
  101. $result->code = -1003;
  102. return $result;
  103. }
  104.  
  105. if (empty($options ['context'])) {
  106. $fp = @stream_socket_client($socket, $errno, $errstr, $options ['timeout']);
  107. }
  108. else {
  109. // Create a stream with context. Allows verification of a SSL certificate.
  110. $fp = @stream_socket_client($socket, $errno, $errstr, $options ['timeout'], STREAM_CLIENT_CONNECT, $options ['context']);
  111. }
  112.  
  113. // Make sure the socket opened properly.
  114. if (!$fp) {
  115. // When a network error occurs, we use a negative number so it does not
  116. // clash with the HTTP status codes.
  117. $result->code = -$errno;
  118. $result->error = trim($errstr) ? trim($errstr) : t('Error opening socket @socket', array('@socket' => $socket));
  119.  
  120. // Mark that this request failed. This will trigger a check of the web
  121. // server's ability to make outgoing HTTP requests the next time that
  122. // requirements checking is performed.
  123. // See system_requirements().
  124. variable_set('drupal_http_request_fails', TRUE);
  125.  
  126. return $result;
  127. }
  128.  
  129. // Construct the path to act on.
  130. $path = isset($uri ['path']) ? $uri ['path'] : '/';
  131. if (isset($uri ['query'])) {
  132. $path .= '?' . $uri ['query'];
  133. }
  134.  
  135. // Only add Content-Length if we actually have any content or if it is a POST
  136. // or PUT request. Some non-standard servers get confused by Content-Length in
  137. // at least HEAD/GET requests, and Squid always requires Content-Length in
  138. // POST/PUT requests.
  139. $content_length = strlen($options ['data']);
  140. if ($content_length > 0 || $options ['method'] == 'POST' || $options ['method'] == 'PUT') {
  141. $options ['headers']['Content-Length'] = $content_length;
  142. }
  143.  
  144. // If the server URL has a user then attempt to use basic authentication.
  145. if (isset($uri ['user'])) {
  146. $options ['headers']['Authorization'] = 'Basic ' . base64_encode($uri ['user'] . (isset($uri ['pass']) ? ':' . $uri ['pass'] : ':'));
  147. }
  148.  
  149. // If the database prefix is being used by SimpleTest to run the tests in a copied
  150. // database then set the user-agent header to the database prefix so that any
  151. // calls to other Drupal pages will run the SimpleTest prefixed database. The
  152. // user-agent is used to ensure that multiple testing sessions running at the
  153. // same time won't interfere with each other as they would if the database
  154. // prefix were stored statically in a file or database variable.
  155. $test_info = &$GLOBALS ['drupal_test_info'];
  156. if (!empty($test_info ['test_run_id'])) {
  157. $options ['headers']['User-Agent'] = drupal_generate_test_ua($test_info ['test_run_id']);
  158. }
  159.  
  160. $request = $options ['method'] . ' ' . $path . " HTTP/1.0\r\n";
  161. foreach ($options ['headers'] as $name => $value) {
  162. $request .= $name . ': ' . trim($value) . "\r\n";
  163. }
  164. $request .= "\r\n" . $options ['data'];
  165. $result->request = $request;
  166. // Calculate how much time is left of the original timeout value.
  167. $timeout = $options ['timeout'] - timer_read(__FUNCTION__) / 1000;
  168. if ($timeout > 0) {
  169. stream_set_timeout($fp, floor($timeout), floor(1000000 * fmod($timeout, 1)));
  170. fwrite($fp, $request);
  171. }
  172.  
  173. // Fetch response. Due to PHP bugs like http://bugs.php.net/bug.php?id=43782
  174. // and http://bugs.php.net/bug.php?id=46049 we can't rely on feof(), but
  175. // instead must invoke stream_get_meta_data() each iteration.
  176. $info = stream_get_meta_data($fp);
  177. $alive = !$info ['eof'] && !$info ['timed_out'];
  178. $response = '';
  179.  
  180. while ($alive) {
  181. // Calculate how much time is left of the original timeout value.
  182. $timeout = $options ['timeout'] - timer_read(__FUNCTION__) / 1000;
  183. if ($timeout <= 0) {
  184. $info ['timed_out'] = TRUE;
  185. break;
  186. }
  187. stream_set_timeout($fp, floor($timeout), floor(1000000 * fmod($timeout, 1)));
  188. $chunk = fread($fp, 1024);
  189. $response .= $chunk;
  190. $info = stream_get_meta_data($fp);
  191. $alive = !$info ['eof'] && !$info ['timed_out'] && $chunk;
  192. }
  193. fclose($fp);
  194.  
  195. if ($info ['timed_out']) {
  196. $result->code = HTTP_REQUEST_TIMEOUT;
  197. $result->error = 'request timed out';
  198. return $result;
  199. }
  200. // Parse response headers from the response body.
  201. // Be tolerant of malformed HTTP responses that separate header and body with
  202. // \n\n or \r\r instead of \r\n\r\n.
  203. list($response, $result->data) = preg_split("/\r\n\r\n|\n\n|\r\r/", $response, 2);
  204. $response = preg_split("/\r\n|\n|\r/", $response);
  205.  
  206. // Parse the response status line.
  207. $response_status_array = _drupal_parse_response_status(trim(array_shift($response)));
  208. $result->protocol = $response_status_array ['http_version'];
  209. $result->status_message = $response_status_array ['reason_phrase'];
  210. $code = $response_status_array ['response_code'];
  211.  
  212. $result->headers = array();
  213.  
  214. // Parse the response headers.
  215. while ($line = trim(array_shift($response))) {
  216. list($name, $value) = explode(':', $line, 2);
  217. $name = strtolower($name);
  218. if (isset($result->headers [$name]) && $name == 'set-cookie') {
  219. // RFC 2109: the Set-Cookie response header comprises the token Set-
  220. // Cookie:, followed by a comma-separated list of one or more cookies.
  221. $result->headers [$name] .= ',' . trim($value);
  222. }
  223. else {
  224. $result->headers [$name] = trim($value);
  225. }
  226. }
  227.  
  228. $responses = array(
  229. 100 => 'Continue',
  230. 101 => 'Switching Protocols',
  231. 200 => 'OK',
  232. 201 => 'Created',
  233. 202 => 'Accepted',
  234. 203 => 'Non-Authoritative Information',
  235. 204 => 'No Content',
  236. 205 => 'Reset Content',
  237. 206 => 'Partial Content',
  238. 300 => 'Multiple Choices',
  239. 301 => 'Moved Permanently',
  240. 302 => 'Found',
  241. 303 => 'See Other',
  242. 304 => 'Not Modified',
  243. 305 => 'Use Proxy',
  244. 307 => 'Temporary Redirect',
  245. 400 => 'Bad Request',
  246. 401 => 'Unauthorized',
  247. 402 => 'Payment Required',
  248. 403 => 'Forbidden',
  249. 404 => 'Not Found',
  250. 405 => 'Method Not Allowed',
  251. 406 => 'Not Acceptable',
  252. 407 => 'Proxy Authentication Required',
  253. 408 => 'Request Time-out',
  254. 409 => 'Conflict',
  255. 410 => 'Gone',
  256. 411 => 'Length Required',
  257. 412 => 'Precondition Failed',
  258. 413 => 'Request Entity Too Large',
  259. 414 => 'Request-URI Too Large',
  260. 415 => 'Unsupported Media Type',
  261. 416 => 'Requested range not satisfiable',
  262. 417 => 'Expectation Failed',
  263. 500 => 'Internal Server Error',
  264. 501 => 'Not Implemented',
  265. 502 => 'Bad Gateway',
  266. 503 => 'Service Unavailable',
  267. 504 => 'Gateway Time-out',
  268. 505 => 'HTTP Version not supported',
  269. );
  270. // RFC 2616 states that all unknown HTTP codes must be treated the same as the
  271. // base code in their class.
  272. if (!isset($responses [$code])) {
  273. $code = floor($code / 100) * 100;
  274. }
  275. $result->code = $code;
  276.  
  277. switch ($code) {
  278. case 200: // OK
  279. case 304: // Not modified
  280. break;
  281. case 301: // Moved permanently
  282. case 302: // Moved temporarily
  283. case 307: // Moved temporarily
  284. $location = $result->headers ['location'];
  285. $options ['timeout'] -= timer_read(__FUNCTION__) / 1000;
  286. if ($options ['timeout'] <= 0) {
  287. $result->code = HTTP_REQUEST_TIMEOUT;
  288. $result->error = 'request timed out';
  289. }
  290. elseif ($options ['max_redirects']) {
  291. // Redirect to the new location.
  292. $options ['max_redirects'];
  293. --$result = drupal_http_request($location, $options);
  294. $result->redirect_code = $code;
  295. }
  296. if (!isset($result->redirect_url)) {
  297. $result->redirect_url = $location;
  298. }
  299. break;
  300. default:
  301. $result->error = $result->status_message;
  302. }
  303.  
  304. return $result;
  305. }

Example of a POST, GET

</> CopyGet raw version
php
  1. $data = 'name=value&name1=value1';
  2. $options = array(
  3. 'method' => 'POST',
  4. 'data' => $data,
  5. 'timeout' => 15,
  6. 'headers' => array('Content-Type' => 'application/x-www-form-urlencoded'),
  7. );
  8.  
  9.  
  10. $result = drupal_http_request('http://somewhere.com', $options);
  11.  
  12. /////////////////////////////////////////////////////////////////
  13.  
  14. $url = 'http://example.com';
  15. $data = array(
  16. 'key1' => $value1,
  17. 'key2' => $value2,
  18. );
  19.  
  20. $full_url = url($url, array('query' => $data));
  21. drupal_http_request($full_url);

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

</> CopyGet raw version
php
  1. global $user;
  2. $long_url = 'http://SOME PROTECTED DRUPAL URL YOU ARE TRYING TO MAKE A drupal_http_request to on your site ';
  3.  
  4. $session_name = ini_get('session.name');
  5. $headers = array('headers' => array('Cookie' => $session_name.'='.$user->sid));
  6. $request = drupal_http_request( $long_url , $headers);
  7. dsm($request);