Example #1
0
    def from_environ(cls, environ, **kwargs):
        """Turn an environ dict back into a builder. Any extra kwargs
        override the args extracted from the environ.

        .. versionadded:: 0.15
        """
        headers = Headers(EnvironHeaders(environ))
        out = {
            "path": environ["PATH_INFO"],
            "base_url": cls._make_base_url(
                environ["wsgi.url_scheme"],
                headers.pop("Host"),
                environ["SCRIPT_NAME"],
            ),
            "query_string": environ["QUERY_STRING"],
            "method": environ["REQUEST_METHOD"],
            "input_stream": environ["wsgi.input"],
            "content_type": headers.pop("Content-Type", None),
            "content_length": headers.pop("Content-Length", None),
            "errors_stream": environ["wsgi.errors"],
            "multithread": environ["wsgi.multithread"],
            "multiprocess": environ["wsgi.multiprocess"],
            "run_once": environ["wsgi.run_once"],
            "headers": headers,
        }
        out.update(kwargs)
        return cls(**out)
Example #2
0
 def __call__(self, environ: Any, start_response: Callable[...,
                                                           Any]) -> Any:
     if self.app.debug:
         headers = list(EnvironHeaders(environ).items())  # type: ignore
         for k, v in headers:
             print(f'{k}: {v}')
     return self.wsgi_app(environ, start_response)
Example #3
0
    def test_multiple_values(self, request_factory, request):
        request = request_factory('GET',
                                  '/',
                                  subdomain='www',
                                  query_string='a=b&a=c')

        openapi_request = FlaskOpenAPIRequest(request)

        path = {}
        query = ImmutableMultiDict([
            ('a', 'b'),
            ('a', 'c'),
        ])
        headers = EnvironHeaders(request.environ)
        cookies = {}
        assert openapi_request.parameters == {
            'path': path,
            'query': query,
            'header': headers,
            'cookie': cookies,
        }
        assert openapi_request.host_url == request.host_url
        assert openapi_request.path == request.path
        assert openapi_request.method == request.method.lower()
        assert openapi_request.path_pattern == request.path
        assert openapi_request.body == request.data
        assert openapi_request.mimetype == request.mimetype
    def test_multiple_values(self, request_factory, request):
        request = request_factory('GET',
                                  '/',
                                  subdomain='www',
                                  query_string='a=b&a=c')

        openapi_request = FlaskOpenAPIRequest(request)

        path = {}
        query = ImmutableMultiDict([
            ('a', 'b'),
            ('a', 'c'),
        ])
        headers = EnvironHeaders(request.environ)
        cookies = {}
        assert openapi_request.parameters == RequestParameters(
            path=path,
            query=query,
            header=headers,
            cookie=cookies,
        )
        assert openapi_request.method == request.method.lower()
        assert openapi_request.full_url_pattern == \
            urljoin(request.host_url, request.path)
        assert openapi_request.body == request.data
        assert openapi_request.mimetype == request.mimetype
Example #5
0
    def get_headers(self, environ=None):
        headers = []
        if environ:
            headers = list(EnvironHeaders(environ))

        headers.append(('Location', self.location))

        return headers
Example #6
0
def test_environ_headers_counts():
    """Ensure that the EnvironHeaders count correctly."""
    # this happens in multiple WSGI servers because they
    # use a vary naive way to convert the headers;
    broken_env = {
        'HTTP_CONTENT_TYPE': 'text/html',
        'CONTENT_TYPE': 'text/html',
        'HTTP_CONTENT_LENGTH': '0',
        'CONTENT_LENGTH': '0',
        'HTTP_ACCEPT': '*',
        'wsgi.version': (1, 0)
    }
    headers = EnvironHeaders(broken_env)
    assert headers
    assert len(headers) == 3
    assert sorted(headers) == [('Accept', '*'), ('Content-Length', '0'),
                               ('Content-Type', 'text/html')]
    assert not EnvironHeaders({'wsgi.version': (1, 0)})
    assert len(EnvironHeaders({'wsgi.version': (1, 0)})) == 0
