Example #1
0
def test_limited_stream_disconnection():
    io = BytesIO(b"A bit of content")

    # disconnect detection on out of bytes
    stream = wsgi.LimitedStream(io, 255)
    with pytest.raises(ClientDisconnected):
        stream.read()

    # disconnect detection because file close
    io = BytesIO(b"x" * 255)
    io.close()
    stream = wsgi.LimitedStream(io, 255)
    with pytest.raises(ClientDisconnected):
        stream.read()
Example #2
0
    def test_limited_stream_disconnection(self):
        io = BytesIO(b'A bit of content')

        # disconnect detection on out of bytes
        stream = wsgi.LimitedStream(io, 255)
        with self.assert_raises(ClientDisconnected):
            stream.read()

        # disconnect detection because file close
        io = BytesIO(b'x' * 255)
        io.close()
        stream = wsgi.LimitedStream(io, 255)
        with self.assert_raises(ClientDisconnected):
            stream.read()
def handle_request(app, event, context):
    if u"multiValueHeaders" in event:
        headers = Headers(event["multiValueHeaders"])
    else:
        headers = Headers(event["headers"])

    strip_stage_path = os.environ.get("STRIP_STAGE_PATH", "").lower().strip() in [
        "yes",
        "y",
        "true",
        "t",
        "1",
    ]
    if u"apigw.tencentcs.com" in headers.get(u"Host", u"") and not strip_stage_path:
        script_name = "/{}".format(event["requestContext"].get(u"stage", ""))
    else:
        script_name = ""

    path_info = event["path"]
    base_path = os.environ.get("API_GATEWAY_BASE_PATH")
    print(base_path)
    if base_path:
        script_name = "/" + base_path

        if path_info.startswith(script_name):
            path_info = path_info[len(script_name) :] or "/"

    if u"body" in event:
        body = event[u"body"] or ""
    else:
        body = ""

    if event.get("isBase64Encoded", False):
        body = base64.b64decode(body)
    if isinstance(body, string_types):
        body = to_bytes(body, charset="utf-8")

    environ = {
        "CONTENT_LENGTH": str(len(body)),
        "CONTENT_TYPE": headers.get(u"Content-Type", ""),
        "PATH_INFO": url_unquote(path_info),
        "QUERY_STRING": encode_query_string(event),
        "REMOTE_ADDR": event["requestContext"]
        .get(u"identity", {})
        .get(u"sourceIp", ""),
        "REMOTE_USER": event["requestContext"]
        .get(u"authorizer", {})
        .get(u"principalId", ""),
        "REQUEST_METHOD": event["httpMethod"],
        "SCRIPT_NAME": script_name,
        "SERVER_NAME": headers.get(u"Host", "Serverless"),
        "SERVER_PORT": headers.get(u"X-Forwarded-Port", "80"),
        "SERVER_PROTOCOL": "HTTP/1.1",
        "wsgi.errors": sys.stderr,
        "wsgi.input": BytesIO(body),
        "wsgi.multiprocess": False,
        "wsgi.multithread": False,
        "wsgi.run_once": False,
        "wsgi.url_scheme": headers.get(u"X-Forwarded-Proto", "http"),
        "wsgi.version": (1, 0),
        "serverless.authorizer": event["requestContext"].get(u"authorizer"),
        "serverless.event": event,
        "serverless.context": context,
        "API_GATEWAY_AUTHORIZER": event["requestContext"].get(u"authorizer"),
        "event": event,
        "context": context,
    }

    for key, value in environ.items():
        if isinstance(value, string_types):
            environ[key] = wsgi_encoding_dance(value)

    for key, value in headers.items():
        key = "HTTP_" + key.upper().replace("-", "_")
        if key not in ("HTTP_CONTENT_TYPE", "HTTP_CONTENT_LENGTH"):
            environ[key] = value

    response = Response.from_app(app, environ)

    returndict = {u"statusCode": response.status_code}

    if u"multiValueHeaders" in event:
        returndict["multiValueHeaders"] = group_headers(response.headers)
    else:
        returndict["headers"] = split_headers(response.headers)

    if event.get("requestContext").get("elb"):
        # If the request comes from ALB we need to add a status description
        returndict["statusDescription"] = u"%d %s" % (
            response.status_code,
            HTTP_STATUS_CODES[response.status_code],
        )

    if response.data:
        mimetype = response.mimetype or "text/plain"
        if (
            mimetype.startswith("text/") or mimetype in TEXT_MIME_TYPES
        ) and not response.headers.get("Content-Encoding", ""):
            returndict["body"] = response.get_data(as_text=True)
            returndict["isBase64Encoded"] = False
        else:
            returndict["body"] = base64.b64encode(response.data).decode("utf-8")
            returndict["isBase64Encoded"] = True

    return returndict
