Exemple #1
0
    def make_environ(self):
        request_url = url_parse(self.path)

        def shutdown_server():
            self.server.shutdown_signal = True

        url_scheme = 'http' if self.server.ssl_context is None else 'https'
        if not self.client_address:
            self.client_address = '<local>'
        if isinstance(self.client_address, str):
            self.client_address = (self.client_address, 0)
        else:
            pass
        path_info = url_unquote(request_url.path)

        environ = {
            'wsgi.version': (1, 0),
            'wsgi.url_scheme': url_scheme,
            'wsgi.input': self.rfile,
            'wsgi.errors': sys.stderr,
            'wsgi.multithread': self.server.multithread,
            'wsgi.multiprocess': self.server.multiprocess,
            'wsgi.run_once': False,
            'werkzeug.server.shutdown': shutdown_server,
            'SERVER_SOFTWARE': self.server_version,
            'REQUEST_METHOD': self.command,
            'SCRIPT_NAME': '',
            'PATH_INFO': wsgi_encoding_dance(path_info),
            'QUERY_STRING': wsgi_encoding_dance(request_url.query),
            # Non-standard, added by mod_wsgi, uWSGI
            "REQUEST_URI": wsgi_encoding_dance(self.path),
            # Non-standard, added by gunicorn
            "RAW_URI": wsgi_encoding_dance(self.path),
            'REMOTE_ADDR': self.address_string(),
            'REMOTE_PORT': self.port_integer(),
            'SERVER_NAME': self.server.server_address[0],
            'SERVER_PORT': str(self.server.server_address[1]),
            'SERVER_PROTOCOL': self.request_version
        }

        for key, value in self.get_header_items():
            key = key.upper().replace('-', '_')
            if key not in ('CONTENT_TYPE', 'CONTENT_LENGTH'):
                key = 'HTTP_' + key
                if key in environ:
                    value = "{},{}".format(environ[key], value)
            environ[key] = value

        if environ.get('HTTP_TRANSFER_ENCODING',
                       '').strip().lower() == 'chunked':
            environ['wsgi.input_terminated'] = True
            environ['wsgi.input'] = DechunkedInput(environ['wsgi.input'])

        if request_url.scheme and request_url.netloc:
            environ['HTTP_HOST'] = request_url.netloc

        return environ
    def make_environ(self):
        request_url = url_parse(self.path)

        def shutdown_server():
            self.server.shutdown_signal = True

        url_scheme = 'http' if self.server.ssl_context is None else 'https'
        if not self.client_address:
            self.client_address = '<local>'
        if isinstance(self.client_address, str):
            self.client_address = (self.client_address, 0)
        else:
            pass
        path_info = url_unquote(request_url.path)

        environ = {
            'wsgi.version':         (1, 0),
            'wsgi.url_scheme':      url_scheme,
            'wsgi.input':           self.rfile,
            'wsgi.errors':          sys.stderr,
            'wsgi.multithread':     self.server.multithread,
            'wsgi.multiprocess':    self.server.multiprocess,
            'wsgi.run_once':        False,
            'werkzeug.server.shutdown': shutdown_server,
            'SERVER_SOFTWARE':      self.server_version,
            'REQUEST_METHOD':       self.command,
            'SCRIPT_NAME':          '',
            'PATH_INFO':            wsgi_encoding_dance(path_info),
            'QUERY_STRING':         wsgi_encoding_dance(request_url.query),
            # Non-standard, added by mod_wsgi, uWSGI
            "REQUEST_URI": wsgi_encoding_dance(self.path),
            # Non-standard, added by gunicorn
            "RAW_URI": wsgi_encoding_dance(self.path),
            'REMOTE_ADDR':          self.address_string(),
            'REMOTE_PORT':          self.port_integer(),
            'SERVER_NAME':          self.server.server_address[0],
            'SERVER_PORT':          str(self.server.server_address[1]),
            'SERVER_PROTOCOL':      self.request_version
        }

        for key, value in self.get_header_items():
            key = key.upper().replace('-', '_')
            if key not in ('CONTENT_TYPE', 'CONTENT_LENGTH'):
                key = 'HTTP_' + key
                if key in environ:
                    value = "{},{}".format(environ[key], value)
            environ[key] = value

        if environ.get('HTTP_TRANSFER_ENCODING', '').strip().lower() == 'chunked':
            environ['wsgi.input_terminated'] = True
            environ['wsgi.input'] = DechunkedInput(environ['wsgi.input'])

        if request_url.scheme and request_url.netloc:
            environ['HTTP_HOST'] = request_url.netloc

        return environ