Example #7
0
def test_immutable_structures():
    """Test immutable structures"""
    l = ImmutableList([1, 2, 3])
    assert_raises(TypeError, l.__delitem__, 0)
    assert_raises(TypeError, l.__delslice__, 0, 1)
    assert_raises(TypeError, l.__iadd__, [1, 2])
    assert_raises(TypeError, l.__setitem__, 0, 1)
    assert_raises(TypeError, l.__setslice__, 0, 1, [2, 3])
    assert_raises(TypeError, l.append, 42)
    assert_raises(TypeError, l.insert, 0, 32)
    assert_raises(TypeError, l.pop)
    assert_raises(TypeError, l.extend, [2, 3])
    assert_raises(TypeError, l.reverse)
    assert_raises(TypeError, l.sort)
    assert l == [1, 2, 3]

    d = ImmutableDict(foo=23, bar=42)
    assert_raises(TypeError, d.setdefault, 'baz')
    assert_raises(TypeError, d.update, {2: 3})
    assert_raises(TypeError, d.popitem)
    assert_raises(TypeError, d.__delitem__, 'foo')
    assert_raises(TypeError, d.clear)
    assert d == dict(foo=23, bar=42)
    d = ImmutableDict.fromkeys([1, 2])
    assert d[1] == d[2] == None

    d = ImmutableMultiDict(d)
    assert_raises(TypeError, d.add, 'fuss', 44)
    assert_raises(TypeError, d.popitemlist)
    assert_raises(TypeError, d.poplist, 'foo')
    assert_raises(TypeError, d.setlist, 'tadaa', [1, 2])
    assert_raises(TypeError, d.setlistdefault, 'tadaa')
    d = ImmutableMultiDict.fromkeys([1, 2])
    assert d[1] == d[2] == None

    d = EnvironHeaders({'HTTP_X_FOO': 'test'})
    assert_raises(TypeError, d.__delitem__, 0)
    assert_raises(TypeError, d.add, 42)
    assert_raises(TypeError, d.pop, 'x-foo')
    assert_raises(TypeError, d.popitem)
    assert_raises(TypeError, d.setdefault, 'foo', 42)
    assert dict(d.items()) == {'X-Foo': 'test'}
    assert_raises(TypeError, d.copy)
    def test_url_rule(self, request_factory, request):
        request = request_factory('GET', '/browse/12/', subdomain='kb')

        openapi_request = FlaskOpenAPIRequest(request)

        path = {'id': 12}
        query = ImmutableMultiDict([])
        headers = EnvironHeaders(request.environ)
        cookies = {}
        assert openapi_request.parameters == RequestParameters(
            path=path,
            query=query,
            header=headers,
            cookie=cookies,
        )
        assert openapi_request.method == request.method.lower()
        assert openapi_request.full_url_pattern == \
            urljoin(request.host_url, '/browse/{id}/')
        assert openapi_request.body == request.data
        assert openapi_request.mimetype == request.mimetype
Example #9
0
    def test_url_rule(self, request_factory, request):
        request = request_factory('GET', '/browse/12/', subdomain='kb')

        openapi_request = FlaskOpenAPIRequest(request)

        path = {'id': 12}
        query = ImmutableMultiDict([])
        headers = EnvironHeaders(request.environ)
        cookies = {}
        assert openapi_request.parameters == {
            'path': path,
            'query': query,
            'header': headers,
            'cookie': cookies,
        }
        assert openapi_request.host_url == request.host_url
        assert openapi_request.path == request.path
        assert openapi_request.method == request.method.lower()
        assert openapi_request.path_pattern == request.url_rule.rule
        assert openapi_request.body == request.data
        assert openapi_request.mimetype == request.mimetype
Example #10
0
    def test_simple(self, request_factory, request):
        request = request_factory('GET', '/', subdomain='www')

        openapi_request = FlaskOpenAPIRequest(request)

        path = {}
        query = ImmutableMultiDict([])
        headers = EnvironHeaders(request.environ)
        cookies = {}
        assert openapi_request.parameters == RequestParameters(
            path=path,
            query=query,
            header=headers,
            cookie=cookies,
        )
        assert openapi_request.host_url == request.host_url
        assert openapi_request.path == request.path
        assert openapi_request.method == request.method.lower()
        assert openapi_request.path_pattern == request.path
        assert openapi_request.body == request.data
        assert openapi_request.mimetype == request.mimetype
