private function validateUrl($url)
    {
        // Check for feed URL
        $url = trim($url);
        if ('feed://' === strtolower(substr($url, 0, 7))) {
            $url = 'http://' . substr($url, 7);
        }

        if (!preg_match('!^https?://.+!i', $url)) {
            $url = 'http://' . $url;
        }

        // explode url to convert accents
        $parsedUrl = parse_url($url);

        if (false === $parsedUrl) {
            throw new \Exception(sprintf('Url "%s" is not valid.', $url));
        }

        if (isset($parsedUrl['host']) && preg_match('/[\x80-\xff]/', $parsedUrl['host'])) {
            $parsedUrl['host'] = $this->punycode->encode($parsedUrl['host']);
        }

        if (isset($parsedUrl['path']) && preg_match('/[\x80-\xff]/', $parsedUrl['path'])) {
            $path = [];
            foreach (explode('/', $parsedUrl['path']) as $value) {
                $path[] = urlencode($value);
            }
            $parsedUrl['path'] = implode('/', $path);
        }

        // everything should be converted, rebuild the final url
        $url = $this->unparseUrl($parsedUrl);

        if (false === filter_var($url, FILTER_VALIDATE_URL)) {
            throw new \Exception(sprintf('Url "%s" is not valid.', $url));
        }

        $url = filter_var($url, FILTER_SANITIZE_URL);

        if (false === $this->isUrlAllowed($url)) {
            throw new \Exception(sprintf('Url "%s" is not allowed to be parsed.', $url));
        }

        return $url;
    }