Exemple #3
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')

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

        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
Exemple #4
0
    def get_environ(self):
        """返回内置环境。"""
        input_stream = self.input_stream
        content_length = self.content_length
        content_type = self.content_type

        if input_stream is not None:
            start_pos = input_stream.tell()
            input_stream.seek(0, 2)
            end_pos = input_stream.tell()
            input_stream.seek(start_pos)
            content_length = end_pos - start_pos
        elif content_type == "multipart/form-data":
            values = CombinedMultiDict([self.form, self.files])
            input_stream, content_length, boundary = stream_encode_multipart(values, charset=self.charset)
            content_type += '; boundary="%s"' % boundary
        elif content_type == "application/x-www-form-urlencoded":
            # py2v3 review
            values = url_encode(self.form, charset=self.charset)
            values = values.encode("ascii")
            content_length = len(values)
            input_stream = BytesIO(values)
        else:
            input_stream = _empty_stream

        result = {}
        if self.environ_base:
            result.update(self.environ_base)

        def _path_encode(x):
            return wsgi_encoding_dance(url_unquote(x, self.charset), self.charset)

        qs = wsgi_encoding_dance(self.query_string)

        result.update(
            {
                "REQUEST_METHOD": self.method,
                "SCRIPT_NAME": _path_encode(self.script_root),
                "PATH_INFO": _path_encode(self.path),
                "QUERY_STRING": qs,
                "SERVER_NAME": self.server_name,
                "SERVER_PORT": str(self.server_port),
                "HTTP_HOST": self.host,
                "SERVER_PROTOCOL": self.server_protocol,
                "CONTENT_TYPE": content_type or "",
                "CONTENT_LENGTH": str(content_length or "0"),
                "wsgi.version": self.wsgi_version,
                "wsgi.url_scheme": self.url_scheme,
                "wsgi.input": input_stream,
                "wsgi.errors": self.errors_stream,
                "wsgi.multithread": self.multithread,
                "wsgi.multiprocess": self.multiprocess,
                "wsgi.run_once": self.run_once,
            }
        )
        for key, value in self.headers.to_wsgi_list():
            result["HTTP_%s" % key.upper().replace("-", "_")] = value
        if self.environ_overrides:
            result.update(self.environ_overrides)
        return result
Exemple #5
0
 def test_cookie_unicode_keys(self):
     # Yes, this is technically against the spec but happens
     val = http.dump_cookie(u'fö', u'fö')
     self.assert_equal(
         val, wsgi_encoding_dance(u'fö="f\\303\\266"; Path=/', 'utf-8'))
     cookies = http.parse_cookie(val)
     self.assert_equal(cookies[u'fö'], u'fö')
Exemple #6
0
    def get_environ(self):
        """Return the built environ."""
        input_stream = self.input_stream
        content_length = self.content_length
        content_type = self.content_type

        if input_stream is not None:
            start_pos = input_stream.tell()
            input_stream.seek(0, 2)
            end_pos = input_stream.tell()
            input_stream.seek(start_pos)
            content_length = end_pos - start_pos
        elif content_type == 'multipart/form-data':
            values = CombinedMultiDict([self.form, self.files])
            input_stream, content_length, boundary = \
                stream_encode_multipart(values, charset=self.charset)
            content_type += '; boundary="%s"' % boundary
        elif content_type == 'application/x-www-form-urlencoded':
            #py2v3 review
            values = url_encode(self.form, charset=self.charset)
            values = values.encode('ascii')
            content_length = len(values)
            input_stream = BytesIO(values)
        else:
            input_stream = _empty_stream

        result = {}
        if self.environ_base:
            result.update(self.environ_base)

        def _path_encode(x):
            return wsgi_encoding_dance(url_unquote(x, self.charset),
                                       self.charset)

        qs = wsgi_encoding_dance(self.query_string)

        result.update({
            'REQUEST_METHOD': self.method,
            'SCRIPT_NAME': _path_encode(self.script_root),
            'PATH_INFO': _path_encode(self.path),
            'QUERY_STRING': qs,
            'SERVER_NAME': self.server_name,
            'SERVER_PORT': str(self.server_port),
            'HTTP_HOST': self.host,
            'SERVER_PROTOCOL': self.server_protocol,
            'CONTENT_TYPE': content_type or '',
            'CONTENT_LENGTH': str(content_length or '0'),
            'wsgi.version': self.wsgi_version,
            'wsgi.url_scheme': self.url_scheme,
            'wsgi.input': input_stream,
            'wsgi.errors': self.errors_stream,
            'wsgi.multithread': self.multithread,
            'wsgi.multiprocess': self.multiprocess,
            'wsgi.run_once': self.run_once
        })
        for key, value in self.headers.to_wsgi_list():
            result['HTTP_%s' % key.upper().replace('-', '_')] = value
        if self.environ_overrides:
            result.update(self.environ_overrides)
        return result