Example #11
0
 def __call__(self, environ, start_response):
     if self.enabled:
         self.headers = EnvironHeaders(environ)
         should_log = True
         if self.pi_filter is not None and self.pi_filter not in environ[
                 'PATH_INFO']:
             should_log = False
         if self.rm_filter is not None and environ['REQUEST_METHOD'].lower(
         ) not in [x.lower() for x in tolist(self.rm_filter)]:
             should_log = False
         if should_log:
             wsgi_input = self.replace_wsgi_input(environ)
             fname = '%s_%s' % (time.time(), randchars())
             fh = open(path.join(self.log_dir, fname), 'wb+')
             try:
                 fh.write(pformat(environ))
                 fh.write('\n')
                 fh.write(wsgi_input.read())
                 wsgi_input.seek(0)
             finally:
                 fh.close()
     return self.application(environ, start_response)
Example #12
0
 def build(cls, environ: WSGIEnviron):
     return cls(EnvironHeaders(environ))
Example #13
0
 def in_headers(self):
     return EnvironHeaders(self.environ)
Example #14
0
        def application(environ, start_response):
            headers = list(EnvironHeaders(environ).items())
            headers[:] = [(k, v) for k, v in headers
                          if not is_hop_by_hop_header(k) and k.lower() not in (
                              'content-length', 'host')]
            headers.append(('Connection', 'close'))
            if opts['host'] == '<auto>':
                headers.append(('Host', target.ascii_host))
            elif opts['host'] is None:
                headers.append(('Host', environ['HTTP_HOST']))
            else:
                headers.append(('Host', opts['host']))
            headers.extend(opts['headers'].items())

            remote_path = path
            if opts['remove_prefix']:
                remote_path = '%s/%s' % (target.path.rstrip('/'),
                                         remote_path[len(prefix):].lstrip('/'))

            content_length = environ.get('CONTENT_LENGTH')
            chunked = False
            if content_length not in ('', None):
                headers.append(('Content-Length', content_length))
            elif content_length is not None:
                headers.append(('Transfer-Encoding', 'chunked'))
                chunked = True

            try:
                if target.scheme == 'http':
                    con = httplib.HTTPConnection(target.ascii_host,
                                                 target.port or 80,
                                                 timeout=self.timeout)
                elif target.scheme == 'https':
                    con = httplib.HTTPSConnection(target.ascii_host,
                                                  target.port or 443,
                                                  timeout=self.timeout,
                                                  context=opts['ssl_context'])
                con.connect()
                con.putrequest(environ['REQUEST_METHOD'],
                               url_quote(remote_path),
                               skip_host=True)

                for k, v in headers:
                    if k.lower() == 'connection':
                        v = 'close'
                    con.putheader(k, v)
                con.endheaders()

                stream = get_input_stream(environ)
                while 1:
                    data = stream.read(self.chunk_size)
                    if not data:
                        break
                    if chunked:
                        con.send(b'%x\r\n%s\r\n' % (len(data), data))
                    else:
                        con.send(data)

                resp = con.getresponse()
            except socket.error:
                from werkzeug.exceptions import BadGateway
                return BadGateway()(environ, start_response)

            start_response(
                '%d %s' % (resp.status, resp.reason),
                [(k.title(), v)
                 for k, v in resp.getheaders() if not is_hop_by_hop_header(k)])

            def read():
                while 1:
                    try:
                        data = resp.read(self.chunk_size)
                    except socket.error:
                        break
                    if not data:
                        break
                    yield data

            return read()
