def _instrument_client(
    client: typing.Union[httpx.Client, httpx.AsyncClient],
    tracer_provider: TracerProvider = None,
    request_hook: typing.Optional[RequestHook] = None,
    response_hook: typing.Optional[ResponseHook] = None,
) -> None:
    """Enables instrumentation for the given Client or AsyncClient"""
    # pylint: disable=protected-access
    if isinstance(client, httpx.Client):
        transport = client._transport or httpx.HTTPTransport()
        telemetry_transport = SyncOpenTelemetryTransport(
            transport,
            tracer_provider=tracer_provider,
            request_hook=request_hook,
            response_hook=response_hook,
        )
    elif isinstance(client, httpx.AsyncClient):
        transport = client._transport or httpx.AsyncHTTPTransport()
        telemetry_transport = AsyncOpenTelemetryTransport(
            transport,
            tracer_provider=tracer_provider,
            request_hook=request_hook,
            response_hook=response_hook,
        )
    else:
        raise TypeError("Invalid client provided")
    client._transport = telemetry_transport
Example #2
0
def test_serve_unix_domain_socket(ds_unix_domain_socket_server):
    _, uds = ds_unix_domain_socket_server
    transport = httpx.HTTPTransport(uds=uds)
    client = httpx.Client(transport=transport)
    response = client.get("http://localhost/_memory.json")
    assert {
        "database": "_memory",
        "path": "/_memory",
        "tables": [],
    }.items() <= response.json().items()
Example #3
0
 def create_transport(
     self,
     tracer_provider: typing.Optional["TracerProvider"] = None,
     request_hook: typing.Optional["RequestHook"] = None,
     response_hook: typing.Optional["ResponseHook"] = None,
 ):
     transport = httpx.HTTPTransport()
     telemetry_transport = SyncOpenTelemetryTransport(
         transport,
         tracer_provider=tracer_provider,
         request_hook=request_hook,
         response_hook=response_hook,
     )
     return telemetry_transport
    def instrumented_sync_send(wrapped, instance, args, kwargs):
        if context.get_value("suppress_instrumentation"):
            return wrapped(*args, **kwargs)

        transport = instance._transport or httpx.HTTPTransport()
        telemetry_transport = SyncOpenTelemetryTransport(
            transport,
            tracer_provider=tracer_provider,
            request_hook=request_hook,
            response_hook=response_hook,
        )

        instance._transport = telemetry_transport
        return wrapped(*args, **kwargs)
Example #5
0
    def instrument_client(
        client: typing.Union[httpx.Client, httpx.AsyncClient],
        tracer_provider: TracerProvider = None,
        request_hook: typing.Optional[RequestHook] = None,
        response_hook: typing.Optional[ResponseHook] = None,
    ) -> None:
        """Instrument httpx Client or AsyncClient

        Args:
            client: The httpx Client or AsyncClient instance
            tracer_provider: A TracerProvider, defaults to global
            request_hook: A hook that receives the span and request that is called
                right after the span is created
            response_hook: A hook that receives the span, request, and response
                that is called right before the span ends
        """
        # pylint: disable=protected-access
        if not hasattr(client, "_is_instrumented_by_opentelemetry"):
            client._is_instrumented_by_opentelemetry = False

        if not client._is_instrumented_by_opentelemetry:
            if isinstance(client, httpx.Client):
                client._original_transport = client._transport
                transport = client._transport or httpx.HTTPTransport()
                client._transport = SyncOpenTelemetryTransport(
                    transport,
                    tracer_provider=tracer_provider,
                    request_hook=request_hook,
                    response_hook=response_hook,
                )
                client._is_instrumented_by_opentelemetry = True
            if isinstance(client, httpx.AsyncClient):
                transport = client._transport or httpx.AsyncHTTPTransport()
                client._transport = AsyncOpenTelemetryTransport(
                    transport,
                    tracer_provider=tracer_provider,
                    request_hook=request_hook,
                    response_hook=response_hook,
                )
                client._is_instrumented_by_opentelemetry = True
        else:
            _logger.warning(
                "Attempting to instrument Httpx client while already instrumented"
            )
