Example #1
0
    def _make_session(hostname,
                      prefix='http://',
                      ssl_adapter=None,
                      test_app_client='requests',
                      client_cert=None,
                      client_key=None):
        """
        Create a pyriform session (with HostProxy) to prefix + hostname.

        :param hostname: hostname for the wsgi_server fixture
        :param prefix: URL prefix (or protocol or scheme);
        :param ssl_adapter: replace, for the life of the current test, the
               wsgi_server's ssl_adapter
        :param test_app_client: the client module used by the
               wsgiproxy.HostProxy for TestApp to proxy to a real URL.
               The supported clients are ['requests', 'httplib', 'urllib3']
        :param client_cert: the path to the client SSL certificate or None
               (for mutual authentication)
        :param client_key: the path to the client private key or None
        :return: pyriform session linked to a TestApp object that proxies
                 requests (for the given prefix) to the wsgi_server using the
                 URL prefix, localhost, and the bound port of the wsgi_server
        """
        scheme = 'http'
        assert prefix.startswith('http')
        if prefix.startswith('https'):
            assert ssl_adapter is not None
            scheme = 'https'

        wsgi_server.ssl_adapter = ssl_adapter

        app = TestApp('{}://{}:{}#{}'.format(scheme, hostname,
                                             wsgi_server.bind_addr[1],
                                             test_app_client))

        my_session = requests.Session()
        my_session.verify = ssl_adapter.certificate_chain
        if client_cert is not None and client_key is not None:
            my_session.cert = (client_cert, client_key)

        # A couple of issues:
        # The constructor for WebTest.TestApp doesn't have a way to pass args
        # to the wsgiproxy.HostProxy constructor
        # The pyriform requests adaptor eats the request verify and cert args
        # as it isn't trivial to pass such args to an instant of
        # WebTest.TestApp
        if scheme == 'https' and test_app_client == 'requests':
            from wsgiproxy import HostProxy
            url = '{}://localhost:{}'.format(scheme, wsgi_server.bind_addr[1])
            app.app = HostProxy(url,
                                client='requests',
                                verify=my_session.verify,
                                cert=my_session.cert)
        elif scheme == 'https' and test_app_client == 'httplib':
            # Note, in order for this to work, wsgiproxy's httplib wrapper
            # needs some work to split the client args into HTTPSConnection
            # args and HTTPSConnection request args.
            from wsgiproxy import HostProxy
            import ssl
            client_ctx = ssl.create_default_context(
                ssl.Purpose.SERVER_AUTH, cafile=ssl_adapter.certificate_chain)
            if client_cert is not None and client_key is not None:
                client_ctx.load_cert_chain(certfile=client_cert,
                                           keyfile=client_key)
            client_ctx.check_hostname = True
            url = '{}://localhost:{}'.format(scheme, wsgi_server.bind_addr[1])
            app.app = HostProxy(url, client='httplib', context=client_ctx)

        my_session.mount(prefix, pyriform.WSGIAdapter(app))
        return my_session