Exemple #7
0
    def make_environ(self):
        request_url = url_parse(self.path)

        def shutdown_server():
            self.server.shutdown_signal = True

        url_scheme = self.server.ssl_context is None and 'http' or 'https'
        path_info = url_unquote(request_url.path)

        environ = {
            'wsgi.version':         (1, 0),
            'wsgi.url_scheme':      url_scheme,
            'wsgi.input':           self.rfile,
            'wsgi.errors':          sys.stderr,
            'wsgi.multithread':     self.server.multithread,
            'wsgi.multiprocess':    self.server.multiprocess,
            'wsgi.run_once':        False,
            'werkzeug.server.shutdown':
                                    shutdown_server,
            'SERVER_SOFTWARE':      self.server_version,
            'REQUEST_METHOD':       self.command,
            'SCRIPT_NAME':          '',
            'PATH_INFO':            wsgi_encoding_dance(path_info),
            'QUERY_STRING':         wsgi_encoding_dance(request_url.query),
            'CONTENT_TYPE':         self.headers.get('Content-Type', ''),
            'CONTENT_LENGTH':       self.headers.get('Content-Length', ''),
            'REMOTE_ADDR':          self.client_address[0],
            'REMOTE_PORT':          self.client_address[1],
            'SERVER_NAME':          self.server.server_address[0],
            'SERVER_PORT':          str(self.server.server_address[1]),
            'SERVER_PROTOCOL':      self.request_version
        }

        for h in self.headers.headers:
            key, value = h.split(':', 1)
            key = 'HTTP_' + key.upper().replace('-', '_')
            value = value.strip()
            if key not in ('HTTP_CONTENT_TYPE', 'HTTP_CONTENT_LENGTH'):
                if key in environ:
                    environ[key] += ',' + value
                else:
                    environ[key] = value

        if request_url.netloc:
            environ['HTTP_HOST'] = request_url.netloc

        return environ
Exemple #8
0
    def get_environ(self):
        """Return the built environ."""
        input_stream = self.input_stream
        content_length = self.content_length
        content_type = self.content_type

        if input_stream is not None:
            start_pos = input_stream.tell()
            input_stream.seek(0, 2)
            end_pos = input_stream.tell()
            input_stream.seek(start_pos)
            content_length = end_pos - start_pos
        elif content_type == 'multipart/form-data':
            values = CombinedMultiDict([self.form, self.files])
            input_stream, content_length, boundary = \
                stream_encode_multipart(values, charset=self.charset)
            content_type += '; boundary="%s"' % boundary
        elif content_type == 'application/x-www-form-urlencoded':
            #py2v3 review
            values = url_encode(self.form, charset=self.charset)
            values = values.encode('ascii')
            content_length = len(values)
            input_stream = BytesIO(values)
        else:
            input_stream = _empty_stream

        result = {}
        if self.environ_base:
            result.update(self.environ_base)

        def _path_encode(x):
            return wsgi_encoding_dance(url_unquote(x, self.charset), self.charset)

        qs = wsgi_encoding_dance(self.query_string)

        result.update({
            'REQUEST_METHOD':       self.method,
            'SCRIPT_NAME':          _path_encode(self.script_root),
            'PATH_INFO':            _path_encode(self.path),
            'QUERY_STRING':         qs,
            'SERVER_NAME':          self.server_name,
            'SERVER_PORT':          str(self.server_port),
            'HTTP_HOST':            self.host,
            'SERVER_PROTOCOL':      self.server_protocol,
            'CONTENT_TYPE':         content_type or '',
            'CONTENT_LENGTH':       str(content_length or '0'),
            'wsgi.version':         self.wsgi_version,
            'wsgi.url_scheme':      self.url_scheme,
            'wsgi.input':           input_stream,
            'wsgi.errors':          self.errors_stream,
            'wsgi.multithread':     self.multithread,
            'wsgi.multiprocess':    self.multiprocess,
            'wsgi.run_once':        self.run_once
        })
        for key, value in self.headers.to_wsgi_list():
            result['HTTP_%s' % key.upper().replace('-', '_')] = value
        if self.environ_overrides:
            result.update(self.environ_overrides)
        return result