Example #4
0
def handle_request(app, event, context):
    if event.get("source") in ["aws.events", "serverless-plugin-warmup"]:
        return {}

    headers = Headers(event[u"headers"])

    if u"amazonaws.com" in headers.get(u"Host", u""):
        script_name = "/{}".format(event[u"requestContext"].get(u"stage", ""))
    else:
        script_name = ""

    # If a user is using a custom domain on API Gateway, they may have a base
    # path in their URL. This allows us to strip it out via an optional
    # environment variable.
    path_info = event[u"path"]
    base_path = os.environ.get("API_GATEWAY_BASE_PATH", "")
    if base_path:
        script_name = "/" + base_path

        if path_info.startswith(script_name):
            path_info = path_info[len(script_name):]

    body = event[u"body"] or ""
    if event.get("isBase64Encoded", False):
        body = base64.b64decode(body)
    if isinstance(body, string_types):
        body = to_bytes(body, charset="utf-8")
    print(event)
    environ = {
        "CONTENT_LENGTH":
        str(len(body)),
        "CONTENT_TYPE":
        headers.get(u"Content-Type", ""),
        "PATH_INFO":
        path_info,
        "QUERY_STRING":
        url_encode(event.get(u"queryStringParameters") or {}),
        "REMOTE_ADDR":
        event[u"requestContext"].get(u"identity", {}).get(u"sourceIp", ""),
        "REMOTE_USER":
        event[u"requestContext"].get(u"authorizer",
                                     {}).get(u"principalId", ""),
        "REQUEST_METHOD":
        event[u"httpMethod"],
        "SCRIPT_NAME":
        script_name,
        "SERVER_NAME":
        headers.get(u"Host", "lambda"),
        "SERVER_PORT":
        headers.get(u"X-Forwarded-Port", "80"),
        "SERVER_PROTOCOL":
        "HTTP/1.1",
        "wsgi.errors":
        sys.stderr,
        "wsgi.input":
        BytesIO(body),
        "wsgi.multiprocess":
        False,
        "wsgi.multithread":
        False,
        "wsgi.run_once":
        False,
        "wsgi.url_scheme":
        headers.get(u"X-Forwarded-Proto", "http"),
        "wsgi.version": (1, 0),
        "serverless.authorizer":
        event[u"requestContext"].get(u"authorizer"),
        "serverless.event":
        event,
        "serverless.context":
        context,
        # TODO: Deprecate the following entries, as they do not comply with the WSGI
        # spec. For custom variables, the spec says:
        #
        #   Finally, the environ dictionary may also contain server-defined variables.
        #   These variables should be named using only lower-case letters, numbers, dots,
        #   and underscores, and should be prefixed with a name that is unique to the
        #   defining server or gateway.
        "API_GATEWAY_AUTHORIZER":
        event[u"requestContext"].get(u"authorizer"),
        "event":
        event,
        "context":
        context,
    }

    for key, value in environ.items():
        if isinstance(value, string_types):
            environ[key] = wsgi_encoding_dance(value)

    for key, value in headers.items():
        key = "HTTP_" + key.upper().replace("-", "_")
        if key not in ("HTTP_CONTENT_TYPE", "HTTP_CONTENT_LENGTH"):
            environ[key] = value

    response = Response.from_app(app, environ)

    returndict = {
        u"statusCode": response.status_code,
        u"headers": split_headers(response.headers),
    }

    if event.get("requestContext").get("elb"):
        # If the request comes from ALB we need to add a status description
        returndict["statusDescription"] = u"%d %s" % (
            response.status_code,
            HTTP_STATUS_CODES[response.status_code],
        )

    if response.data:
        mimetype = response.mimetype or "text/plain"
        if (mimetype.startswith("text/")
                or mimetype in TEXT_MIME_TYPES) and not response.headers.get(
                    "Content-Encoding", ""):
            returndict["body"] = response.get_data(as_text=True)
            returndict["isBase64Encoded"] = False
        else:
            returndict["body"] = base64.b64encode(
                response.data).decode("utf-8")
            returndict["isBase64Encoded"] = True

    return returndict
