urllib2_build_opener.py 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
  1. """PyOpenSSL utilities including HTTPSSocket class which wraps PyOpenSSL
  2. SSL connection into a httplib-like interface suitable for use with urllib2
  3. """
  4. __author__ = "P J Kershaw"
  5. __date__ = "21/12/10"
  6. __copyright__ = "(C) 2011 Science and Technology Facilities Council"
  7. __license__ = "BSD - see LICENSE file in top-level directory"
  8. __contact__ = "Philip.Kershaw@stfc.ac.uk"
  9. __revision__ = '$Id: pyopenssl.py 7929 2011-08-16 16:39:13Z pjkersha $'
  10. import logging
  11. from urllib2 import (ProxyHandler, UnknownHandler, HTTPDefaultErrorHandler,
  12. FTPHandler, FileHandler, HTTPErrorProcessor)
  13. import sys
  14. if sys.version_info < (2, 6, 2):
  15. from ndg.httpsclient.urllib2_proxy import (HTTPHandler, OpenerDirector,
  16. HTTPRedirectHandler)
  17. else:
  18. from urllib2 import HTTPHandler, OpenerDirector, HTTPRedirectHandler
  19. from ndg.httpsclient.https import HTTPSContextHandler
  20. log = logging.getLogger(__name__)
  21. # Copied from urllib2 with modifications for ssl
  22. def build_opener(ssl_context=None, *handlers):
  23. """Create an opener object from a list of handlers.
  24. The opener will use several default handlers, including support
  25. for HTTP and FTP.
  26. If any of the handlers passed as arguments are subclasses of the
  27. default handlers, the default handlers will not be used.
  28. """
  29. import types
  30. def isclass(obj):
  31. return isinstance(obj, types.ClassType) or hasattr(obj, "__bases__")
  32. opener = OpenerDirector()
  33. default_classes = [ProxyHandler, UnknownHandler, HTTPHandler,
  34. HTTPDefaultErrorHandler, HTTPRedirectHandler,
  35. FTPHandler, FileHandler, HTTPErrorProcessor]
  36. check_classes = list(default_classes)
  37. check_classes.append(HTTPSContextHandler)
  38. skip = []
  39. for klass in check_classes:
  40. for check in handlers:
  41. if isclass(check):
  42. if issubclass(check, klass):
  43. skip.append(klass)
  44. elif isinstance(check, klass):
  45. skip.append(klass)
  46. for klass in default_classes:
  47. if klass not in skip:
  48. opener.add_handler(klass())
  49. # Add the HTTPS handler with ssl_context
  50. if HTTPSContextHandler not in skip:
  51. opener.add_handler(HTTPSContextHandler(ssl_context))
  52. for h in handlers:
  53. if isclass(h):
  54. h = h()
  55. opener.add_handler(h)
  56. return opener