/** * Assemble an HTTP request from received FCGI params. */ protected function buildRequest() : HttpRequest { static $extra = ['CONTENT_TYPE' => 'Content-Type', 'CONTENT_LENGTH' => 'Content-Length', 'CONTENT_MD5' => 'Content-MD5']; $uri = \strtolower($this->params['REQUEST_SCHEME'] ?? 'http') . '://'; $uri .= $this->params['HTTP_HOST'] ?? $this->context->getPeerName(); if (!empty($this->params['SERVER_PORT'])) { $uri .= ':' . (int) $this->params['SERVER_PORT']; } $uri = Uri::parse($uri . '/' . \ltrim($this->params['REQUEST_URI'] ?? '', '/')); $request = new HttpRequest($uri, $this->params['REQUEST_METHOD'] ?? Http::GET, [], '1.1'); foreach ($this->params as $k => $v) { if ('HTTP_' === \substr($k, 0, 5)) { switch ($k) { case 'HTTP_TRANSFER_ENCODING': case 'HTTP_CONTENT_ENCODING': case 'HTTP_KEEP_ALIVE': // Skip these headers... break; default: $request = $request->withAddedHeader(\str_replace('_', '-', \substr($k, 5)), (string) $v); } } } foreach ($extra as $k => $v) { if (isset($this->params[$k])) { $request = $request->withHeader($v, $this->params[$k]); } } $addresses = [$this->conn->getRemoteAddress()]; if (isset($this->params['REMOTE_ADDR'])) { $addresses = \array_merge([$this->params['REMOTE_ADDR']], $addresses); } $request = $request->withAddress(...$addresses); $request = $request->withAttribute(HttpDriverContext::class, $this->context); return $request->withBody(new StreamBody(new ReadableChannelStream($this->body))); }
/** * Parse the next HTTP request that arrives via the given stream. * * @param SocketStream $socket * @return HttpRequest */ protected function parseNextRequest(HttpDriverContext $context, SocketStream $socket) : \Generator { $request = (yield new Timeout(30, new Coroutine($this->parser->parseRequest($socket)))); $request->getBody()->setCascadeClose(false); if ($request->getProtocolVersion() == '1.1') { if (\in_array('100-continue', $request->getHeaderTokenValues('Expect'), true)) { $request->getBody()->setExpectContinue($socket); } } $peerName = $context->getPeerName(); $protocol = $context->isEncrypted() ? 'https' : 'http'; $proxy = $context->getProxySettings(); $parts = \explode(':', $socket->getRemoteAddress()); \array_pop($parts); $ip = \implode(':', $parts); $addresses = [$ip === '' ? '127.0.0.1' : $ip]; if ($proxy->isTrustedProxy($ip)) { $host = $proxy->getHost($request); if ($host === null) { if (!$request->hasHeader('Host')) { return $request; } $peerName = $request->getHeaderLine('Host'); } else { $peerName = $host; } $protocol = $proxy->getScheme($request) ?? $protocol; $addresses = \array_merge($proxy->getAddresses($request), $addresses); } elseif ($request->hasHeader('Host')) { $peerName = $request->getHeaderLine('Host'); } elseif ($request->getProtocolVersion() === '1.1') { return $request; } $request = $request->withAddress(...$addresses); $request = $request->withAttribute(HttpDriverContext::class, $context); $target = $request->getRequestTarget(); if (\substr($target, 0, 1) === '/') { $request = $request->withUri(Uri::parse(\sprintf('%s://%s/%s', $protocol, $peerName, \ltrim($target, '/')))); } else { $request = $request->withUri(Uri::parse(\sprintf('%s://%s/', $protocol, $peerName))); } return $request; }