public function request(RequestInterface $request, Options $options) { $context = stream_context_create(); // ssl $scheme = null; if ($options->getSsl() !== false && ($options->getSsl() === true || strcasecmp($request->getUri()->getScheme(), 'https') === 0)) { $transports = stream_get_transports(); if (in_array('tls', $transports)) { $scheme = 'tls'; } elseif (in_array('ssl', $transports)) { $scheme = 'ssl'; } else { throw new NotSupportedException('https is not supported'); } Stream::assignSslContext($context, $options); } else { $scheme = 'tcp'; } // port $port = $request->getUri()->getPort(); if (empty($port)) { $port = getservbyname($request->getUri()->getScheme(), 'tcp'); } // open socket set_error_handler(__CLASS__ . '::handleError'); $timeout = ini_get('default_socket_timeout'); $handle = stream_socket_client($scheme . '://' . $request->getUri()->getHost() . ':' . $port, $errno, $errstr, $timeout, STREAM_CLIENT_CONNECT, $context); restore_error_handler(); if ($handle !== false) { // timeout $timeout = $options->getTimeout(); if (!empty($timeout)) { stream_set_timeout($handle, $timeout); } // callback $callback = $options->getCallback(); if (!empty($callback)) { call_user_func_array($callback, array($handle, $request)); } // write header $headers = ResponseParser::buildHeaderFromMessage($request); fwrite($handle, Http\RequestParser::buildStatusLine($request) . Http::$newLine); foreach ($headers as $header) { fwrite($handle, $header . Http::$newLine); } fwrite($handle, Http::$newLine); fflush($handle); // write body $body = $request->getBody(); if ($body !== null && !in_array($request->getMethod(), array('HEAD', 'GET'))) { if ($request->getHeader('Transfer-Encoding') == 'chunked') { while (!$body->eof()) { $chunk = $body->read($this->chunkSize); $len = strlen($chunk); if ($len > 0) { fwrite($handle, dechex($len) . Http::$newLine . $chunk . Http::$newLine); fflush($handle); } } fwrite($handle, '0' . Http::$newLine . Http::$newLine); fflush($handle); } else { fwrite($handle, (string) $body); fflush($handle); } } // read header $headers = array(); do { $header = trim(fgets($handle)); if (!empty($header)) { $headers[] = $header; } } while (!empty($header)); // check for timeout $meta = stream_get_meta_data($handle); if ($meta['timed_out']) { throw new HandlerException('Connection timeout'); } // build response $response = ResponseParser::buildResponseFromHeader($headers); // create stream $contentLength = (int) $response->getHeader('Content-Length'); $chunkedEncoding = $response->getHeader('Transfer-Encoding') == 'chunked'; if ($request->getMethod() != 'HEAD') { $response->setBody(new SocksStream($handle, $contentLength, $chunkedEncoding)); } else { fclose($handle); $response->setBody(new StringStream()); } return $response; } else { throw new HandlerException(!empty($errstr) ? $errstr : 'Could not open socket'); } }
/** * @expectedException \PSX\Exception */ public function testBuildStatusLineNoTarget() { $request = new Request(new Url('http://127.0.0.1'), 'GET'); $request->setRequestTarget(''); RequestParser::buildStatusLine($request); }
/** * Converts the request object to an http request string * * @return string */ public function toString() { $request = RequestParser::buildStatusLine($this) . Http::$newLine; $headers = RequestParser::buildHeaderFromMessage($this); foreach ($headers as $header) { $request .= $header . Http::$newLine; } $request .= Http::$newLine; $request .= (string) $this->getBody(); return $request; }