Example #5
0
def handler(event, context):
    headers = Headers(event[u'headers'])

    if headers.get(u'Host', u'').endswith(u'.amazonaws.com'):
        script_name = '/{}'.format(event[u'requestContext'].get(u'stage', ''))
    else:
        script_name = ''

    # If a user is using a custom domain on API Gateway, they may have a base
    # path in their URL. This allows us to strip it out via an optional
    # environment variable.
    path_info = event[u'path']
    base_path = os.environ.get('API_GATEWAY_BASE_PATH', '')
    if base_path:
        script_name = '/' + base_path

        if path_info.startswith(script_name):
            path_info = path_info[len(script_name):]

    body = event[u'body'] or ''
    if event.get('isBase64Encoded', False):
        body = base64.b64decode(body)
    if isinstance(body, string_types):
        body = to_bytes(body)

    environ = {
        'API_GATEWAY_AUTHORIZER':
        event[u'requestContext'].get(u'authorizer', None),
        'CONTENT_LENGTH':
        str(len(body)),
        'CONTENT_TYPE':
        headers.get(u'Content-Type', ''),
        'PATH_INFO':
        path_info,
        'QUERY_STRING':
        url_encode(event.get(u'queryStringParameters', None) or {}),
        'REMOTE_ADDR':
        event[u'requestContext'].get(u'identity', {}).get(u'sourceIp', ''),
        'REMOTE_USER':
        event[u'requestContext'].get(u'authorizer',
                                     {}).get(u'principalId', ''),
        'REQUEST_METHOD':
        event[u'httpMethod'],
        'SCRIPT_NAME':
        script_name,
        'SERVER_NAME':
        headers.get(u'Host', 'lambda'),
        'SERVER_PORT':
        headers.get(u'X-Forwarded-Port', '80'),
        'SERVER_PROTOCOL':
        'HTTP/1.1',
        'event':
        event,
        'context':
        context,
        'wsgi.errors':
        sys.stderr,
        'wsgi.input':
        BytesIO(body),
        'wsgi.multiprocess':
        False,
        'wsgi.multithread':
        False,
        'wsgi.run_once':
        False,
        'wsgi.url_scheme':
        headers.get(u'X-Forwarded-Proto', 'http'),
        'wsgi.version': (1, 0),
    }

    for key, value in environ.items():
        if isinstance(value, string_types):
            environ[key] = wsgi_encoding_dance(value)

    for key, value in headers.items():
        key = 'HTTP_' + key.upper().replace('-', '_')
        if key not in ('HTTP_CONTENT_TYPE', 'HTTP_CONTENT_LENGTH'):
            environ[key] = value

    response = Response.from_app(wsgi_app, environ)

    # If there are multiple Set-Cookie headers, create case-mutated variations
    # in order to pass them through APIGW. This is a hack that's currently
    # needed. See: https://github.com/logandk/serverless-wsgi/issues/11
    # Source: https://github.com/Miserlou/Zappa/blob/master/zappa/middleware.py
    new_headers = [x for x in response.headers if x[0] != 'Set-Cookie']
    cookie_headers = [x for x in response.headers if x[0] == 'Set-Cookie']
    if len(cookie_headers) > 1:
        for header, new_name in zip(cookie_headers, all_casings('Set-Cookie')):
            new_headers.append((new_name, header[1]))
    elif len(cookie_headers) == 1:
        new_headers.extend(cookie_headers)

    returndict = {
        u'statusCode': response.status_code,
        u'headers': dict(new_headers)
    }

    if response.data:
        mimetype = response.mimetype or 'text/plain'
        if ((mimetype.startswith('text/') or mimetype in TEXT_MIME_TYPES)
                and not response.headers.get('Content-Encoding', '')):
            returndict['body'] = response.get_data(as_text=True)
        else:
            returndict['body'] = base64.b64encode(
                response.data).decode('utf-8')
            returndict['isBase64Encoded'] = 'true'

    return returndict