Example #6
0
def https(q, where, timeout=None, port=443, source=None, source_port=0,
          one_rr_per_rrset=False, ignore_trailing=False,
          session=None, path='/dns-query', post=True,
          bootstrap_address=None, verify=True):
    """Return the response obtained after sending a query via DNS-over-HTTPS.

    *q*, a ``dns.message.Message``, the query to send.

    *where*, a ``str``, the nameserver IP address or the full URL. If an IP
    address is given, the URL will be constructed using the following schema:
    https://<IP-address>:<port>/<path>.

    *timeout*, a ``float`` or ``None``, the number of seconds to
    wait before the query times out. If ``None``, the default, wait forever.

    *port*, a ``int``, the port to send the query to. The default is 443.

    *source*, a ``str`` containing an IPv4 or IPv6 address, specifying
    the source address.  The default is the wildcard address.

    *source_port*, an ``int``, the port from which to send the message.
    The default is 0.

    *one_rr_per_rrset*, a ``bool``. If ``True``, put each RR into its own
    RRset.

    *ignore_trailing*, a ``bool``. If ``True``, ignore trailing
    junk at end of the received message.

    *session*, an ``httpx.Client`` or ``requests.session.Session``.  If
    provided, the client/session to use to send the queries.

    *path*, a ``str``. If *where* is an IP address, then *path* will be used to
    construct the URL to send the DNS query to.

    *post*, a ``bool``. If ``True``, the default, POST method will be used.

    *bootstrap_address*, a ``str``, the IP address to use to bypass the
    system's DNS resolver.

    *verify*, a ``str``, containing a path to a certificate file or directory.

    Returns a ``dns.message.Message``.
    """

    if not have_doh:
        raise NoDOH('Neither httpx nor requests is available.')  # pragma: no cover

    _httpx_ok = _have_httpx

    wire = q.to_wire()
    (af, _, source) = _destination_and_source(where, port, source, source_port,
                                              False)
    transport_adapter = None
    transport = None
    headers = {
        "accept": "application/dns-message"
    }
    if af is not None:
        if af == socket.AF_INET:
            url = 'https://{}:{}{}'.format(where, port, path)
        elif af == socket.AF_INET6:
            url = 'https://[{}]:{}{}'.format(where, port, path)
    elif bootstrap_address is not None:
        _httpx_ok = False
        split_url = urllib.parse.urlsplit(where)
        headers['Host'] = split_url.hostname
        url = where.replace(split_url.hostname, bootstrap_address)
        if _have_requests:
            transport_adapter = HostHeaderSSLAdapter()
    else:
        url = where
    if source is not None:
        # set source port and source address
        if _have_httpx:
            if source_port == 0:
                transport = httpx.HTTPTransport(local_address=source[0])
            else:
                _httpx_ok = False
        if _have_requests:
            transport_adapter = SourceAddressAdapter(source)

    if session:
        if _have_httpx:
            _is_httpx = isinstance(session, httpx.Client)
        else:
            _is_httpx = False
        if _is_httpx and not _httpx_ok:
            raise NoDOH('Session is httpx, but httpx cannot be used for '
                        'the requested operation.')
    else:
        _is_httpx = _httpx_ok

    if not _httpx_ok and not _have_requests:
        raise NoDOH('Cannot use httpx for this operation, and '
                    'requests is not available.')

    with contextlib.ExitStack() as stack:
        if not session:
            if _is_httpx:
                session = stack.enter_context(httpx.Client(http1=True,
                                                           http2=_have_http2,
                                                           verify=verify,
                                                           transport=transport))
            else:
                session = stack.enter_context(requests.sessions.Session())

        if transport_adapter:
            session.mount(url, transport_adapter)

        # see https://tools.ietf.org/html/rfc8484#section-4.1.1 for DoH
        # GET and POST examples
        if post:
            headers.update({
                "content-type": "application/dns-message",
                "content-length": str(len(wire))
            })
            if _is_httpx:
                response = session.post(url, headers=headers, content=wire,
                                        timeout=timeout)
            else:
                response = session.post(url, headers=headers, data=wire,
                                        timeout=timeout, verify=verify)
        else:
            wire = base64.urlsafe_b64encode(wire).rstrip(b"=")
            if _is_httpx:
                wire = wire.decode()  # httpx does a repr() if we give it bytes
                response = session.get(url, headers=headers,
                                       timeout=timeout,
                                       params={"dns": wire})
            else:
                response = session.get(url, headers=headers,
                                       timeout=timeout, verify=verify,
                                       params={"dns": wire})

    # see https://tools.ietf.org/html/rfc8484#section-4.2.1 for info about DoH
    # status codes
    if response.status_code < 200 or response.status_code > 299:
        raise ValueError('{} responded with status code {}'
                         '\nResponse body: {}'.format(where,
                                                      response.status_code,
                                                      response.content))
    r = dns.message.from_wire(response.content,
                              keyring=q.keyring,
                              request_mac=q.request_mac,
                              one_rr_per_rrset=one_rr_per_rrset,
                              ignore_trailing=ignore_trailing)
    r.time = response.elapsed
    if not q.is_response(r):
        raise BadResponse
    return r
Example #7
0
# Object for storing metadata about filings that will be downloaded.
FilingMetadata = namedtuple(
    "FilingMetadata",
    [
        "accession_number",
        "full_submission_url",
        "filing_details_url",
        "filing_details_filename",
    ],
)

# Object for generating fake user-agent strings
fake = Faker()

# Specify max number of request retries
transport = httpx.HTTPTransport(retries=MAX_RETRIES)


def validate_date_format(date_format: str) -> None:
    error_msg_base = "Please enter a date string of the form YYYY-MM-DD."

    if not isinstance(date_format, str):
        raise TypeError(error_msg_base)

    try:
        datetime.strptime(date_format, DATE_FORMAT_TOKENS)
    except ValueError:
        # Re-raise with custom error message
        raise ValueError(f"Incorrect date format. {error_msg_base}")

Example #8
0
import os
import base64
import tempfile
import hashlib
import shutil
import httpx
import typing
import www_authenticate
import json

from urllib import parse


transport = httpx.HTTPTransport(retries=3)
container_httpx_client = httpx.Client(
    headers={"Accept": "application/vnd.docker.distribution.manifest.v2+json"},
    follow_redirects=True,
    transport=transport,
)

auth_httpx_client = httpx.Client(transport=transport)


class ContainerRepositoryException(BaseException):
    def __init__(self, repository: str, *args: object) -> None:
        self.repository = repository
        super().__init__(*args)


class ContainerTagNotFoundException(ContainerRepositoryException):
    def __init__(self, repository: str, tag: str, *args: object) -> None: