* * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\BrowserKit; use Symfony\Component\HttpClient\HttpClient; use Symfony\Component\Mime\Part\AbstractPart; use Symfony\Component\Mime\Part\Multipart\FormDataPart; use Symfony\Component\Mime\Part\TextPart; use Symfony\Contracts\HttpClient\HttpClientInterface; /** * An implementation of a browser using the HttpClient component * to make real HTTP requests. * * @author Fabien Potencier * * @final */ class HttpBrowser extends AbstractBrowser { private $client; public function __construct(HttpClientInterface $client = null, History $history = null, CookieJar $cookieJar = null) { if (!class_exists(HttpClient::class)) { throw new \LogicException(sprintf('You cannot use "%s" as the HttpClient component is not installed. Try running "composer require symfony/http-client".', __CLASS__)); } $this->client = $client ?? HttpClient::create(); parent::__construct([], $history, $cookieJar); } protected function doRequest($request) { $headers = $this->getHeaders($request); $body = ''; if (null !== $part = $this->getBody($request)) { $headers = array_merge($headers, $part->getPreparedHeaders()->toArray()); $body = $part->bodyToIterable(); } $response = $this->client->request($request->getMethod(), $request->getUri(), [ 'headers' => $headers, 'body' => $body, 'max_redirects' => 0, ]); return new Response($response->getContent(false), $response->getStatusCode(), $response->getHeaders(false)); } private function getBody(Request $request): ?AbstractPart { if (\in_array($request->getMethod(), ['GET', 'HEAD'])) { return null; } if (!class_exists(AbstractPart::class)) { throw new \LogicException('You cannot pass non-empty bodies as the Mime component is not installed. Try running "composer require symfony/mime".'); } if (null !== $content = $request->getContent()) { return new TextPart($content, 'utf-8', 'plain', '8bit'); } $fields = $request->getParameters(); foreach ($request->getFiles() as $name => $file) { if (!isset($file['tmp_name'])) { continue; } $fields[$name] = DataPart::fromPath($file['tmp_name'], $file['name']); } return new FormDataPart($fields); } private function getHeaders(Request $request): array { $headers = []; foreach ($request->getServer() as $key => $value) { $key = strtolower(str_replace('_', '-', $key)); $contentHeaders = ['content-length' => true, 'content-md5' => true, 'content-type' => true]; if (0 === strpos($key, 'http-')) { $headers[substr($key, 5)] = $value; } elseif (isset($contentHeaders[$key])) { // CONTENT_* are not prefixed with HTTP_ $headers[$key] = $value; } } $cookies = []; foreach ($this->getCookieJar()->allRawValues($request->getUri()) as $name => $value) { $cookies[] = $name.'='.$value; } if ($cookies) { $headers['cookie'] = implode('; ', $cookies); } return $headers; } }