Example #6
0
    def test_limiting(self):
        data = b'foo=Hello+World&bar=baz'
        req = Request.from_values(
            input_stream=BytesIO(data),
            content_length=len(data),
            content_type='application/x-www-form-urlencoded',
            method='POST')
        req.max_content_length = 400
        strict_eq(req.form['foo'], u'Hello World')

        req = Request.from_values(
            input_stream=BytesIO(data),
            content_length=len(data),
            content_type='application/x-www-form-urlencoded',
            method='POST')
        req.max_form_memory_size = 7
        pytest.raises(RequestEntityTooLarge, lambda: req.form['foo'])

        req = Request.from_values(
            input_stream=BytesIO(data),
            content_length=len(data),
            content_type='application/x-www-form-urlencoded',
            method='POST')
        req.max_form_memory_size = 400
        strict_eq(req.form['foo'], u'Hello World')

        data = b'foo=Hello+World&bar=\xd6\xd0\xce\xc4'
        req = Request.from_values(
            input_stream=BytesIO(data),
            content_length=len(data),
            content_type='application/x-www-form-urlencoded; charset=GBK',
            method='POST')
        req.max_content_length = 400
        strict_eq(req.form['bar'], u'中文')

        data = (b'--foo\r\nContent-Disposition: form-field; name=foo\r\n\r\n'
                b'Hello World\r\n'
                b'--foo\r\nContent-Disposition: form-field; name=bar\r\n\r\n'
                b'bar=baz\r\n--foo--')
        req = Request.from_values(
            input_stream=BytesIO(data),
            content_length=len(data),
            content_type='multipart/form-data; boundary=foo',
            method='POST')
        req.max_content_length = 4
        pytest.raises(RequestEntityTooLarge, lambda: req.form['foo'])

        req = Request.from_values(
            input_stream=BytesIO(data),
            content_length=len(data),
            content_type='multipart/form-data; boundary=foo',
            method='POST')
        req.max_content_length = 400
        strict_eq(req.form['foo'], u'Hello World')

        req = Request.from_values(
            input_stream=BytesIO(data),
            content_length=len(data),
            content_type='multipart/form-data; boundary=foo',
            method='POST')
        req.max_form_memory_size = 7
        pytest.raises(RequestEntityTooLarge, lambda: req.form['foo'])

        req = Request.from_values(
            input_stream=BytesIO(data),
            content_length=len(data),
            content_type='multipart/form-data; boundary=foo',
            method='POST')
        req.max_form_memory_size = 400
        strict_eq(req.form['foo'], u'Hello World')
Example #7
0
def test_limited_stream():
    class RaisingLimitedStream(wsgi.LimitedStream):
        def on_exhausted(self):
            raise BadRequest('input stream exhausted')

    io = BytesIO(b'123456')
    stream = RaisingLimitedStream(io, 3)
    strict_eq(stream.read(), b'123')
    pytest.raises(BadRequest, stream.read)

    io = BytesIO(b'123456')
    stream = RaisingLimitedStream(io, 3)
    strict_eq(stream.tell(), 0)
    strict_eq(stream.read(1), b'1')
    strict_eq(stream.tell(), 1)
    strict_eq(stream.read(1), b'2')
    strict_eq(stream.tell(), 2)
    strict_eq(stream.read(1), b'3')
    strict_eq(stream.tell(), 3)
    pytest.raises(BadRequest, stream.read)

    io = BytesIO(b'123456\nabcdefg')
    stream = wsgi.LimitedStream(io, 9)
    strict_eq(stream.readline(), b'123456\n')
    strict_eq(stream.readline(), b'ab')

    io = BytesIO(b'123456\nabcdefg')
    stream = wsgi.LimitedStream(io, 9)
    strict_eq(stream.readlines(), [b'123456\n', b'ab'])

    io = BytesIO(b'123456\nabcdefg')
    stream = wsgi.LimitedStream(io, 9)
    strict_eq(stream.readlines(2), [b'12'])
    strict_eq(stream.readlines(2), [b'34'])
    strict_eq(stream.readlines(), [b'56\n', b'ab'])

    io = BytesIO(b'123456\nabcdefg')
    stream = wsgi.LimitedStream(io, 9)
    strict_eq(stream.readline(100), b'123456\n')

    io = BytesIO(b'123456\nabcdefg')
    stream = wsgi.LimitedStream(io, 9)
    strict_eq(stream.readlines(100), [b'123456\n', b'ab'])

    io = BytesIO(b'123456')
    stream = wsgi.LimitedStream(io, 3)
    strict_eq(stream.read(1), b'1')
    strict_eq(stream.read(1), b'2')
    strict_eq(stream.read(), b'3')
    strict_eq(stream.read(), b'')

    io = BytesIO(b'123456')
    stream = wsgi.LimitedStream(io, 3)
    strict_eq(stream.read(-1), b'123')

    io = BytesIO(b'123456')
    stream = wsgi.LimitedStream(io, 0)
    strict_eq(stream.read(-1), b'')

    io = StringIO(u'123456')
    stream = wsgi.LimitedStream(io, 0)
    strict_eq(stream.read(-1), u'')

    io = StringIO(u'123\n456\n')
    stream = wsgi.LimitedStream(io, 8)
    strict_eq(list(stream), [u'123\n', u'456\n'])
