Skip to main content
Drupal API
User account menu
  • Log in

Breadcrumb

  1. Drupal Core 11.1.x
  2. HttpBrowser.php

class HttpBrowser

An implementation of a browser using the HttpClient component to make real HTTP requests.

@author Fabien Potencier <fabien@symfony.com>

@template-extends AbstractBrowser<Request, Response>

Hierarchy

  • class \Symfony\Component\BrowserKit\AbstractBrowser
    • class \Symfony\Component\BrowserKit\HttpBrowser extends \Symfony\Component\BrowserKit\AbstractBrowser

Expanded class hierarchy of HttpBrowser

File

vendor/symfony/browser-kit/HttpBrowser.php, line 30

Namespace

Symfony\Component\BrowserKit
View source
class HttpBrowser extends AbstractBrowser {
    private HttpClientInterface $client;
    public function __construct(?HttpClientInterface $client = null, ?History $history = null, ?CookieJar $cookieJar = null) {
        if (!$client && !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);
    }
    
    /**
     * @param Request $request
     */
    protected function doRequest(object $request) : Response {
        $headers = $this->getHeaders($request);
        [
            $body,
            $extraHeaders,
        ] = $this->getBodyAndExtraHeaders($request, $headers);
        $response = $this->client
            ->request($request->getMethod(), $request->getUri(), [
            'headers' => array_merge($headers, $extraHeaders),
            'body' => $body,
            'max_redirects' => 0,
        ]);
        return new Response($response->getContent(false), $response->getStatusCode(), $response->getHeaders(false));
    }
    
    /**
     * @return array [$body, $headers]
     */
    private function getBodyAndExtraHeaders(Request $request, array $headers) : array {
        if (\in_array($request->getMethod(), [
            'GET',
            'HEAD',
        ]) && !isset($headers['content-type'])) {
            return [
                '',
                [],
            ];
        }
        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())) {
            if (isset($headers['content-type'])) {
                return [
                    $content,
                    [],
                ];
            }
            $part = new TextPart($content, 'utf-8', 'plain', '8bit');
            return [
                $part->bodyToString(),
                $part->getPreparedHeaders()
                    ->toArray(),
            ];
        }
        $fields = $request->getParameters();
        if ($uploadedFiles = $this->getUploadedFiles($request->getFiles())) {
            $part = new FormDataPart(array_replace_recursive($fields, $uploadedFiles));
            return [
                $part->bodyToIterable(),
                $part->getPreparedHeaders()
                    ->toArray(),
            ];
        }
        if (!$fields) {
            return [
                '',
                [],
            ];
        }
        array_walk_recursive($fields, $caster = static function (&$v) use (&$caster) {
            if (\is_object($v)) {
                if ($vars = get_object_vars($v)) {
                    array_walk_recursive($vars, $caster);
                    $v = $vars;
                }
                elseif ($v instanceof \Stringable) {
                    $v = (string) $v;
                }
            }
        });
        return [
            http_build_query($fields, '', '&'),
            [
                'Content-Type' => 'application/x-www-form-urlencoded',
            ],
        ];
    }
    protected 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 (str_starts_with($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;
    }
    
    /**
     * Recursively go through the list. If the file has a tmp_name, convert it to a DataPart.
     * Keep the original hierarchy.
     */
    private function getUploadedFiles(array $files) : array {
        $uploadedFiles = [];
        foreach ($files as $name => $file) {
            if (!\is_array($file)) {
                return $uploadedFiles;
            }
            if (!isset($file['tmp_name'])) {
                $uploadedFiles[$name] = $this->getUploadedFiles($file);
            }
            if (isset($file['tmp_name'])) {
                $uploadedFiles[$name] = DataPart::fromPath($file['tmp_name'], $file['name']);
            }
        }
        return $uploadedFiles;
    }

}

Members

