def default_url_fetcher(url, timeout=10, ssl_context=None):
    """Fetch an external resource such as an image or stylesheet.

    Another callable with the same signature can be given as the
    ``url_fetcher`` argument to :class:`HTML` or :class:`CSS`.
    (See :ref:`URL Fetchers`.)

    :param str url:
        The URL of the resource to fetch.
    :param int timeout:
        The number of seconds before HTTP requests are dropped.
    :param ssl.SSLContext ssl_context:
        An SSL context used for HTTP requests.
    :raises: An exception indicating failure, e.g. :obj:`ValueError` on
        syntactically invalid URL.
    :returns: A :obj:`dict` with the following keys:

        * One of ``string`` (a :obj:`bytestring <bytes>`) or ``file_obj``
          (a :term:`file object`).
        * Optionally: ``mime_type``, a MIME type extracted e.g. from a
          *Content-Type* header. If not provided, the type is guessed from the
          file extension in the URL.
        * Optionally: ``encoding``, a character encoding extracted e.g. from a
          *charset* parameter in a *Content-Type* header
        * Optionally: ``redirected_url``, the actual URL of the resource
          if there were e.g. HTTP redirects.
        * Optionally: ``filename``, the filename of the resource. Usually
          derived from the *filename* parameter in a *Content-Disposition*
          header

        If a ``file_obj`` key is given, it is the caller’s responsibility
        to call ``file_obj.close()``. The default function used internally to
        fetch data in WeasyPrint tries to close the file object after
        retreiving; but if this URL fetcher is used elsewhere, the file object
        has to be closed manually.

    """
    if UNICODE_SCHEME_RE.match(url):
        # See https://bugs.python.org/issue34702
        if url.startswith('file://'):
            url = url.split('?')[0]

        url = iri_to_uri(url)
        response = urlopen(
            Request(url, headers=HTTP_HEADERS), timeout=timeout,
            context=ssl_context)
        response_info = response.info()
        result = {
            'redirected_url': response.geturl(),
            'mime_type': response_info.get_content_type(),
            'encoding': response_info.get_param('charset'),
            'filename': response_info.get_filename(),
        }
        content_encoding = response_info.get('Content-Encoding')
        if content_encoding == 'gzip':
            result['file_obj'] = StreamingGzipFile(fileobj=response)
        elif content_encoding == 'deflate':
            data = response.read()
            try:
                result['string'] = zlib.decompress(data)
            except zlib.error:
                # Try without zlib header or checksum
                result['string'] = zlib.decompress(data, -15)
        else:
            result['file_obj'] = response
        return result
    else:  # pragma: no cover
        raise ValueError('Not an absolute URI: %r' % url)
Fetch an external resource such as an image or stylesheet.

Another callable with the same signature can be given as the
``url_fetcher`` argument to :class:`HTML` or :class:`CSS`.
(See :ref:`URL Fetchers`.)

:param str url:
The URL of the resource to fetch.
:param int timeout:
The number of seconds before HTTP requests are dropped.
:param ssl.SSLContext ssl_context:
An SSL context used for HTTP requests.
:raises: An exception indicating failure, e.g. :obj:`ValueError` on
syntactically invalid URL.
:returns: A :obj:`dict` with the following keys:

* One of ``string`` (a :obj:`bytestring <bytes>`) or ``file_obj``
(a :term:`file object`).
* Optionally: ``mime_type``, a MIME type extracted e.g. from a
*Content-Type* header. If not provided, the type is guessed from the
file extension in the URL.
* Optionally: ``encoding``, a character encoding extracted e.g. from a
*charset* parameter in a *Content-Type* header
* Optionally: ``redirected_url``, the actual URL of the resource
if there were e.g. HTTP redirects.
* Optionally: ``filename``, the filename of the resource. Usually
derived from the *filename* parameter in a *Content-Disposition*
header

If a ``file_obj`` key is given, it is the caller’s responsibility
to call ``file_obj.close()``. The default function used internally to
fetch data in WeasyPrint tries to close the file object after
retreiving; but if this URL fetcher is used elsewhere, the file object
has to be closed manually.
weasyprint/urls.py