Exemple #9
0
	def make_environ(self):
		request_url = url_parse(self.path)

		def shutdown_server():
			self.server.shutdown_signal = True

		url_scheme = self.server.ssl_context is None and 'http' or 'https'
		path_info = url_unquote(request_url.path)

		environ = {
			'REQUEST_UUID': uuid.uuid4().hex,
			'wsgi.version': (1, 0),
			'wsgi.url_scheme': url_scheme,
			'wsgi.input': self.rfile,
			'wsgi.errors': sys.stderr,
			'wsgi.multithread': self.server.multithread,
			'wsgi.multiprocess': self.server.multiprocess,
			'wsgi.run_once': False,
			'werkzeug.server.shutdown': shutdown_server,
			'SERVER_SOFTWARE': self.server_version,
			'REQUEST_METHOD': self.command,
			'SCRIPT_NAME': '',
			'PATH_INFO': wsgi_encoding_dance(path_info),
			'QUERY_STRING': wsgi_encoding_dance(request_url.query),
			'REMOTE_ADDR': self.address_string(),
			'REMOTE_PORT': self.port_integer(),
			'SERVER_NAME': self.server.server_address[0],
			'SERVER_PORT': str(self.server.server_address[1]),
			'SERVER_PROTOCOL': self.request_version
		}

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

		if environ.get('HTTP_TRANSFER_ENCODING', '').strip().lower() == 'chunked':
			environ['wsgi.input_terminated'] = True
			environ['wsgi.input'] = DechunkedInput(environ['wsgi.input'])

		if request_url.scheme and request_url.netloc:
			environ['HTTP_HOST'] = request_url.netloc

		return environ
Exemple #10
0
    def make_environ(self):
        request_url = url_parse(self.path)

        def shutdown_server():
            self.server.shutdown_signal = True

        url_scheme = self.server.ssl_context is None and "http" or "https"
        path_info = url_unquote(request_url.path)

        environ = {
            "wsgi.version": (1, 0),
            "wsgi.url_scheme": url_scheme,
            "wsgi.input": self.rfile,
            "wsgi.errors": sys.stderr,
            "wsgi.multithread": self.server.multithread,
            "wsgi.multiprocess": self.server.multiprocess,
            "wsgi.run_once": False,
            "werkzeug.server.shutdown": shutdown_server,
            "SERVER_SOFTWARE": self.server_version,
            "REQUEST_METHOD": self.command,
            "SCRIPT_NAME": "",
            "PATH_INFO": wsgi_encoding_dance(path_info),
            "QUERY_STRING": wsgi_encoding_dance(request_url.query),
            "REMOTE_ADDR": self.address_string(),
            "REMOTE_PORT": self.port_integer(),
            "SERVER_NAME": self.server.server_address[0],
            "SERVER_PORT": str(self.server.server_address[1]),
            "SERVER_PROTOCOL": self.request_version,
        }

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

        if environ.get("HTTP_TRANSFER_ENCODING", "").strip().lower() == "chunked":
            environ["wsgi.input_terminated"] = True
            environ["wsgi.input"] = DechunkedInput(environ["wsgi.input"])

        if request_url.scheme and request_url.netloc:
            environ["HTTP_HOST"] = request_url.netloc

        return environ
