requests metodo hacer con biblioteca python http dns urllib python-requests

metodo - Biblioteca de ''solicitudes'' de Python: ¿definir un DNS específico?



requests python https (2)

Debería ver TransportAdapters , incluido el código fuente. La documentación sobre ellos no es buena, pero dan acceso de bajo nivel a mucha de la funcionalidad descrita en RFC 2818 y RFC 6125 . En particular, esos documentos fomentan (¿requieren?) El código del lado del cliente para soportar DNS específicos de la aplicación con el fin de verificar los certificados ''CommonName y SubjectAltName. El argumento de palabra clave que necesita en esas llamadas es "assert_hostname". A continuación se explica cómo configurarlo con la biblioteca de solicitudes:

from requests import Session, HTTPError from requests.adapters import HTTPAdapter, DEFAULT_POOLSIZE, DEFAULT_RETRIES, DEFAULT_POOLBLOCK class DNSResolverHTTPSAdapter(HTTPAdapter): def __init__(self, common_name, host, pool_connections=DEFAULT_POOLSIZE, pool_maxsize=DEFAULT_POOLSIZE, max_retries=DEFAULT_RETRIES, pool_block=DEFAULT_POOLBLOCK): self.__common_name = common_name self.__host = host super(DNSResolverHTTPSAdapter, self).__init__(pool_connections=pool_connections, pool_maxsize=pool_maxsize, max_retries=max_retries, pool_block=pool_block) def get_connection(self, url, proxies=None): redirected_url = url.replace(self.__common_name, self.__host) return super(DNSResolverHTTPSAdapter, self).get_connection(redirected_url, proxies=proxies) def init_poolmanager(self, connections, maxsize, block=DEFAULT_POOLBLOCK, **pool_kwargs): pool_kwargs[''assert_hostname''] = self.__common_name super(DNSResolverHTTPSAdapter, self).init_poolmanager(connections, maxsize, block=block, **pool_kwargs) common_name = ''SuperSecretSarahServer'' host = ''192.168.33.51'' port = 666 base_url = ''https://{}:{}/api/''.format(common_name, port) my_session = Session() my_session.mount(self.base_url.lower(), DNSResolverHTTPSAdapter(common_name, host)) user_name = ''sarah'' url = ''{}users/{}''.format(self.base_url, user_name) default_response_kwargs = { ''auth'': (NAME, PASSWORD), ''headers'': {''Content-Type'': ''application/json''}, ''verify'': SSL_OPTIONS[''ca_certs''], ''cert'': (SSL_OPTIONS[''certfile''], SSL_OPTIONS[''keyfile'']) } response = my_session.get(url, **default_response_kwargs)

Utilizo common_name para el nombre que se espera que esté en el certificado y cómo su código hará referencia a la máquina deseada. Utilizo el host para un nombre reconocido por el mundo externo: FQDN, IP, entrada de DNS, ... Por supuesto, el diccionario SSL_OPTIONS (en mi ejemplo) debe listar los nombres de archivo / clave apropiados en su máquina. (Además, NAME y PASSWORD deberían resolver corregir las cadenas).

En mi proyecto estoy manejando todas las solicitudes HTTP con la biblioteca de requests python.

Ahora, necesito consultar el servidor http utilizando un DNS específico: hay dos entornos, cada uno con su propio DNS, y los cambios se realizan de forma independiente.

Por lo tanto, cuando se ejecuta el código, debe usar DNS específico para el entorno y no el DNS especificado en mi conexión a Internet.

¿Alguien ha intentado esto usando python-requests? Solo he encontrado una solución para urllib2:
https://stackoverflow.com/questions/4623090/python-set-custom-dns-server-for-urllib-requests


requests utiliza urllib3 , que en última instancia utiliza httplib.HTTPConnection también, por lo que las técnicas de https://.com/questions/4623090/python-set-custom-dns-server-for-urllib-requests (ahora eliminadas, meramente vinculado a Tell urllib2 para usar DNS personalizado ) aún se aplican, hasta cierto punto.

El módulo urllib3.connection subclasifica httplib.HTTPConnection bajo el mismo nombre, después de haber reemplazado el método .connect() con uno que llama a self._new_conn . A su vez, esto delega en urllib3.util.connection.create_connection() . Quizás sea más fácil parchar esa función:

from urllib3.util import connection _orig_create_connection = connection.create_connection def patched_create_connection(address, *args, **kwargs): """Wrap urllib3''s create_connection to resolve the name elsewhere""" # resolve hostname to an ip address; use your own # resolver here, as otherwise the system resolver will be used. host, port = address hostname = your_dns_resolver(host) return _orig_create_connection((hostname, port), *args, **kwargs) connection.create_connection = patched_create_connection

y proporcionaría su propio código para resolver la parte de host de la dirección en una dirección IP en lugar de confiar en la llamada connection.create_connection() (que ajusta socket.create_connection() ) para resolver el nombre de host por usted.

Al igual que todos los parches, tenga cuidado de que el código no haya cambiado significativamente en lanzamientos posteriores; el parche aquí fue creado contra urllib3 versión 1.21.1. pero debería funcionar para versiones tan atrás como 1.9.

Tenga en cuenta que esta respuesta se volvió a escribir para que funcione con las versiones más recientes de urllib3 , que han agregado una ubicación de parche mucho más conveniente. Consulte el historial de edición para el método anterior, aplicable a la versión <1.9, como un parche para la versión vendida de urllib3 lugar de una instalación independiente.