1"""
2raven.utils.http
3~~~~~~~~~~~~~~~~
4
5:copyright: (c) 2010-2012 by the Sentry Team, see AUTHORS for more details.
6:license: BSD, see LICENSE for more details.
7"""
8from __future__ import absolute_import
9
10import socket
11import ssl
12import sys
13
14from raven.conf import defaults
15from raven.utils.compat import urllib2, httplib
16from raven.utils.ssl_match_hostname import match_hostname
17
18
19def urlopen(url, data=None, timeout=defaults.TIMEOUT, ca_certs=None,
20            verify_ssl=False, assert_hostname=None):
21
22    class ValidHTTPSConnection(httplib.HTTPConnection):
23        default_port = httplib.HTTPS_PORT
24
25        def __init__(self, *args, **kwargs):
26            httplib.HTTPConnection.__init__(self, *args, **kwargs)
27
28        def connect(self):
29            sock = socket.create_connection(
30                address=(self.host, self.port),
31                timeout=self.timeout,
32            )
33            if self._tunnel_host:
34                self.sock = sock
35                self._tunnel()
36
37            self.sock = ssl.wrap_socket(
38                sock, ca_certs=ca_certs, cert_reqs=ssl.CERT_REQUIRED)
39
40            if assert_hostname is not None:
41                match_hostname(self.sock.getpeercert(),
42                               self.assert_hostname or self.host)
43
44    class ValidHTTPSHandler(urllib2.HTTPSHandler):
45        def https_open(self, req):
46            return self.do_open(ValidHTTPSConnection, req)
47
48    if verify_ssl:
49        handlers = [ValidHTTPSHandler]
50    else:
51        try:
52            handlers = [urllib2.HTTPSHandler(
53                context=ssl._create_unverified_context())]
54        except AttributeError:
55            handlers = []
56
57    opener = urllib2.build_opener(*handlers)
58
59    if sys.version_info < (2, 6):
60        default_timeout = socket.getdefaulttimeout()
61        socket.setdefaulttimeout(timeout)
62        try:
63            return opener.open(url, data)
64        finally:
65            socket.setdefaulttimeout(default_timeout)
66    return opener.open(url, data, timeout)
67