Exemple #11
0
    def make_environ(self):
        """
        Create an environment that can be used with werkzeug
        """
        # Derived from werkzeug's WSGIRequestHandler
        from werkzeug.urls import url_parse, url_unquote
        from werkzeug._compat import wsgi_encoding_dance

        request_url = url_parse(self.path)

        url_scheme = "http"
        path_info = url_unquote(request_url.path)

        environ = {
            'wsgi.version': (1, 0),
            'wsgi.url_scheme': url_scheme,
            'wsgi.input': self.rfile,
            'wsgi.errors': sys.stderr,
            'wsgi.multithread': False,
            'wsgi.multiprocess': True,
            'wsgi.run_once': False,
            'SERVER_SOFTWARE': self.server_version,
            'REQUEST_METHOD': self.command,
            'SCRIPT_NAME': '',
            'PATH_INFO': wsgi_encoding_dance(path_info),
            'QUERY_STRING': wsgi_encoding_dance(request_url.query),
            'CONTENT_TYPE': self.headers.get('Content-Type', ''),
            'CONTENT_LENGTH': self.headers.get('Content-Length', ''),
            'REMOTE_ADDR': self.client_address[0],
            'REMOTE_PORT': self.client_address[1],
            'SERVER_NAME': self.server.server_address[0],
            'SERVER_PORT': str(self.server.server_address[1]),
            'SERVER_PROTOCOL': self.request_version
        }

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

        if request_url.netloc:
            environ['HTTP_HOST'] = request_url.netloc

        return environ
def setup_environ_items(environ, headers):
    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
    return environ
Exemple #13
0
    def make_environ(self):
        request_url = url_parse(self.path)

        def shutdown_server():
            self.server.shutdown_signal = True

        url_scheme = self.server.ssl_context is None and 'http' or 'https'
        path_info = url_unquote(request_url.path)

        environ = {
            'wsgi.version':         (1, 0),
            'wsgi.url_scheme':      url_scheme,
            'wsgi.input':           self.rfile,
            'wsgi.errors':          sys.stderr,
            'wsgi.multithread':     self.server.multithread,
            'wsgi.multiprocess':    self.server.multiprocess,
            'wsgi.run_once':        False,
            'werkzeug.server.shutdown':
                                    shutdown_server,
            'SERVER_SOFTWARE':      self.server_version,
            'REQUEST_METHOD':       self.command,
            'SCRIPT_NAME':          '',
            'PATH_INFO':            wsgi_encoding_dance(path_info),
            'QUERY_STRING':         wsgi_encoding_dance(request_url.query),
            'CONTENT_TYPE':         self.headers.get('Content-Type', ''),
            'CONTENT_LENGTH':       self.headers.get('Content-Length', ''),
            'REMOTE_ADDR':          self.client_address[0],
            'REMOTE_PORT':          self.client_address[1],
            'SERVER_NAME':          self.server.server_address[0],
            'SERVER_PORT':          str(self.server.server_address[1]),
            'SERVER_PROTOCOL':      self.request_version
        }

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

        if request_url.netloc:
            environ['HTTP_HOST'] = request_url.netloc

        return environ
    def make_environ(self):
        request_url = url_parse(self.path)

        def shutdown_server():
            self.server.shutdown_signal = True

        url_scheme = self.server.ssl_context is None and "http" or "https"
        path_info = url_unquote(request_url.path)

        environ = {
            "wsgi.version": (1, 0),
            "wsgi.url_scheme": url_scheme,
            "wsgi.input": self.rfile,
            "wsgi.errors": sys.stderr,
            "wsgi.multithread": self.server.multithread,
            "wsgi.multiprocess": self.server.multiprocess,
            "wsgi.run_once": False,
            "werkzeug.server.shutdown": shutdown_server,
            "SERVER_SOFTWARE": self.server_version,
            "REQUEST_METHOD": self.command,
            "SCRIPT_NAME": "",
            "PATH_INFO": wsgi_encoding_dance(path_info),
            "QUERY_STRING": wsgi_encoding_dance(request_url.query),
            "CONTENT_TYPE": self.headers.get("Content-Type", ""),
            "CONTENT_LENGTH": self.headers.get("Content-Length", ""),
            "REMOTE_ADDR": self.client_address[0],
            "REMOTE_PORT": self.client_address[1],
            "SERVER_NAME": self.server.server_address[0],
            "SERVER_PORT": str(self.server.server_address[1]),
            "SERVER_PROTOCOL": self.request_version,
        }

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

        if request_url.netloc:
            environ["HTTP_HOST"] = request_url.netloc

        return environ