Title Sort descending Modifiers Object type Summary Overriden Title Overrides
AbstractBrowser::$cookieJar protected property
AbstractBrowser::$crawler protected property
AbstractBrowser::$followMetaRefresh protected property
AbstractBrowser::$followRedirects protected property
AbstractBrowser::$history protected property
AbstractBrowser::$insulated protected property
AbstractBrowser::$internalRequest protected property
AbstractBrowser::$internalResponse protected property
AbstractBrowser::$isMainRequest private property
AbstractBrowser::$maxRedirects private property
AbstractBrowser::$redirect protected property
AbstractBrowser::$redirectCount private property
AbstractBrowser::$redirects private property
AbstractBrowser::$request protected property @psalm-var TRequest
AbstractBrowser::$response protected property @psalm-var TResponse
AbstractBrowser::$server protected property
AbstractBrowser::$useHtml5Parser protected property
AbstractBrowser::back public function Goes back in the browser history.
AbstractBrowser::click public function Clicks on a given link.
AbstractBrowser::clickLink public function Clicks the first link (or clickable image) that contains the given text.
AbstractBrowser::createCrawlerFromContent protected function Creates a crawler.
AbstractBrowser::doRequestInProcess protected function Makes a request in another process.
AbstractBrowser::extractHost private function
AbstractBrowser::filterRequest protected function Filters the BrowserKit request to the origin one. 1
AbstractBrowser::filterResponse protected function Filters the origin response to the BrowserKit one. 1
AbstractBrowser::followMetaRefresh public function Sets whether to automatically follow meta refresh redirects or not.
AbstractBrowser::followRedirect public function Follow redirects?
AbstractBrowser::followRedirects public function Sets whether to automatically follow redirects or not.
AbstractBrowser::forward public function Goes forward in the browser history.
AbstractBrowser::getAbsoluteUri protected function Takes a URI and converts it to absolute if it is not already absolute.
AbstractBrowser::getCookieJar public function Returns the CookieJar instance.
AbstractBrowser::getCrawler public function Returns the current Crawler instance.
AbstractBrowser::getHistory public function Returns the History instance.
AbstractBrowser::getInternalRequest public function Returns the current BrowserKit Request instance.
AbstractBrowser::getInternalResponse public function Returns the current BrowserKit Response instance.
AbstractBrowser::getMaxRedirects public function Returns the maximum number of redirects that crawler can follow.
AbstractBrowser::getMetaRefreshUrl private function
AbstractBrowser::getRequest public function Returns the current origin Request instance.
AbstractBrowser::getResponse public function Returns the current origin response instance.
AbstractBrowser::getScript protected function Returns the script to execute when the request must be insulated. 1
AbstractBrowser::getServerParameter public function Gets single server parameter for specified key.
AbstractBrowser::insulate public function Sets the insulated flag.
AbstractBrowser::isFollowingRedirects public function Returns whether client automatically follows redirects or not.
AbstractBrowser::jsonRequest public function Converts the request parameters into a JSON string and uses it as request content.
AbstractBrowser::reload public function Reloads the current browser.
AbstractBrowser::request public function Calls a URI.
AbstractBrowser::requestFromRequest protected function Makes a request from a Request object directly.
AbstractBrowser::restart public function Restarts the client.
AbstractBrowser::setMaxRedirects public function Sets the maximum number of redirects that crawler can follow.
AbstractBrowser::setServerParameter public function Sets single server parameter.
AbstractBrowser::setServerParameters public function Sets server parameters.
AbstractBrowser::submit public function Submits a form.
AbstractBrowser::submitForm public function Finds the first form that contains a button with the given content and
uses it to submit the given form field values.
AbstractBrowser::updateServerFromUri private function
AbstractBrowser::useHtml5Parser public function Sets whether parsing should be done using &quot;masterminds/html5&quot;.
AbstractBrowser::xmlHttpRequest public function
HttpBrowser::$client private property
HttpBrowser::doRequest protected function Overrides AbstractBrowser::doRequest
HttpBrowser::getBodyAndExtraHeaders private function
HttpBrowser::getHeaders protected function
HttpBrowser::getUploadedFiles private function Recursively go through the list. If the file has a tmp_name, convert it to a DataPart.
Keep the original hierarchy.
HttpBrowser::__construct public function Overrides AbstractBrowser::__construct
RSS feed
Powered by Drupal