Skip to content

Commit

Permalink
feat: Support unix sockets for urllib3
Browse files Browse the repository at this point in the history
  • Loading branch information
mattrobenolt committed Oct 31, 2018
1 parent e40fae8 commit 9a9be34
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 10 deletions.
35 changes: 35 additions & 0 deletions src/sentry/net/http.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from __future__ import absolute_import

import socket
from socket import error as SocketError, timeout as SocketTimeout

from requests import Session as _Session
Expand All @@ -8,6 +9,7 @@
from urllib3.connection import HTTPConnection, HTTPSConnection
from urllib3.exceptions import NewConnectionError, ConnectTimeoutError
from urllib3.poolmanager import PoolManager
from urllib3.util.connection import _set_socket_options

from sentry import VERSION as SENTRY_VERSION
from sentry.net.socket import safe_create_connection
Expand Down Expand Up @@ -149,3 +151,36 @@ def __init__(self):
adapter = BlacklistAdapter()
self.mount('https://', adapter)
self.mount('http://', adapter)


class UnixHTTPConnection(HTTPConnection):
default_socket_options = []

def __init__(self, host, **kwargs):
# We're using the `host` as the socket path, but
# urllib3 uses this host as the Host header by default.
# If we send along the socket path as a Host header, this is
# never what you want and would typically be malformed value.
# So we fake this by sending along `localhost` by default as
# other libraries do.
self.socket_path = host
super(UnixHTTPConnection, self).__init__(host='localhost', **kwargs)

def _new_conn(self):
sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)

# If provided, set socket level options before connecting.
_set_socket_options(sock, self.socket_options)

if self.timeout is not socket._GLOBAL_DEFAULT_TIMEOUT:
sock.settimeout(self.timeout)
sock.connect(self.socket_path)
return sock


class UnixHTTPConnectionPool(HTTPConnectionPool):
ConnectionCls = UnixHTTPConnection

def __str__(self):
return '%s(host=%r)' % (type(self).__name__,
self.host)
25 changes: 15 additions & 10 deletions src/sentry/nodestore/riak/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,11 @@
from requests.certs import where as ca_certs
from six.moves.urllib.parse import urlencode, quote_plus
from urllib3 import HTTPConnectionPool, HTTPSConnectionPool
from urllib3.connection import HTTPConnection
from urllib3.exceptions import HTTPError

from sentry.net.http import UnixHTTPConnectionPool


DEFAULT_NODES = ({'host': '127.0.0.1', 'port': 8098}, )


Expand Down Expand Up @@ -243,11 +245,6 @@ def create_pool(self, host):
if 'basic_auth' in host:
options['headers']['authorization'] = encode_basic_auth(host['basic_auth'])

if self.tcp_keepalive:
options['socket_options'] = HTTPConnection.default_socket_options + [
(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1),
]

# Support backwards compatibility with `http_port`
if 'http_port' in host:
import warnings
Expand All @@ -257,10 +254,12 @@ def create_pool(self, host):
addr = host.get('host', '127.0.0.1')
port = int(host.get('port', 8098))
secure = host.get('secure', False)
if not secure:
connection_cls = HTTPConnectionPool
if addr[:1] == '/':
pool_cls = UnixHTTPConnectionPool
elif not secure:
pool_cls = HTTPConnectionPool
else:
connection_cls = HTTPSConnectionPool
pool_cls = HTTPSConnectionPool
verify_ssl = host.get('verify_ssl', False)
if verify_ssl:
options.extend(
Expand All @@ -269,7 +268,13 @@ def create_pool(self, host):
'ca_certs': host.get('ca_certs', ca_certs())
}
)
return connection_cls(addr, port, **options)

if self.tcp_keepalive:
options['socket_options'] = pool_cls.ConnectionCls.default_socket_options + [
(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1),
]

return pool_cls(addr, port, **options)

def urlopen(self, method, path, headers=None, **kwargs):
"""
Expand Down

0 comments on commit 9a9be34

Please sign in to comment.