Exemple #15
0
 def _path_encode(x):
     return wsgi_encoding_dance(url_unquote(x, self.charset), self.charset)
Exemple #16
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 = ''

    environ = {
        'CONTENT_LENGTH':
        headers.get(u'Content-Length', str(len(event[u'body'] or ''))),
        'CONTENT_TYPE':
        headers.get(u'Content-Type', ''),
        'PATH_INFO':
        event[u'path'],
        'QUERY_STRING':
        url_encode(event.get(u'queryStringParameters', None) or {}),
        'REMOTE_ADDR':
        headers.get(u'X-Forwarded-For', '').split(', ')[0],
        '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':
        StringIO(),
        'wsgi.input':
        StringIO(wsgi_encoding_dance(event[u'body'] or '')),
        '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, basestring):
            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)

    errors = environ['wsgi.errors'].getvalue()
    if errors:
        print errors

    return {
        u'statusCode': response.status_code,
        u'headers': dict(response.headers),
        u'body': response.data
    }
Exemple #17
0
def handler(app, lambda_event, context):

    event = json.loads(lambda_event['body'])
    headers = Headers(event.get('headers', None))
    parsed_url = urlparse(event['path'])

    body = event.get('body', '')
    encoding = event.get('encoding', None)

    if encoding == 'base64':
        body = base64.b64decode(body)
    else:
        body = to_bytes(body, charset='utf-8')

    environ = {
        'CONTENT_LENGTH': str(len(body)),
        'CONTENT_TYPE': headers.get('Content-Type', ''),
        'PATH_INFO': parsed_url.path,
        'QUERY_STRING': unquote(parsed_url.query),
        'REMOTE_ADDR': event.get('x-real-ip', ''),
        'REQUEST_METHOD': event['method'],
        'SCRIPT_NAME': '',
        'SERVER_NAME': headers.get('Host', 'lambda'),
        'SERVER_PORT': headers.get('X-Forwarded-Port', '80'),
        'SERVER_PROTOCOL': 'HTTP/1.1',
        'event': lambda_event['body'],
        '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):
            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)

    # Handle multi-value headers
    headers = {}
    for key, value in response.headers:
        if key in headers:
            current_value = headers[key]
            if isinstance(current_value, list):
                headers[key] += [value]
            else:
                headers[key] = [current_value, value]
        else:
            headers[key] = value

    returndict = {
        'statusCode': response.status_code,
        'headers': headers,
        'body': '',
    }

    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['encoding'] = 'base64'

    return returndict
Exemple #18
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 = ""

    # 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")

    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

    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
