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
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()
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)
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" )
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
# 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}")
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: