You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

124 lines
4.1 KiB

7 years ago
  1. <?php
  2. namespace p3k\HTTP;
  3. class Curl implements Transport {
  4. protected $_timeout = 4;
  5. protected $_max_redirects = 8;
  6. static protected $_http_version = null;
  7. public function set_max_redirects($max) {
  8. $this->_max_redirects = $max;
  9. }
  10. public function set_timeout($timeout) {
  11. $this->_timeout = $timeout;
  12. }
  13. public function get($url, $headers=[]) {
  14. $ch = curl_init($url);
  15. $this->_set_curlopts($ch, $url);
  16. if($headers)
  17. curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
  18. $response = curl_exec($ch);
  19. $header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
  20. $header_str = trim(substr($response, 0, $header_size));
  21. return [
  22. 'code' => curl_getinfo($ch, CURLINFO_HTTP_CODE),
  23. 'header' => $header_str,
  24. 'body' => substr($response, $header_size),
  25. 'error' => self::error_string_from_code(curl_errno($ch)),
  26. 'error_description' => curl_error($ch),
  27. 'url' => curl_getinfo($ch, CURLINFO_EFFECTIVE_URL),
  28. 'debug' => $response
  29. ];
  30. }
  31. public function post($url, $body, $headers=[]) {
  32. $ch = curl_init($url);
  33. $this->_set_curlopts($ch, $url);
  34. curl_setopt($ch, CURLOPT_POST, true);
  35. curl_setopt($ch, CURLOPT_POSTFIELDS, $body);
  36. if($headers)
  37. curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
  38. $response = curl_exec($ch);
  39. $header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
  40. $header_str = trim(substr($response, 0, $header_size));
  41. return [
  42. 'code' => curl_getinfo($ch, CURLINFO_HTTP_CODE),
  43. 'header' => $header_str,
  44. 'body' => substr($response, $header_size),
  45. 'error' => self::error_string_from_code(curl_errno($ch)),
  46. 'error_description' => curl_error($ch),
  47. 'url' => curl_getinfo($ch, CURLINFO_EFFECTIVE_URL),
  48. 'debug' => $response
  49. ];
  50. }
  51. public function head($url, $headers=[]) {
  52. $ch = curl_init($url);
  53. $this->_set_curlopts($ch, $url);
  54. if($headers)
  55. curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
  56. curl_setopt($ch, CURLOPT_NOBODY, true);
  57. $response = curl_exec($ch);
  58. return [
  59. 'code' => curl_getinfo($ch, CURLINFO_HTTP_CODE),
  60. 'header' => trim($response),
  61. 'error' => self::error_string_from_code(curl_errno($ch)),
  62. 'error_description' => curl_error($ch),
  63. 'url' => curl_getinfo($ch, CURLINFO_EFFECTIVE_URL),
  64. 'debug' => $response
  65. ];
  66. }
  67. private function _set_curlopts($ch, $url) {
  68. curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
  69. curl_setopt($ch, CURLOPT_HEADER, true);
  70. if($this->_max_redirects > 0)
  71. curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
  72. curl_setopt($ch, CURLOPT_POSTREDIR, 7); // don't change POST to GET on HTTP 301/302/303 redirects
  73. curl_setopt($ch, CURLOPT_MAXREDIRS, $this->_max_redirects);
  74. curl_setopt($ch, CURLOPT_TIMEOUT_MS, round($this->_timeout * 1000));
  75. curl_setopt($ch, CURLOPT_CONNECTTIMEOUT_MS, 2000);
  76. curl_setopt($ch, CURLOPT_HTTP_VERSION, $this->_http_version());
  77. }
  78. private function _http_version() {
  79. if (static::$_http_version !== null)
  80. return static::$_http_version;
  81. if (defined('CURL_HTTP_VERSION_2')) { // PHP 7.0.7
  82. static::$_http_version = CURL_HTTP_VERSION_2;
  83. } else if (defined('CURL_HTTP_VERSION_2_0')) { // Recommended in online articles
  84. static::$_http_version = CURL_HTTP_VERSION_2_0;
  85. } else { // Linked curl might be newer than PHP, send (current) INT value anyway.
  86. static::$_http_version = 3;
  87. }
  88. return static::$_http_version;
  89. }
  90. public static function error_string_from_code($code) {
  91. switch($code) {
  92. case 0:
  93. return '';
  94. case CURLE_COULDNT_RESOLVE_HOST:
  95. return 'dns_error';
  96. case CURLE_COULDNT_CONNECT:
  97. return 'connect_error';
  98. case CURLE_OPERATION_TIMEDOUT:
  99. return 'timeout';
  100. case CURLE_SSL_CONNECT_ERROR:
  101. return 'ssl_error';
  102. case CURLE_SSL_CERTPROBLEM:
  103. return 'ssl_cert_error';
  104. case CURLE_SSL_CIPHER:
  105. return 'ssl_unsupported_cipher';
  106. case CURLE_SSL_CACERT:
  107. return 'ssl_cert_error';
  108. case CURLE_TOO_MANY_REDIRECTS:
  109. return 'too_many_redirects';
  110. default:
  111. return 'unknown';
  112. }
  113. }
  114. }