[ Index ] |
PHP Cross Reference of Phabricator |
[Summary view] [Print] [Text view]
1 <?php 2 3 namespace Httpful; 4 5 use Httpful\Exception\ConnectionErrorException; 6 7 /** 8 * Clean, simple class for sending HTTP requests 9 * in PHP. 10 * 11 * There is an emphasis of readability without loosing concise 12 * syntax. As such, you will notice that the library lends 13 * itself very nicely to "chaining". You will see several "alias" 14 * methods: more readable method definitions that wrap 15 * their more concise counterparts. You will also notice 16 * no public constructor. This two adds to the readability 17 * and "chainabilty" of the library. 18 * 19 * @author Nate Good <[email protected]> 20 */ 21 class Request 22 { 23 24 // Option constants 25 const SERIALIZE_PAYLOAD_NEVER = 0; 26 const SERIALIZE_PAYLOAD_ALWAYS = 1; 27 const SERIALIZE_PAYLOAD_SMART = 2; 28 29 const MAX_REDIRECTS_DEFAULT = 25; 30 31 public $uri, 32 $method = Http::GET, 33 $headers = array(), 34 $raw_headers = '', 35 $strict_ssl = false, 36 $content_type, 37 $expected_type, 38 $additional_curl_opts = array(), 39 $auto_parse = true, 40 $serialize_payload_method = self::SERIALIZE_PAYLOAD_SMART, 41 $username, 42 $password, 43 $serialized_payload, 44 $payload, 45 $parse_callback, 46 $error_callback, 47 $follow_redirects = false, 48 $max_redirects = self::MAX_REDIRECTS_DEFAULT, 49 $payload_serializers = array(); 50 51 // Options 52 // private $_options = array( 53 // 'serialize_payload_method' => self::SERIALIZE_PAYLOAD_SMART 54 // 'auto_parse' => true 55 // ); 56 57 // Curl Handle 58 public $_ch, 59 $_debug; 60 61 // Template Request object 62 private static $_template; 63 64 /** 65 * We made the constructor private to force the factory style. This was 66 * done to keep the syntax cleaner and better the support the idea of 67 * "default templates". Very basic and flexible as it is only intended 68 * for internal use. 69 * @param array $attrs hash of initial attribute values 70 */ 71 private function __construct($attrs = null) 72 { 73 if (!is_array($attrs)) return; 74 foreach ($attrs as $attr => $value) { 75 $this->$attr = $value; 76 } 77 } 78 79 // Defaults Management 80 81 /** 82 * Let's you configure default settings for this 83 * class from a template Request object. Simply construct a 84 * Request object as much as you want to and then pass it to 85 * this method. It will then lock in those settings from 86 * that template object. 87 * The most common of which may be default mime 88 * settings or strict ssl settings. 89 * Again some slight memory overhead incurred here but in the grand 90 * scheme of things as it typically only occurs once 91 * @param Request $template 92 */ 93 public static function ini(Request $template) 94 { 95 self::$_template = clone $template; 96 } 97 98 /** 99 * Reset the default template back to the 100 * library defaults. 101 */ 102 public static function resetIni() 103 { 104 self::_initializeDefaults(); 105 } 106 107 /** 108 * Get default for a value based on the template object 109 * @return mixed default value 110 * @param string|null $attr Name of attribute (e.g. mime, headers) 111 * if null just return the whole template object; 112 */ 113 public static function d($attr) 114 { 115 return isset($attr) ? self::$_template->$attr : self::$_template; 116 } 117 118 // Accessors 119 120 /** 121 * @return bool does the request have a timeout? 122 */ 123 public function hasTimeout() 124 { 125 return isset($this->timeout); 126 } 127 128 /** 129 * @return bool has the internal curl request been initialized? 130 */ 131 public function hasBeenInitialized() 132 { 133 return isset($this->_ch); 134 } 135 136 /** 137 * @return bool Is this request setup for basic auth? 138 */ 139 public function hasBasicAuth() 140 { 141 return isset($this->password) && isset($this->username); 142 } 143 144 /** 145 * @return bool Is this request setup for digest auth? 146 */ 147 public function hasDigestAuth() 148 { 149 return isset($this->password) && isset($this->username) && $this->additional_curl_opts['CURLOPT_HTTPAUTH'] = CURLAUTH_DIGEST; 150 } 151 152 /** 153 * Specify a HTTP timeout 154 * @return Request $this 155 * @param |int $timeout seconds to timeout the HTTP call 156 */ 157 public function timeout($timeout) 158 { 159 $this->timeout = $timeout; 160 return $this; 161 } 162 163 /** 164 * If the response is a 301 or 302 redirect, automatically 165 * send off another request to that location 166 * @return Request $this 167 * @param bool|int $follow follow or not to follow or maximal number of redirects 168 */ 169 public function followRedirects($follow = true) 170 { 171 $this->max_redirects = $follow === true ? self::MAX_REDIRECTS_DEFAULT : max(0, $follow); 172 $this->follow_redirects = (bool) $follow; 173 return $this; 174 } 175 176 /** 177 * @return Request $this 178 * @see Request::followRedirects() 179 */ 180 public function doNotFollowRedirects() 181 { 182 return $this->followRedirects(false); 183 } 184 185 /** 186 * Actually send off the request, and parse the response 187 * @return string|associative array of parsed results 188 * @throws ConnectionErrorException when unable to parse or communicate w server 189 */ 190 public function send() 191 { 192 if (!$this->hasBeenInitialized()) 193 $this->_curlPrep(); 194 195 $result = curl_exec($this->_ch); 196 197 if ($result === false) { 198 $this->_error(curl_error($this->_ch)); 199 throw new ConnectionErrorException('Unable to connect.'); 200 } 201 202 $info = curl_getinfo($this->_ch); 203 $response = explode("\r\n\r\n", $result, 2 + $info['redirect_count']); 204 205 $body = array_pop($response); 206 $headers = array_pop($response); 207 208 return new Response($body, $headers, $this); 209 } 210 public function sendIt() 211 { 212 return $this->send(); 213 } 214 215 // Setters 216 217 /** 218 * @return Request this 219 * @param string $uri 220 */ 221 public function uri($uri) 222 { 223 $this->uri = $uri; 224 return $this; 225 } 226 227 /** 228 * User Basic Auth. 229 * Only use when over SSL/TSL/HTTPS. 230 * @return Request this 231 * @param string $username 232 * @param string $password 233 */ 234 public function basicAuth($username, $password) 235 { 236 $this->username = $username; 237 $this->password = $password; 238 return $this; 239 } 240 // @alias of basicAuth 241 public function authenticateWith($username, $password) 242 { 243 return $this->basicAuth($username, $password); 244 } 245 // @alias of basicAuth 246 public function authenticateWithBasic($username, $password) 247 { 248 return $this->basicAuth($username, $password); 249 } 250 251 /** 252 * User Digest Auth. 253 * @return Request this 254 * @param string $username 255 * @param string $password 256 */ 257 public function digestAuth($username, $password) 258 { 259 $this->addOnCurlOption(CURLOPT_HTTPAUTH, CURLAUTH_DIGEST); 260 return $this->basicAuth($username, $password); 261 } 262 263 // @alias of digestAuth 264 public function authenticateWithDigest($username, $password) 265 { 266 return $this->digestAuth($username, $password); 267 } 268 269 /** 270 * @return is this request setup for client side cert? 271 */ 272 public function hasClientSideCert() { 273 return isset($this->client_cert) && isset($this->client_key); 274 } 275 276 /** 277 * Use Client Side Cert Authentication 278 * @return Response $this 279 * @param string $key file path to client key 280 * @param string $cert file path to client cert 281 * @param string $passphrase for client key 282 * @param string $encoding default PEM 283 */ 284 public function clientSideCert($cert, $key, $passphrase = null, $encoding = 'PEM') 285 { 286 $this->client_cert = $cert; 287 $this->client_key = $key; 288 $this->client_passphrase = $passphrase; 289 $this->client_encoding = $encoding; 290 291 return $this; 292 } 293 // @alias of basicAuth 294 public function authenticateWithCert($cert, $key, $passphrase = null, $encoding = 'PEM') 295 { 296 return $this->clientSideCert($cert, $key, $passphrase, $encoding); 297 } 298 299 /** 300 * Set the body of the request 301 * @return Request this 302 * @param mixed $payload 303 * @param string $mimeType 304 */ 305 public function body($payload, $mimeType = null) 306 { 307 $this->mime($mimeType); 308 $this->payload = $payload; 309 // Iserntentially don't call _serializePayload yet. Wait until 310 // we actually send off the request to convert payload to string. 311 // At that time, the `serialized_payload` is set accordingly. 312 return $this; 313 } 314 315 /** 316 * Helper function to set the Content type and Expected as same in 317 * one swoop 318 * @return Request this 319 * @param string $mime mime type to use for content type and expected return type 320 */ 321 public function mime($mime) 322 { 323 if (empty($mime)) return $this; 324 $this->content_type = $this->expected_type = Mime::getFullMime($mime); 325 return $this; 326 } 327 // @alias of mime 328 public function sendsAndExpectsType($mime) 329 { 330 return $this->mime($mime); 331 } 332 // @alias of mime 333 public function sendsAndExpects($mime) 334 { 335 return $this->mime($mime); 336 } 337 338 /** 339 * Set the method. Shouldn't be called often as the preferred syntax 340 * for instantiation is the method specific factory methods. 341 * @return Request this 342 * @param string $method 343 */ 344 public function method($method) 345 { 346 if (empty($method)) return $this; 347 $this->method = $method; 348 return $this; 349 } 350 351 /** 352 * @return Request this 353 * @param string $mime 354 */ 355 public function expects($mime) 356 { 357 if (empty($mime)) return $this; 358 $this->expected_type = Mime::getFullMime($mime); 359 return $this; 360 } 361 // @alias of expects 362 public function expectsType($mime) 363 { 364 return $this->expects($mime); 365 } 366 367 /** 368 * @return Request this 369 * @param string $mime 370 */ 371 public function contentType($mime) 372 { 373 if (empty($mime)) return $this; 374 $this->content_type = Mime::getFullMime($mime); 375 return $this; 376 } 377 // @alias of contentType 378 public function sends($mime) 379 { 380 return $this->contentType($mime); 381 } 382 // @alias of contentType 383 public function sendsType($mime) 384 { 385 return $this->contentType($mime); 386 } 387 388 /** 389 * Do we strictly enforce SSL verification? 390 * @return Request this 391 * @param bool $strict 392 */ 393 public function strictSSL($strict) 394 { 395 $this->strict_ssl = $strict; 396 return $this; 397 } 398 public function withoutStrictSSL() 399 { 400 return $this->strictSSL(false); 401 } 402 public function withStrictSSL() 403 { 404 return $this->strictSSL(true); 405 } 406 407 /** 408 * Determine how/if we use the built in serialization by 409 * setting the serialize_payload_method 410 * The default (SERIALIZE_PAYLOAD_SMART) is... 411 * - if payload is not a scalar (object/array) 412 * use the appropriate serialize method according to 413 * the Content-Type of this request. 414 * - if the payload IS a scalar (int, float, string, bool) 415 * than just return it as is. 416 * When this option is set SERIALIZE_PAYLOAD_ALWAYS, 417 * it will always use the appropriate 418 * serialize option regardless of whether payload is scalar or not 419 * When this option is set SERIALIZE_PAYLOAD_NEVER, 420 * it will never use any of the serialization methods. 421 * Really the only use for this is if you want the serialize methods 422 * to handle strings or not (e.g. Blah is not valid JSON, but "Blah" 423 * is). Forcing the serialization helps prevent that kind of error from 424 * happening. 425 * @return Request $this 426 * @param int $mode 427 */ 428 public function serializePayload($mode) 429 { 430 $this->serialize_payload_method = $mode; 431 return $this; 432 } 433 434 /** 435 * @see Request::serializePayload() 436 * @return Request 437 */ 438 public function neverSerializePayload() 439 { 440 return $this->serializePayload(self::SERIALIZE_PAYLOAD_NEVER); 441 } 442 443 /** 444 * This method is the default behavior 445 * @see Request::serializePayload() 446 * @return Request 447 */ 448 public function smartSerializePayload() 449 { 450 return $this->serializePayload(self::SERIALIZE_PAYLOAD_SMART); 451 } 452 453 /** 454 * @see Request::serializePayload() 455 * @return Request 456 */ 457 public function alwaysSerializePayload() 458 { 459 return $this->serializePayload(self::SERIALIZE_PAYLOAD_ALWAYS); 460 } 461 462 /** 463 * Add an additional header to the request 464 * Can also use the cleaner syntax of 465 * $Request->withMyHeaderName($my_value); 466 * @see Request::__call() 467 * 468 * @return Request this 469 * @param string $header_name 470 * @param string $value 471 */ 472 public function addHeader($header_name, $value) 473 { 474 $this->headers[$header_name] = $value; 475 return $this; 476 } 477 478 /** 479 * Add group of headers all at once. Note: This is 480 * here just as a convenience in very specific cases. 481 * The preferred "readable" way would be to leverage 482 * the support for custom header methods. 483 * @return Response $this 484 * @param array $headers 485 */ 486 public function addHeaders(array $headers) 487 { 488 foreach ($headers as $header => $value) { 489 $this->addHeader($header, $value); 490 } 491 return $this; 492 } 493 494 /** 495 * @return Request 496 * @param bool $auto_parse perform automatic "smart" 497 * parsing based on Content-Type or "expectedType" 498 * If not auto parsing, Response->body returns the body 499 * as a string. 500 */ 501 public function autoParse($auto_parse = true) 502 { 503 $this->auto_parse = $auto_parse; 504 return $this; 505 } 506 507 /** 508 * @see Request::autoParse() 509 * @return Request 510 */ 511 public function withoutAutoParsing() 512 { 513 return $this->autoParse(false); 514 } 515 516 /** 517 * @see Request::autoParse() 518 * @return Request 519 */ 520 public function withAutoParsing() 521 { 522 return $this->autoParse(true); 523 } 524 525 /** 526 * Use a custom function to parse the response. 527 * @return Request this 528 * @param \Closure $callback Takes the raw body of 529 * the http response and returns a mixed 530 */ 531 public function parseWith(\Closure $callback) 532 { 533 $this->parse_callback = $callback; 534 return $this; 535 } 536 537 /** 538 * @see Request::parseResponsesWith() 539 * @return Request $this 540 * @param \Closure $callback 541 */ 542 public function parseResponsesWith(\Closure $callback) 543 { 544 return $this->parseWith($callback); 545 } 546 547 /** 548 * Register a callback that will be used to serialize the payload 549 * for a particular mime type. When using "*" for the mime 550 * type, it will use that parser for all responses regardless of the mime 551 * type. If a custom '*' and 'application/json' exist, the custom 552 * 'application/json' would take precedence over the '*' callback. 553 * 554 * @return Request $this 555 * @param string $mime mime type we're registering 556 * @param Closure $callback takes one argument, $payload, 557 * which is the payload that we'll be 558 */ 559 public function registerPayloadSerializer($mime, \Closure $callback) 560 { 561 $this->payload_serializers[Mime::getFullMime($mime)] = $callback; 562 return $this; 563 } 564 565 /** 566 * @see Request::registerPayloadSerializer() 567 * @return Request $this 568 * @param Closure $callback 569 */ 570 public function serializePayloadWith(\Closure $callback) 571 { 572 return $this->regregisterPayloadSerializer('*', $callback); 573 } 574 575 /** 576 * Magic method allows for neatly setting other headers in a 577 * similar syntax as the other setters. This method also allows 578 * for the sends* syntax. 579 * @return Request this 580 * @param string $method "missing" method name called 581 * the method name called should be the name of the header that you 582 * are trying to set in camel case without dashes e.g. to set a 583 * header for Content-Type you would use contentType() or more commonly 584 * to add a custom header like X-My-Header, you would use xMyHeader(). 585 * To promote readability, you can optionally prefix these methods with 586 * "with" (e.g. withXMyHeader("blah") instead of xMyHeader("blah")). 587 * @param array $args in this case, there should only ever be 1 argument provided 588 * and that argument should be a string value of the header we're setting 589 */ 590 public function __call($method, $args) 591 { 592 // This method supports the sends* methods 593 // like sendsJSON, sendsForm 594 //!method_exists($this, $method) && 595 if (substr($method, 0, 5) === 'sends') { 596 $mime = strtolower(substr($method, 5)); 597 if (Mime::supportsMimeType($mime)) { 598 $this->sends(Mime::getFullMime($mime)); 599 return $this; 600 } 601 // else { 602 // throw new \Exception("Unsupported Content-Type $mime"); 603 // } 604 } 605 if (substr($method, 0, 7) === 'expects') { 606 $mime = strtolower(substr($method, 7)); 607 if (Mime::supportsMimeType($mime)) { 608 $this->expects(Mime::getFullMime($mime)); 609 return $this; 610 } 611 // else { 612 // throw new \Exception("Unsupported Content-Type $mime"); 613 // } 614 } 615 616 // This method also adds the custom header support as described in the 617 // method comments 618 if (count($args) === 0) 619 return; 620 621 // Strip the sugar. If it leads with "with", strip. 622 // This is okay because: No defined HTTP headers begin with with, 623 // and if you are defining a custom header, the standard is to prefix it 624 // with an "X-", so that should take care of any collisions. 625 if (substr($method, 0, 4) === 'with') 626 $method = substr($method, 4); 627 628 // Precede upper case letters with dashes, uppercase the first letter of method 629 $header = ucwords(implode('-', preg_split('/([A-Z][^A-Z]*)/', $method, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY))); 630 $this->addHeader($header, $args[0]); 631 return $this; 632 } 633 634 // Internal Functions 635 636 /** 637 * This is the default template to use if no 638 * template has been provided. The template 639 * tells the class which default values to use. 640 * While there is a slight overhead for object 641 * creation once per execution (not once per 642 * Request instantiation), it promotes readability 643 * and flexibility within the class. 644 */ 645 private static function _initializeDefaults() 646 { 647 // This is the only place you will 648 // see this constructor syntax. It 649 // is only done here to prevent infinite 650 // recusion. Do not use this syntax elsewhere. 651 // It goes against the whole readability 652 // and transparency idea. 653 self::$_template = new Request(array('method' => Http::GET)); 654 655 // This is more like it... 656 self::$_template 657 ->withoutStrictSSL(); 658 } 659 660 /** 661 * Set the defaults on a newly instantiated object 662 * Doesn't copy variables prefixed with _ 663 * @return Request this 664 */ 665 private function _setDefaults() 666 { 667 if (!isset(self::$_template)) 668 self::_initializeDefaults(); 669 foreach (self::$_template as $k=>$v) { 670 if ($k[0] != '_') 671 $this->$k = $v; 672 } 673 return $this; 674 } 675 676 private function _error($error) 677 { 678 // Default actions write to error log 679 // TODO add in support for various Loggers 680 error_log($error); 681 } 682 683 /** 684 * Factory style constructor works nicer for chaining. This 685 * should also really only be used internally. The Request::get, 686 * Request::post syntax is preferred as it is more readable. 687 * @return Request 688 * @param string $method Http Method 689 * @param string $mime Mime Type to Use 690 */ 691 public static function init($method = null, $mime = null) 692 { 693 // Setup our handlers, can call it here as it's idempotent 694 Bootstrap::init(); 695 696 // Setup the default template if need be 697 if (!isset(self::$_template)) 698 self::_initializeDefaults(); 699 700 $request = new Request(); 701 return $request 702 ->_setDefaults() 703 ->method($method) 704 ->sendsType($mime) 705 ->expectsType($mime); 706 } 707 708 /** 709 * Does the heavy lifting. Uses de facto HTTP 710 * library cURL to set up the HTTP request. 711 * Note: It does NOT actually send the request 712 * @return Request $this; 713 */ 714 public function _curlPrep() 715 { 716 // Check for required stuff 717 if (!isset($this->uri)) 718 throw new \Exception('Attempting to send a request before defining a URI endpoint.'); 719 720 $ch = curl_init($this->uri); 721 722 curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $this->method); 723 724 if ($this->hasBasicAuth()) { 725 curl_setopt($ch, CURLOPT_USERPWD, $this->username . ':' . $this->password); 726 } 727 728 if ($this->hasClientSideCert()) { 729 730 if (!file_exists($this->client_key)) 731 throw new \Exception('Could not read Client Key'); 732 733 if (!file_exists($this->client_cert)) 734 throw new \Exception('Could not read Client Certificate'); 735 736 curl_setopt($ch, CURLOPT_SSLCERTTYPE, $this->client_encoding); 737 curl_setopt($ch, CURLOPT_SSLKEYTYPE, $this->client_encoding); 738 curl_setopt($ch, CURLOPT_SSLCERT, $this->client_cert); 739 curl_setopt($ch, CURLOPT_SSLKEY, $this->client_key); 740 curl_setopt($ch, CURLOPT_SSLKEYPASSWD, $this->client_passphrase); 741 // curl_setopt($ch, CURLOPT_SSLCERTPASSWD, $this->client_cert_passphrase); 742 } 743 744 if ($this->hasTimeout()) { 745 curl_setopt($ch, CURLOPT_TIMEOUT, $this->timeout); 746 } 747 748 if ($this->follow_redirects) { 749 curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); 750 curl_setopt($ch, CURLOPT_MAXREDIRS, $this->max_redirects); 751 } 752 753 curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, $this->strict_ssl); 754 curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); 755 756 $headers = array(); 757 // https://github.com/nategood/httpful/issues/37 758 // Except header removes any HTTP 1.1 Continue from response headers 759 $headers[] = 'Expect:'; 760 761 if (!isset($this->headers['User-Agent'])) { 762 $headers[] = $this->buildUserAgent(); 763 } 764 765 $headers[] = "Content-Type: {$this->content_type}"; 766 767 // allow custom Accept header if set 768 if (!isset($this->headers['Accept'])) { 769 // http://pretty-rfc.herokuapp.com/RFC2616#header.accept 770 $accept = 'Accept: */*; q=0.5, text/plain; q=0.8, text/html;level=3;'; 771 772 if (!empty($this->expected_type)) { 773 $accept .= "q=0.9, {$this->expected_type}"; 774 } 775 776 $headers[] = $accept; 777 } 778 779 foreach ($this->headers as $header => $value) { 780 $headers[] = "$header: $value"; 781 } 782 783 $url = \parse_url($this->uri); 784 $path = (isset($url['path']) ? $url['path'] : '/').(isset($url['query']) ? '?'.$url['query'] : ''); 785 $this->raw_headers = "{$this->method} $path HTTP/1.1\r\n"; 786 $host = (isset($url['host']) ? $url['host'] : 'localhost').(isset($url['port']) ? ':'.$url['port'] : ''); 787 $this->raw_headers .= "Host: $host\r\n"; 788 $this->raw_headers .= \implode("\r\n", $headers); 789 $this->raw_headers .= "\r\n"; 790 791 curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); 792 793 if (isset($this->payload)) { 794 $this->serialized_payload = $this->_serializePayload($this->payload); 795 curl_setopt($ch, CURLOPT_POSTFIELDS, $this->serialized_payload); 796 } 797 798 if ($this->_debug) { 799 curl_setopt($ch, CURLOPT_VERBOSE, true); 800 } 801 802 curl_setopt($ch, CURLOPT_HEADER, 1); 803 804 // If there are some additional curl opts that the user wants 805 // to set, we can tack them in here 806 foreach ($this->additional_curl_opts as $curlopt => $curlval) { 807 curl_setopt($ch, $curlopt, $curlval); 808 } 809 810 $this->_ch = $ch; 811 812 return $this; 813 } 814 815 public function buildUserAgent() { 816 $user_agent = 'User-Agent: Httpful/' . Httpful::VERSION . ' (cURL/'; 817 $curl = \curl_version(); 818 819 if (isset($curl['version'])) { 820 $user_agent .= $curl['version']; 821 } else { 822 $user_agent .= '?.?.?'; 823 } 824 825 $user_agent .= ' PHP/'. PHP_VERSION . ' (' . PHP_OS . ')'; 826 827 if (isset($_SERVER['SERVER_SOFTWARE'])) { 828 $user_agent .= ' ' . \preg_replace('~PHP/[\d\.]+~U', '', 829 $_SERVER['SERVER_SOFTWARE']); 830 } else { 831 if (isset($_SERVER['TERM_PROGRAM'])) { 832 $user_agent .= " {$_SERVER['TERM_PROGRAM']}"; 833 } 834 835 if (isset($_SERVER['TERM_PROGRAM_VERSION'])) { 836 $user_agent .= "/{$_SERVER['TERM_PROGRAM_VERSION']}"; 837 } 838 } 839 840 if (isset($_SERVER['HTTP_USER_AGENT'])) { 841 $user_agent .= " {$_SERVER['HTTP_USER_AGENT']}"; 842 } 843 844 $user_agent .= ')'; 845 846 return $user_agent; 847 } 848 849 /** 850 * Semi-reluctantly added this as a way to add in curl opts 851 * that are not otherwise accessible from the rest of the API. 852 * @return Request $this 853 * @param string $curlopt 854 * @param mixed $curloptval 855 */ 856 public function addOnCurlOption($curlopt, $curloptval) 857 { 858 $this->additional_curl_opts[$curlopt] = $curloptval; 859 return $this; 860 } 861 862 /** 863 * Turn payload from structured data into 864 * a string based on the current Mime type. 865 * This uses the auto_serialize option to determine 866 * it's course of action. See serialize method for more. 867 * Renamed from _detectPayload to _serializePayload as of 868 * 2012-02-15. 869 * 870 * Added in support for custom payload serializers. 871 * The serialize_payload_method stuff still holds true though. 872 * @see Request::registerPayloadSerializer() 873 * 874 * @return string 875 * @param mixed $payload 876 */ 877 private function _serializePayload($payload) 878 { 879 if (empty($payload) || $this->serialize_payload_method === self::SERIALIZE_PAYLOAD_NEVER) 880 return $payload; 881 882 // When we are in "smart" mode, don't serialize strings/scalars, assume they are already serialized 883 if ($this->serialize_payload_method === self::SERIALIZE_PAYLOAD_SMART && is_scalar($payload)) 884 return $payload; 885 886 // Use a custom serializer if one is registered for this mime type 887 if (isset($this->payload_serializers['*']) || isset($this->payload_serializers[$this->content_type])) { 888 $key = isset($this->payload_serializers[$this->content_type]) ? $this->content_type : '*'; 889 return call_user_func($this->payload_serializers[$key], $payload); 890 } 891 892 return Httpful::get($this->content_type)->serialize($payload); 893 } 894 895 /** 896 * HTTP Method Get 897 * @return Request 898 * @param string $uri optional uri to use 899 * @param string $mime expected 900 */ 901 public static function get($uri, $mime = null) 902 { 903 return self::init(Http::GET)->uri($uri)->mime($mime); 904 } 905 906 907 /** 908 * Like Request:::get, except that it sends off the request as well 909 * returning a response 910 * @return Response 911 * @param string $uri optional uri to use 912 * @param string $mime expected 913 */ 914 public static function getQuick($uri, $mime = null) 915 { 916 return self::get($uri, $mime)->send(); 917 } 918 919 /** 920 * HTTP Method Post 921 * @return Request 922 * @param string $uri optional uri to use 923 * @param string $payload data to send in body of request 924 * @param string $mime MIME to use for Content-Type 925 */ 926 public static function post($uri, $payload = null, $mime = null) 927 { 928 return self::init(Http::POST)->uri($uri)->body($payload, $mime); 929 } 930 931 /** 932 * HTTP Method Put 933 * @return Request 934 * @param string $uri optional uri to use 935 * @param string $payload data to send in body of request 936 * @param string $mime MIME to use for Content-Type 937 */ 938 public static function put($uri, $payload = null, $mime = null) 939 { 940 return self::init(Http::PUT)->uri($uri)->body($payload, $mime); 941 } 942 943 /** 944 * HTTP Method Patch 945 * @return Request 946 * @param string $uri optional uri to use 947 * @param string $payload data to send in body of request 948 * @param string $mime MIME to use for Content-Type 949 */ 950 public static function patch($uri, $payload = null, $mime = null) 951 { 952 return self::init(Http::PATCH)->uri($uri)->body($payload, $mime); 953 } 954 955 /** 956 * HTTP Method Delete 957 * @return Request 958 * @param string $uri optional uri to use 959 */ 960 public static function delete($uri, $mime = null) 961 { 962 return self::init(Http::DELETE)->uri($uri)->mime($mime); 963 } 964 965 /** 966 * HTTP Method Head 967 * @return Request 968 * @param string $uri optional uri to use 969 */ 970 public static function head($uri) 971 { 972 return self::init(Http::HEAD)->uri($uri); 973 } 974 975 /** 976 * HTTP Method Options 977 * @return Request 978 * @param string $uri optional uri to use 979 */ 980 public static function options($uri) 981 { 982 return self::init(Http::OPTIONS)->uri($uri); 983 } 984 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Sun Nov 30 09:20:46 2014 | Cross-referenced by PHPXref 0.7.1 |