¿Es posible anular las opciones de socket predeterminadas en las solicitudes?

He escrito un cliente muy simple para una API de descanso utilizando la excelente biblioteca de solicitudes para python. Todo funciona a la perfección. Ejecuto el cliente a través de un equilibrador de carga, que detecta las conexiones tcp inactivas y las mata. Me gustaría que mi cliente use algunas opciones diferentes de mantenimiento de TCP que sean las predeterminadas en mi plataforma (Linux). Pero no veo una manera fácil de decirle a la biblioteca de sockets que me gustaría elegir algunas opciones predeterminadas para sockets nuevos.

Cuando se usa socket.create_connection directamente, esto es bastante fácil de hacer con un decorador, pero no tengo idea de cómo haría que esa llamada decorada esté disponible cuando la llamada real esté enterrada en alguna biblioteca de terceros, como es el caso con las solicitudes.

gracias por adelantado

requests utiliza urllib3 , que utiliza el http.client la biblioteca estándar (o httplib , para 2.x), que llama socket.create_connection , todo sin ningún lugar para enganchar cosas.

Entonces, o bien tendrás que bifurcar una de esas bibliotecas, o emparejarla sobre la marcha.

El lugar más simple para hacerlo es probablemente en http.client.connect , ya que es una envoltura trivial alrededor de socket.create_connection que se puede intercambiar fácilmente:

 orig_connect = http.client.HTTPConnection.connect def monkey_connect(self): orig_connect(self) self.sock.setsockopt(…) http.client.HTTPConnection.connect = monkey_connect 

Si está en la versión 2.x, es probable que sea tan simple como usar httplib lugar del http.client anterior, pero es posible que desee verificarlo.

Las versiones más nuevas de urllib3 (desde la urllib3 1.8.3, lanzada el 2014-06-23) admiten las opciones de configuración de socket.

Puede configurar estas opciones a partir de las requests (desde la versión 2.4.0, lanzada el 2014-08-29) creando un adaptador personalizado:

 class HTTPAdapterWithSocketOptions(requests.adapters.HTTPAdapter): def __init__(self, *args, **kwargs): self.socket_options = kwargs.pop("socket_options", None) super(HTTPAdapterWithSocketOptions, self).__init__(*args, **kwargs) def init_poolmanager(self, *args, **kwargs): if self.socket_options is not None: kwargs["socket_options"] = self.socket_options super(HTTPAdapterWithSocketOptions, self).init_poolmanager(*args, **kwargs) 

Luego puede montar este adaptador en las sesiones que necesitan opciones de socket personalizadas (por ejemplo, configurando SO_KEEPALIVE ):

 adapter = HTTPAdapterWithSocketOptions(socket_options=[(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)]) s = requests.session() s.mount("http://", adapter) s.mount("https://", adapter)