public function setUrl(string $url) : Request
    {
        $components = parse_url($url);

        if ($components === false) {
            throw new \InvalidArgumentException('The URL provided is not valid.');
        }

        if (! isset($components['scheme'])) {
            throw new \InvalidArgumentException('The URL must have a scheme.');
        }

        $scheme = strtolower($components['scheme']);

        if ($scheme !== 'http' && $scheme !== 'https') {
            throw new \InvalidArgumentException(sprintf('The URL scheme "%s" is not acceptable.', $scheme));
        }

        $isSecure = ($scheme === 'https');

        if (! isset($components['host'])) {
            throw new \InvalidArgumentException('The URL must have a host name.');
        }

        $host = $components['host'];

        if (isset($components['port'])) {
            $port = $components['port'];
            $hostHeader = $host . ':' . $port;
        } else {
            $port = ($isSecure ? 443 : 80);
            $hostHeader = $host;
        }

        $this->path = isset($components['path']) ? $components['path'] : '/';
        $requestUri = $this->path;

        if (isset($components['query'])) {
            $this->queryString = $components['query'];
            parse_str($this->queryString, $this->query);
            $requestUri .= '?' . $this->queryString;
        } else {
            $this->queryString = '';
            $this->query = [];
        }

        $this->setHeader('Host', $hostHeader);

        $this->host = $host;
        $this->port = $port;
        $this->isSecure = $isSecure;
        $this->requestUri = $requestUri;

        return $this;
    }