Example #8
0
def handler(event, context):
    if event.get("source") in ["aws.events", "serverless-plugin-warmup"]:
        return {}

    headers = Headers(event[u"headers"])

    if u"amazonaws.com" in headers.get(u"Host", u""):
        script_name = "/{}".format(event[u"requestContext"].get(u"stage", ""))
    else:
        script_name = ""

    print(script_name)

    # If a user is using a custom domain on API Gateway, they may have a base
    # path in their URL. This allows us to strip it out via an optional
    # environment variable.
    path_info = event[u"path"]
    base_path = os.environ.get("API_GATEWAY_BASE_PATH", "")
    if base_path:
        script_name = "/" + base_path

        if path_info.startswith(script_name):
            path_info = path_info[len(script_name):]

    body = event[u"body"] or ""
    if event.get("isBase64Encoded", False):
        body = base64.b64decode(body)
    if isinstance(body, string_types):
        body = to_bytes(body, charset="utf-8")

    print(script_name)

    environ = {
        "API_GATEWAY_AUTHORIZER":
        event[u"requestContext"].get(u"authorizer"),
        "CONTENT_LENGTH":
        str(len(body)),
        "CONTENT_TYPE":
        headers.get(u"Content-Type", ""),
        "PATH_INFO":
        path_info,
        "QUERY_STRING":
        url_encode(event.get(u"queryStringParameters") or {}),
        "REMOTE_ADDR":
        event[u"requestContext"].get(u"identity", {}).get(u"sourceIp", ""),
        "REMOTE_USER":
        event[u"requestContext"].get(u"authorizer",
                                     {}).get(u"principalId", ""),
        "REQUEST_METHOD":
        event[u"httpMethod"],
        "SCRIPT_NAME":
        script_name,
        "SERVER_NAME":
        headers.get(u"Host", "lambda"),
        "SERVER_PORT":
        headers.get(u"X-Forwarded-Port", "80"),
        "SERVER_PROTOCOL":
        "HTTP/1.1",
        "event":
        event,
        "context":
        context,
        "wsgi.errors":
        sys.stderr,
        "wsgi.input":
        BytesIO(body),
        "wsgi.multiprocess":
        False,
        "wsgi.multithread":
        False,
        "wsgi.run_once":
        False,
        "wsgi.url_scheme":
        headers.get(u"X-Forwarded-Proto", "http"),
        "wsgi.version": (1, 0),
    }

    for key, value in environ.items():
        if isinstance(value, string_types):
            environ[key] = wsgi_encoding_dance(value)

    for key, value in headers.items():
        key = "HTTP_" + key.upper().replace("-", "_")
        if key not in ("HTTP_CONTENT_TYPE", "HTTP_CONTENT_LENGTH"):
            environ[key] = value

    print(environ)
    response = Response.from_app(wsgi_app, environ)
    print(response)
    # If there are multiple Set-Cookie headers, create case-mutated variations
    # in order to pass them through APIGW. This is a hack that's currently
    # needed. See: https://github.com/logandk/serverless-wsgi/issues/11
    # Source: https://github.com/Miserlou/Zappa/blob/master/zappa/middleware.py
    new_headers = [x for x in response.headers if x[0] != "Set-Cookie"]
    cookie_headers = [x for x in response.headers if x[0] == "Set-Cookie"]
    if len(cookie_headers) > 1:
        for header, new_name in zip(cookie_headers, all_casings("Set-Cookie")):
            new_headers.append((new_name, header[1]))
    elif len(cookie_headers) == 1:
        new_headers.extend(cookie_headers)

    returndict = {
        u"statusCode": response.status_code,
        u"headers": dict(new_headers)
    }

    if response.data:
        mimetype = response.mimetype or "text/plain"
        if (mimetype.startswith("text/")
                or mimetype in TEXT_MIME_TYPES) and not response.headers.get(
                    "Content-Encoding", ""):
            returndict["body"] = response.get_data(as_text=True)
        else:
            returndict["body"] = base64.b64encode(
                response.data).decode("utf-8")
            returndict["isBase64Encoded"] = "true"

    return returndict
