Magento 2 Documentation  2.3
Documentation for Magento 2 CMS v2.3 (December 2018)
Proxy.php
Go to the documentation of this file.
1 <?php
2 
27 #require_once 'Zend/Uri/Http.php';
28 
31 #require_once 'Zend/Http/Client.php';
32 
35 #require_once 'Zend/Http/Client/Adapter/Socket.php';
36 
53 {
59  protected $config = array(
60  'ssltransport' => 'ssl',
61  'sslcert' => null,
62  'sslpassphrase' => null,
63  'sslusecontext' => false,
64  'proxy_host' => '',
65  'proxy_port' => 8080,
66  'proxy_user' => '',
67  'proxy_pass' => '',
68  'proxy_auth' => Zend_Http_Client::AUTH_BASIC,
69  'persistent' => false,
70  );
71 
77  protected $negotiated = false;
78 
85 
96  public function connect($host, $port = 80, $secure = false)
97  {
98  // If no proxy is set, fall back to Socket adapter
99  if (!$this->config['proxy_host']) {
100  return parent::connect($host, $port, $secure);
101  }
102 
103  /* Url might require stream context even if proxy connection doesn't */
104  if ($secure) {
105  $this->config['sslusecontext'] = true;
106  }
107 
108  // Connect (a non-secure connection) to the proxy server
109  return parent::connect(
110  $this->config['proxy_host'],
111  $this->config['proxy_port'],
112  false
113  );
114  }
115 
127  public function write(
128  $method, $uri, $http_ver = '1.1', $headers = array(), $body = ''
129  )
130  {
131  // If no proxy is set, fall back to default Socket adapter
132  if (!$this->config['proxy_host']) {
133  return parent::write($method, $uri, $http_ver, $headers, $body);
134  }
135 
136  // Make sure we're properly connected
137  if (!$this->socket) {
138  #require_once 'Zend/Http/Client/Adapter/Exception.php';
140  'Trying to write but we are not connected'
141  );
142  }
143 
144  $host = $this->config['proxy_host'];
145  $port = $this->config['proxy_port'];
146 
147  if ($this->connected_to[0] != "tcp://$host"
148  || $this->connected_to[1] != $port
149  ) {
150  #require_once 'Zend/Http/Client/Adapter/Exception.php';
152  'Trying to write but we are connected to the wrong proxy server'
153  );
154  }
155 
156  // Add Proxy-Authorization header
157  if ($this->config['proxy_user']) {
158  // Check to see if one already exists
159  $hasProxyAuthHeader = false;
160  foreach ($headers as $k => $v) {
161  if ((string) $k == 'proxy-authorization'
162  || preg_match("/^proxy-authorization:/i", $v)
163  ) {
164  $hasProxyAuthHeader = true;
165  break;
166  }
167  }
168  if (!$hasProxyAuthHeader) {
169  $headers[] = 'Proxy-authorization: '
171  $this->config['proxy_user'],
172  $this->config['proxy_pass'], $this->config['proxy_auth']
173  );
174  }
175  }
176 
177  // if we are proxying HTTPS, preform CONNECT handshake with the proxy
178  if ($uri->getScheme() == 'https' && (!$this->negotiated)) {
179  $this->connectHandshake(
180  $uri->getHost(), $uri->getPort(), $http_ver, $headers
181  );
182  $this->negotiated = true;
183  }
184 
185  // Save request method for later
186  $this->method = $method;
187 
188  // Build request headers
189  if ($this->negotiated) {
190  $path = $uri->getPath();
191  if ($uri->getQuery()) {
192  $path .= '?' . $uri->getQuery();
193  }
194  $request = "$method $path HTTP/$http_ver\r\n";
195  } else {
196  $request = "$method $uri HTTP/$http_ver\r\n";
197  }
198 
199  // Add all headers to the request string
200  foreach ($headers as $k => $v) {
201  if (is_string($k)) $v = "$k: $v";
202  $request .= "$v\r\n";
203  }
204 
205  if(is_resource($body)) {
206  $request .= "\r\n";
207  } else {
208  // Add the request body
209  $request .= "\r\n" . $body;
210  }
211 
212  // Send the request
213  if (!@fwrite($this->socket, $request)) {
214  #require_once 'Zend/Http/Client/Adapter/Exception.php';
216  'Error writing request to proxy server'
217  );
218  }
219 
220  if(is_resource($body)) {
221  if(stream_copy_to_stream($body, $this->socket) == 0) {
222  #require_once 'Zend/Http/Client/Adapter/Exception.php';
224  'Error writing request to server'
225  );
226  }
227  }
228 
229  return $request;
230  }
231 
242  protected function connectHandshake(
243  $host, $port = 443, $http_ver = '1.1', array &$headers = array()
244  )
245  {
246  $request = "CONNECT $host:$port HTTP/$http_ver\r\n" .
247  "Host: " . $host . "\r\n";
248 
249  // Process provided headers, including important ones to CONNECT request
250  foreach ($headers as $k => $v) {
251  switch (strtolower(substr($v,0,strpos($v,':')))) {
252  case 'proxy-authorization':
253  // break intentionally omitted
254 
255  case 'user-agent':
256  $request .= $v . "\r\n";
257  break;
258 
259  default:
260  break;
261  }
262  }
263  $request .= "\r\n";
264 
265  // @see ZF-3189
266  $this->connectHandshakeRequest = $request;
267 
268  // Send the request
269  if (!@fwrite($this->socket, $request)) {
270  #require_once 'Zend/Http/Client/Adapter/Exception.php';
272  'Error writing request to proxy server'
273  );
274  }
275 
276  // Read response headers only
277  $response = '';
278  $gotStatus = false;
279  while ($line = @fgets($this->socket)) {
280  $gotStatus = $gotStatus || (strpos($line, 'HTTP') !== false);
281  if ($gotStatus) {
282  $response .= $line;
283  if (!chop($line)) {
284  break;
285  }
286  }
287  }
288 
289  // Check that the response from the proxy is 200
291  #require_once 'Zend/Http/Client/Adapter/Exception.php';
293  'Unable to connect to HTTPS proxy. Server response: ' . $response
294  );
295  }
296 
297  // If all is good, switch socket to secure mode. We have to fall back
298  // through the different modes
299  $modes = array(
300  // TODO: Add STREAM_CRYPTO_METHOD_TLSv1_3_CLIENT in the future when it is supported by PHP
301  STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT
302  );
303 
304  $success = false;
305  foreach($modes as $mode) {
306  $success = stream_socket_enable_crypto($this->socket, true, $mode);
307  if ($success) {
308  break;
309  }
310  }
311 
312  if (!$success) {
313  #require_once 'Zend/Http/Client/Adapter/Exception.php';
315  'Unable to connect to HTTPS server through proxy: could not '
316  . 'negotiate secure connection.'
317  );
318  }
319  }
320 
325  public function close()
326  {
327  parent::close();
328  $this->negotiated = false;
329  }
330 
335  public function __destruct()
336  {
337  if ($this->socket) {
338  $this->close();
339  }
340  }
341 }
connect($host, $port=80, $secure=false)
Definition: Proxy.php:96
$response
Definition: 404.php:11
write( $method, $uri, $http_ver='1.1', $headers=array(), $body='')
Definition: Proxy.php:127
const AUTH_BASIC
Definition: Client.php:91
connectHandshake( $host, $port=443, $http_ver='1.1', array &$headers=array())
Definition: Proxy.php:242
if($exist=($block->getProductCollection() && $block->getProductCollection() ->getSize())) $mode
Definition: grid.phtml:15
static encodeAuthHeader($user, $password, $type=self::AUTH_BASIC)
Definition: Client.php:1502
static extractCode($response_str)
Definition: Response.php:449