1<?php 2 3/** 4 * Copyright (c) 2006- Facebook 5 * Distributed under the Thrift Software License 6 * 7 * See accompanying file LICENSE or visit the Thrift site at: 8 * http://developers.facebook.com/thrift/ 9 * 10 * @package thrift.transport 11 * @author Mark Slee <mcslee@facebook.com> 12 */ 13 14/** 15 * HTTP client for Thrift 16 * 17 * @package thrift.transport 18 * @author Mark Slee <mcslee@facebook.com> 19 */ 20class THttpClient extends TTransport { 21 22 /** 23 * The host to connect to 24 * 25 * @var string 26 */ 27 protected $host_; 28 29 /** 30 * The port to connect on 31 * 32 * @var int 33 */ 34 protected $port_; 35 36 /** 37 * The URI to request 38 * 39 * @var string 40 */ 41 protected $uri_; 42 43 /** 44 * The scheme to use for the request, i.e. http, https 45 * 46 * @var string 47 */ 48 protected $scheme_; 49 50 /** 51 * Buffer for the HTTP request data 52 * 53 * @var string 54 */ 55 protected $buf_; 56 57 /** 58 * Input socket stream. 59 * 60 * @var resource 61 */ 62 protected $handle_; 63 64 /** 65 * Read timeout 66 * 67 * @var float 68 */ 69 protected $timeout_; 70 71 /** 72 * Make a new HTTP client. 73 * 74 * @param string $host 75 * @param int $port 76 * @param string $uri 77 */ 78 public function __construct($host, $port=80, $uri='', $scheme = 'http') { 79 if ((strlen($uri) > 0) && ($uri{0} != '/')) { 80 $uri = '/'.$uri; 81 } 82 $this->scheme_ = $scheme; 83 $this->host_ = $host; 84 $this->port_ = $port; 85 $this->uri_ = $uri; 86 $this->buf_ = ''; 87 $this->handle_ = null; 88 $this->timeout_ = null; 89 } 90 91 /** 92 * Set read timeout 93 * 94 * @param float $timeout 95 */ 96 public function setTimeoutSecs($timeout) { 97 $this->timeout_ = $timeout; 98 } 99 100 /** 101 * Whether this transport is open. 102 * 103 * @return boolean true if open 104 */ 105 public function isOpen() { 106 return true; 107 } 108 109 /** 110 * Open the transport for reading/writing 111 * 112 * @throws TTransportException if cannot open 113 */ 114 public function open() {} 115 116 /** 117 * Close the transport. 118 */ 119 public function close() { 120 if ($this->handle_) { 121 @fclose($this->handle_); 122 $this->handle_ = null; 123 } 124 } 125 126 /** 127 * Read some data into the array. 128 * 129 * @param int $len How much to read 130 * @return string The data that has been read 131 * @throws TTransportException if cannot read any more data 132 */ 133 public function read($len) { 134 $data = @fread($this->handle_, $len); 135 if ($data === FALSE || $data === '') { 136 $md = stream_get_meta_data($this->handle_); 137 if ($md['timed_out']) { 138 throw new TTransportException('THttpClient: timed out reading '.$len.' bytes from '.$this->host_.':'.$this->port_.'/'.$this->uri_, TTransportException::TIMED_OUT); 139 } else { 140 throw new TTransportException('THttpClient: Could not read '.$len.' bytes from '.$this->host_.':'.$this->port_.'/'.$this->uri_, TTransportException::UNKNOWN); 141 } 142 } 143 return $data; 144 } 145 146 /** 147 * Writes some data into the pending buffer 148 * 149 * @param string $buf The data to write 150 * @throws TTransportException if writing fails 151 */ 152 public function write($buf) { 153 $this->buf_ .= $buf; 154 } 155 156 /** 157 * Opens and sends the actual request over the HTTP connection 158 * 159 * @throws TTransportException if a writing error occurs 160 */ 161 public function flush() { 162 // God, PHP really has some esoteric ways of doing simple things. 163 $host = $this->host_.($this->port_ != 80 ? ':'.$this->port_ : ''); 164 165 $headers = array('Host: '.$host, 166 'Accept: application/x-thrift', 167 'User-Agent: PHP/THttpClient', 168 'Content-Type: application/x-thrift', 169 'Content-Length: '.strlen($this->buf_)); 170 171 $options = array('method' => 'POST', 172 'header' => implode("\r\n", $headers), 173 'max_redirects' => 1, 174 'content' => $this->buf_); 175 if ($this->timeout_ > 0) { 176 $options['timeout'] = $this->timeout_; 177 } 178 $this->buf_ = ''; 179 180 $contextid = stream_context_create(array('http' => $options)); 181 $this->handle_ = @fopen($this->scheme_.'://'.$host.$this->uri_, 'r', false, $contextid); 182 183 // Connect failed? 184 if ($this->handle_ === FALSE) { 185 $this->handle_ = null; 186 $error = 'THttpClient: Could not connect to '.$host.$this->uri_; 187 throw new TTransportException($error, TTransportException::NOT_OPEN); 188 } 189 } 190 191} 192 193?> 194