Example #9
0
    def now_handler(event, context):
        payload = json.loads(event['body'])

        headers = Headers(payload.get('headers', {}))

        body = payload.get('body', '')
        if body != '':
            if payload.get('encoding') == 'base64':
                body = base64.b64decode(body)
        if isinstance(body, string_types):
            body = to_bytes(body, charset='utf-8')

        url = urlparse(unquote(payload['path']))
        query = url.query
        path = url.path

        environ = {
            'CONTENT_LENGTH':
            str(len(body)),
            'CONTENT_TYPE':
            headers.get('content-type', ''),
            'PATH_INFO':
            path,
            'QUERY_STRING':
            query,
            'REMOTE_ADDR':
            headers.get(
                'x-forwarded-for',
                headers.get('x-real-ip', payload.get('true-client-ip', ''))),
            'REQUEST_METHOD':
            payload['method'],
            'SERVER_NAME':
            headers.get('host', 'lambda'),
            'SERVER_PORT':
            headers.get('x-forwarded-port', '80'),
            'SERVER_PROTOCOL':
            'HTTP/1.1',
            'event':
            event,
            'context':
            context,
            'wsgi.errors':
            sys.stderr,
            'wsgi.input':
            BytesIO(body),
            'wsgi.multiprocess':
            False,
            'wsgi.multithread':
            False,
            'wsgi.run_once':
            False,
            'wsgi.url_scheme':
            headers.get('x-forwarded-proto', 'http'),
            'wsgi.version': (1, 0),
        }

        for key, value in environ.items():
            if isinstance(value, string_types) and key != 'QUERY_STRING':
                environ[key] = wsgi_encoding_dance(value)

        for key, value in headers.items():
            key = 'HTTP_' + key.upper().replace('-', '_')
            if key not in ('HTTP_CONTENT_TYPE', 'HTTP_CONTENT_LENGTH'):
                environ[key] = value

        response = Response.from_app(__NOW_HANDLER_FILENAME.app, environ)

        return_dict = {
            'statusCode': response.status_code,
            'headers': dict(response.headers)
        }

        if response.data:
            return_dict['body'] = base64.b64encode(
                response.data).decode('utf-8')
            return_dict['encoding'] = 'base64'

        return return_dict