Example #15
0
    def __call__(self, environ, start_response):
        # this middleware only used for (/call/<dbot_address>/<path:uri>
        url_map = Map(
            [Rule('/call/<dbot_address>/<path:uri>', endpoint='proxy')])
        urls = url_map.bind_to_environ(environ)
        try:
            endpoint, kwargs = urls.match()
        except (NotFound, MethodNotAllowed) as e:
            return self.app(environ, start_response)

        try:
            method = environ['REQUEST_METHOD']
            if method == 'OPTIONS':
                # if CORS first request, return response
                return self.app(environ, start_response)

            dbot_address = kwargs['dbot_address']
            dbot_address = to_checksum_address(dbot_address)
            uri = kwargs['uri']
            dbot_service = dbot.get_service(dbot_address)
            if not dbot_service:
                raise InvalidUsage('dbot address not found', status_code=404)

            # Ensure the URI is an approved API endpoint, else abort
            price, proxy_uri = _get_endpoint(dbot_service, uri, method)
            if price < 0:
                logger.error(
                    "({}: {}) is not an approved API endpoint.".format(
                        method, uri))
                raise InvalidUsage(
                    "({}: {}) is not an approved API endpoint.".format(
                        method, uri),
                    status_code=404)

            environ['PATH_INFO'] = '/call/{}/{}'.format(
                dbot_address, remove_slash_prefix(proxy_uri))
            if price > 0:
                # Balance Proof check
                ret, code, headers = dbot_service.paywall.access(
                    price, EnvironHeaders(environ))
                if code != 200:
                    return _make_response(environ, start_response, ret, code,
                                          headers)

            logger.info("Balance Proof check is ok.")
            middleware_cls = dbot_service.middleware
            if middleware_cls:
                # load dbot's middleware in runtime
                logger.info('init middleware({}) for dbot({})'.format(
                    middleware_cls, dbot_address))
                middleware = middleware_cls(self.app)
                return middleware(environ, start_response)
            else:
                return self.app(environ, start_response)
        except InvalidUsage as e:
            logger.error('{}'.format(e.message))
            return _make_response(environ, start_response,
                                  '{}'.format(e.to_dict()), e.status_code)
        except Exception as e:
            logger.error('{}'.format(e))
            return _make_response(environ, start_response, '{}'.format(e), 500)
Example #16
0
        def application(environ, start_response):
            headers = list(EnvironHeaders(environ).items())
            headers[:] = [(k, v) for k, v in headers
                          if not is_hop_by_hop_header(k) and k.lower() not in (
                              "content-length", "host")]
            headers.append(("Connection", "close"))
            if opts["host"] == "<auto>":
                headers.append(("Host", target.ascii_host))
            elif opts["host"] is None:
                headers.append(("Host", environ["HTTP_HOST"]))
            else:
                headers.append(("Host", opts["host"]))
            headers.extend(opts["headers"].items())

            remote_path = path
            if opts["remove_prefix"]:
                remote_path = "%s/%s" % (
                    target.path.rstrip("/"),
                    remote_path[len(prefix):].lstrip("/"),
                )

            content_length = environ.get("CONTENT_LENGTH")
            chunked = False
            if content_length not in ("", None):
                headers.append(("Content-Length", content_length))
            elif content_length is not None:
                headers.append(("Transfer-Encoding", "chunked"))
                chunked = True

            try:
                if target.scheme == "http":
                    con = httplib.HTTPConnection(target.ascii_host,
                                                 target.port or 80,
                                                 timeout=self.timeout)
                elif target.scheme == "https":
                    con = httplib.HTTPSConnection(
                        target.ascii_host,
                        target.port or 443,
                        timeout=self.timeout,
                        context=opts["ssl_context"],
                    )
                con.connect()
                con.putrequest(environ["REQUEST_METHOD"],
                               url_quote(remote_path),
                               skip_host=True)

                for k, v in headers:
                    if k.lower() == "connection":
                        v = "close"
                    con.putheader(k, v)
                con.endheaders()

                stream = get_input_stream(environ)
                while 1:
                    data = stream.read(self.chunk_size)
                    if not data:
                        break
                    if chunked:
                        con.send(b"%x\r\n%s\r\n" % (len(data), data))
                    else:
                        con.send(data)

                resp = con.getresponse()
            except socket.error:
                from werkzeug.exceptions import BadGateway

                return BadGateway()(environ, start_response)

            start_response(
                "%d %s" % (resp.status, resp.reason),
                [(k.title(), v)
                 for k, v in resp.getheaders() if not is_hop_by_hop_header(k)],
            )

            def read():
                while 1:
                    try:
                        data = resp.read(self.chunk_size)
                    except socket.error:
                        break
                    if not data:
                        break
                    yield data

            return read()
 def __call__(self, environ, start_response):
     if self.app.debug:
         headers = list(EnvironHeaders(environ).items())
         for k, v in headers:
             print(f'{k}: {v}')
     return self.wsgi_app(environ, start_response)