def handle_request(app, event, context):
    if event.get("source") in ["aws.events", "serverless-plugin-warmup"]:
        return {}

    if u"multiValueHeaders" in event:
        headers = Headers(event[u"multiValueHeaders"])
    else:
        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")

    environ = {
        "CONTENT_LENGTH":
        str(len(body)),
        "CONTENT_TYPE":
        headers.get(u"Content-Type", ""),
        "PATH_INFO":
        path_info,
        "QUERY_STRING":
        encode_query_string(event),
        "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),
        "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}

    if u"multiValueHeaders" in event:
        returndict[u"multiValueHeaders"] = group_headers(response.headers)
    else:
        returndict[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
Exemple #20
0
 def test_cookie_unicode_keys(self):
     # Yes, this is technically against the spec but happens
     val = http.dump_cookie(u"fö", u"fö")
     assert val == wsgi_encoding_dance(u'fö="f\\303\\266"; Path=/', "utf-8")
     cookies = http.parse_cookie(val)
     assert cookies[u"fö"] == u"fö"
Exemple #21
0
    def get_environ(self):
        """Return the built environ.

        .. versionchanged:: 0.15
            The content type and length headers are set based on
            input stream detection. Previously this only set the WSGI
            keys.
        """
        input_stream = self.input_stream
        content_length = self.content_length

        mimetype = self.mimetype
        content_type = self.content_type

        if input_stream is not None:
            start_pos = input_stream.tell()
            input_stream.seek(0, 2)
            end_pos = input_stream.tell()
            input_stream.seek(start_pos)
            content_length = end_pos - start_pos
        elif mimetype == 'multipart/form-data':
            values = CombinedMultiDict([self.form, self.files])
            input_stream, content_length, boundary = \
                stream_encode_multipart(values, charset=self.charset)
            content_type = mimetype + '; boundary="%s"' % boundary
        elif mimetype == 'application/x-www-form-urlencoded':
            # XXX: py2v3 review
            values = url_encode(self.form, charset=self.charset)
            values = values.encode('ascii')
            content_length = len(values)
            input_stream = BytesIO(values)
        else:
            input_stream = BytesIO()

        result = {}
        if self.environ_base:
            result.update(self.environ_base)

        def _path_encode(x):
            return wsgi_encoding_dance(url_unquote(x, self.charset),
                                       self.charset)

        qs = wsgi_encoding_dance(self.query_string)

        result.update({
            'REQUEST_METHOD': self.method,
            'SCRIPT_NAME': _path_encode(self.script_root),
            'PATH_INFO': _path_encode(self.path),
            'QUERY_STRING': qs,
            # Non-standard, added by mod_wsgi, uWSGI
            "REQUEST_URI": wsgi_encoding_dance(self.path),
            # Non-standard, added by gunicorn
            "RAW_URI": wsgi_encoding_dance(self.path),
            'SERVER_NAME': self.server_name,
            'SERVER_PORT': str(self.server_port),
            'HTTP_HOST': self.host,
            'SERVER_PROTOCOL': self.server_protocol,
            'wsgi.version': self.wsgi_version,
            'wsgi.url_scheme': self.url_scheme,
            'wsgi.input': input_stream,
            'wsgi.errors': self.errors_stream,
            'wsgi.multithread': self.multithread,
            'wsgi.multiprocess': self.multiprocess,
            'wsgi.run_once': self.run_once
        })

        headers = self.headers.copy()

        if content_type is not None:
            result['CONTENT_TYPE'] = content_type
            headers.set("Content-Type", content_type)

        if content_length is not None:
            result['CONTENT_LENGTH'] = str(content_length)
            headers.set("Content-Length", content_length)

        for key, value in headers.to_wsgi_list():
            result['HTTP_%s' % key.upper().replace('-', '_')] = value

        if self.environ_overrides:
            result.update(self.environ_overrides)

        return result
Exemple #22
0
 def test_cookie_unicode_keys(self):
     # Yes, this is technically against the spec but happens
     val = http.dump_cookie(u"fö", u"fö")
     assert val == wsgi_encoding_dance(u'fö="f\\303\\266"; Path=/', "utf-8")
     cookies = http.parse_cookie(val)
     assert cookies[u"fö"] == u"fö"
Exemple #23
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(wsgi_encoding_dance(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
Exemple #24
0
def handle_request(application, 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")
    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", "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["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["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(application, 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
Exemple #25
0
 def _path_encode(x):
     return wsgi_encoding_dance(url_unquote(x, self.charset),
                                self.charset)
Exemple #26
0
    def get_environ(self):
        """Return the built environ."""
        input_stream = self.input_stream
        content_length = self.content_length

        mimetype = self.mimetype
        content_type = self.content_type

        if input_stream is not None:
            start_pos = input_stream.tell()
            input_stream.seek(0, 2)
            end_pos = input_stream.tell()
            input_stream.seek(start_pos)
            content_length = end_pos - start_pos
        elif mimetype == "multipart/form-data":
            values = CombinedMultiDict([self.form, self.files])
            input_stream, content_length, boundary = stream_encode_multipart(
                values, charset=self.charset)
            content_type = mimetype + '; boundary="%s"' % boundary
        elif mimetype == "application/x-www-form-urlencoded":
            # XXX: py2v3 review
            values = url_encode(self.form, charset=self.charset)
            values = values.encode("ascii")
            content_length = len(values)
            input_stream = BytesIO(values)
        else:
            input_stream = _empty_stream

        result = {}
        if self.environ_base:
            result.update(self.environ_base)

        def _path_encode(x):
            return wsgi_encoding_dance(url_unquote(x, self.charset),
                                       self.charset)

        qs = wsgi_encoding_dance(self.query_string)

        result.update({
            "REQUEST_METHOD": self.method,
            "SCRIPT_NAME": _path_encode(self.script_root),
            "PATH_INFO": _path_encode(self.path),
            "QUERY_STRING": qs,
            "SERVER_NAME": self.server_name,
            "SERVER_PORT": str(self.server_port),
            "HTTP_HOST": self.host,
            "SERVER_PROTOCOL": self.server_protocol,
            "CONTENT_TYPE": content_type or "",
            "CONTENT_LENGTH": str(content_length or "0"),
            "wsgi.version": self.wsgi_version,
            "wsgi.url_scheme": self.url_scheme,
            "wsgi.input": input_stream,
            "wsgi.errors": self.errors_stream,
            "wsgi.multithread": self.multithread,
            "wsgi.multiprocess": self.multiprocess,
            "wsgi.run_once": self.run_once,
        })
        for key, value in self.headers.to_wsgi_list():
            result["HTTP_%s" % key.upper().replace("-", "_")] = value
        if self.environ_overrides:
            result.update(self.environ_overrides)
        return result
Exemple #27
0
def handler(app, lambda_event, context):
    event = json.loads(lambda_event['body'])
    headers = Headers(event.get('headers', None))
    parsed_url = urlparse(event['path'])

    body = event.get('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('Content-Type', ''),
        'PATH_INFO': parsed_url.path,
        'QUERY_STRING': parsed_url.query,
        'REMOTE_ADDR': event.get('x-real-ip', ''),
        'REQUEST_METHOD': event['method'],
        'SCRIPT_NAME': '',
        'SERVER_NAME': headers.get('Host', 'lambda'),
        'SERVER_PORT': headers.get('X-Forwarded-Port', '80'),
        'SERVER_PROTOCOL': 'HTTP/1.1',
        'event': lambda_event['body'],
        '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):
            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)

    # 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 = {
        'statusCode': response.status_code,
        'headers': dict(new_headers),
        'body': '',
    }

    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
Exemple #28
0
 def test_cookie_unicode_keys(self):
     # Yes, this is technically against the spec but happens
     val = http.dump_cookie(u'fö', u'fö')
     self.assert_equal(val, wsgi_encoding_dance(u'fö="f\\303\\266"; Path=/', 'utf-8'))
     cookies = http.parse_cookie(val)
     self.assert_equal(cookies[u'fö'], u'fö')
Exemple #29
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 = ''

    environ = {
        'API_GATEWAY_AUTHORIZER':
            event[u'requestContext'].get(u'authorizer', None),
        'CONTENT_LENGTH':
            headers.get(u'Content-Length', str(len(event[u'body'] or ''))),
        'CONTENT_TYPE':
            headers.get(u'Content-Type', ''),
        'PATH_INFO':
            event[u'path'],
        'QUERY_STRING':
            url_encode(event.get(u'queryStringParameters', None) or {}),
        'REMOTE_ADDR':
            headers.get(u'X-Forwarded-For', '').split(', ')[0],
        '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',
        'context':
            context,
        'wsgi.errors':
            # Per PEP 333, this should be a "text mode" stream.
            StringIO(),
        'wsgi.input':
            BytesIO(),
        'wsgi.multiprocess':
            False,
        'wsgi.multithread':
            False,
        'wsgi.run_once':
            False,
        'wsgi.url_scheme':
            headers.get(u'X-Forwarded-Proto', 'http'),
        'wsgi.version':
            (1, 0),
    }

    body = event[u'body'] or ''
    encoded = wsgi_encoding_dance(body)
    if not PY2:
        encoded = bytes(encoded, 'utf-8', 'replace')

    # XXX: why do we have to supply an encoding here?
    # Doesn't wsgi_encoding_dance already do that?
    environ['wsgi.input'] = BytesIO(encoded)

    for key, value in environ.items():
        if PY2:
            if isinstance(value, basestring):  # noqa: F821
                environ[key] = wsgi_encoding_dance(value)
        else:
            if isinstance(value, str):
                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)

    errors = environ['wsgi.errors'].getvalue()
    if errors:
        print(errors)

    # 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:
            returndict['body'] = response.get_data(as_text=True)
        else:
            returndict['body'] = base64.b64encode(response.data).decode(
                'utf-8')
            returndict["isBase64Encoded"] = "true"

    return returndict