Example #10
0
def test_limited_stream():
    class RaisingLimitedStream(wsgi.LimitedStream):
        def on_exhausted(self):
            raise BadRequest("input stream exhausted")

    io = BytesIO(b"123456")
    stream = RaisingLimitedStream(io, 3)
    strict_eq(stream.read(), b"123")
    pytest.raises(BadRequest, stream.read)

    io = BytesIO(b"123456")
    stream = RaisingLimitedStream(io, 3)
    strict_eq(stream.tell(), 0)
    strict_eq(stream.read(1), b"1")
    strict_eq(stream.tell(), 1)
    strict_eq(stream.read(1), b"2")
    strict_eq(stream.tell(), 2)
    strict_eq(stream.read(1), b"3")
    strict_eq(stream.tell(), 3)
    pytest.raises(BadRequest, stream.read)

    io = BytesIO(b"123456\nabcdefg")
    stream = wsgi.LimitedStream(io, 9)
    strict_eq(stream.readline(), b"123456\n")
    strict_eq(stream.readline(), b"ab")

    io = BytesIO(b"123456\nabcdefg")
    stream = wsgi.LimitedStream(io, 9)
    strict_eq(stream.readlines(), [b"123456\n", b"ab"])

    io = BytesIO(b"123456\nabcdefg")
    stream = wsgi.LimitedStream(io, 9)
    strict_eq(stream.readlines(2), [b"12"])
    strict_eq(stream.readlines(2), [b"34"])
    strict_eq(stream.readlines(), [b"56\n", b"ab"])

    io = BytesIO(b"123456\nabcdefg")
    stream = wsgi.LimitedStream(io, 9)
    strict_eq(stream.readline(100), b"123456\n")

    io = BytesIO(b"123456\nabcdefg")
    stream = wsgi.LimitedStream(io, 9)
    strict_eq(stream.readlines(100), [b"123456\n", b"ab"])

    io = BytesIO(b"123456")
    stream = wsgi.LimitedStream(io, 3)
    strict_eq(stream.read(1), b"1")
    strict_eq(stream.read(1), b"2")
    strict_eq(stream.read(), b"3")
    strict_eq(stream.read(), b"")

    io = BytesIO(b"123456")
    stream = wsgi.LimitedStream(io, 3)
    strict_eq(stream.read(-1), b"123")

    io = BytesIO(b"123456")
    stream = wsgi.LimitedStream(io, 0)
    strict_eq(stream.read(-1), b"")

    io = StringIO(u"123456")
    stream = wsgi.LimitedStream(io, 0)
    strict_eq(stream.read(-1), u"")

    io = StringIO(u"123\n456\n")
    stream = wsgi.LimitedStream(io, 8)
    strict_eq(list(stream), [u"123\n", u"456\n"])
Example #11
0
    :copyright: (c) 2014 by the Werkzeug Team, see AUTHORS for more details.
    :license: BSD, see LICENSE for more details.
"""
import re
import string
import inspect
from weakref import WeakKeyDictionary
from datetime import datetime, date
from itertools import chain

from werkzeug._compat import iter_bytes, text_type, BytesIO, int_to_byte, \
    range_type, integer_types


_logger = None
_empty_stream = BytesIO()
_signature_cache = WeakKeyDictionary()
_epoch_ord = date(1970, 1, 1).toordinal()
_cookie_params = set((b'expires', b'path', b'comment',
                      b'max-age', b'secure', b'httponly',
                      b'version'))
_legal_cookie_chars = (string.ascii_letters +
                       string.digits +
                       u"/=!#$%&'*+-.^_`|~:").encode('ascii')

_cookie_quoting_map = {
    b',': b'\\054',
    b';': b'\\073',
    b'"': b'\\"',
    b'\\': b'\\\\',
}
Example #12
0
def handle_payload_v2(app, event, context):
    headers = Headers(event[u"headers"])

    script_name = get_script_name(headers, event.get("requestContext", {}))

    path_info = event[u"rawPath"]

    body = event.get("body", "")
    body = get_body_bytes(event, body)

    headers["Cookie"] = "; ".join(event.get("cookies", []))

    environ = {
        "CONTENT_LENGTH":
        str(len(body)),
        "CONTENT_TYPE":
        headers.get(u"Content-Type", ""),
        "PATH_INFO":
        url_unquote(path_info),
        "QUERY_STRING":
        url_encode(event.get(u"queryStringParameters", {})),
        "REMOTE_ADDR":
        event.get("requestContext", {}).get(u"http", {}).get(u"sourceIp", ""),
        "REMOTE_USER":
        event.get("requestContext", {}).get(u"authorizer",
                                            {}).get(u"principalId", ""),
        "REQUEST_METHOD":
        event.get("requestContext", {}).get("http", {}).get("method", ""),
        "SCRIPT_NAME":
        script_name,
        "SERVER_NAME":
        headers.get(u"Host", "lambda"),
        "SERVER_PORT":
        headers.get(u"X-Forwarded-Port", "80"),
        "SERVER_PROTOCOL":
        "HTTP/1.1",
        "wsgi.errors":
        sys.stderr,
        "wsgi.input":
        BytesIO(body),
        "wsgi.multiprocess":
        False,
        "wsgi.multithread":
        False,
        "wsgi.run_once":
        False,
        "wsgi.url_scheme":
        headers.get(u"X-Forwarded-Proto", "http"),
        "wsgi.version": (1, 0),
        "serverless.authorizer":
        event.get("requestContext", {}).get(u"authorizer"),
        "serverless.event":
        event,
        "serverless.context":
        context,
        # TODO: Deprecate the following entries, as they do not comply with the WSGI
        # spec. For custom variables, the spec says:
        #
        #   Finally, the environ dictionary may also contain server-defined variables.
        #   These variables should be named using only lower-case letters, numbers, dots,
        #   and underscores, and should be prefixed with a name that is unique to the
        #   defining server or gateway.
        "API_GATEWAY_AUTHORIZER":
        event.get("requestContext", {}).get(u"authorizer"),
        "event":
        event,
        "context":
        context,
    }

    environ = setup_environ_items(environ, headers)

    response = Response.from_app(app, environ)

    returndict = generate_response(response, event)

    return returndict
Example #13
0
def handle_payload_v1(app, event, context):
    if u"multiValueHeaders" in event:
        headers = Headers(event[u"multiValueHeaders"])
    else:
        headers = Headers(event[u"headers"])

    script_name = get_script_name(headers, event.get("requestContext", {}))

    # If a user is using a custom domain on API Gateway, they may have a base
    # path in their URL. This allows us to strip it out via an optional
    # environment variable.
    path_info = event[u"path"]
    base_path = os.environ.get("API_GATEWAY_BASE_PATH")
    if base_path:
        script_name = "/" + base_path

        if path_info.startswith(script_name):
            path_info = path_info[len(script_name):]

    body = event[u"body"] or ""
    body = get_body_bytes(event, body)

    environ = {
        "CONTENT_LENGTH":
        str(len(body)),
        "CONTENT_TYPE":
        headers.get(u"Content-Type", ""),
        "PATH_INFO":
        url_unquote(path_info),
        "QUERY_STRING":
        encode_query_string(event),
        "REMOTE_ADDR":
        event.get(u"requestContext", {}).get(u"identity",
                                             {}).get(u"sourceIp", ""),
        "REMOTE_USER":
        event.get(u"requestContext", {}).get(u"authorizer",
                                             {}).get(u"principalId", ""),
        "REQUEST_METHOD":
        event.get(u"httpMethod", {}),
        "SCRIPT_NAME":
        script_name,
        "SERVER_NAME":
        headers.get(u"Host", "lambda"),
        "SERVER_PORT":
        headers.get(u"X-Forwarded-Port", "80"),
        "SERVER_PROTOCOL":
        "HTTP/1.1",
        "wsgi.errors":
        sys.stderr,
        "wsgi.input":
        BytesIO(body),
        "wsgi.multiprocess":
        False,
        "wsgi.multithread":
        False,
        "wsgi.run_once":
        False,
        "wsgi.url_scheme":
        headers.get(u"X-Forwarded-Proto", "http"),
        "wsgi.version": (1, 0),
        "serverless.authorizer":
        event.get(u"requestContext", {}).get(u"authorizer"),
        "serverless.event":
        event,
        "serverless.context":
        context,
        # TODO: Deprecate the following entries, as they do not comply with the WSGI
        # spec. For custom variables, the spec says:
        #
        #   Finally, the environ dictionary may also contain server-defined variables.
        #   These variables should be named using only lower-case letters, numbers, dots,
        #   and underscores, and should be prefixed with a name that is unique to the
        #   defining server or gateway.
        "API_GATEWAY_AUTHORIZER":
        event.get(u"requestContext", {}).get(u"authorizer"),
        "event":
        event,
        "context":
        context,
    }

    environ = setup_environ_items(environ, headers)

    response = Response.from_app(app, environ)
    returndict = generate_response(response, event)

    return returndict