Пример #1
0
 async def index(path=None):
     response = await make_response('{}')
     if handler:
         data = await request.get_data()
         try:
             result = await run_sync(handler, request, data)
         except Exception as e:
             LOG.warning(
                 'Error in proxy handler for request %s %s: %s %s' %
                 (request.method, request.url, e, traceback.format_exc()))
             response.status_code = 500
             return response
         if result is not None:
             is_chunked = uses_chunked_encoding(result)
             result_content = result.content or ''
             response = await make_response(result_content)
             response.status_code = result.status_code
             if is_chunked:
                 response.headers.pop('Content-Length', None)
             result.headers.pop('Server', None)
             result.headers.pop('Date', None)
             response.headers.update(dict(result.headers))
             # set multi-value headers
             multi_value_headers = getattr(result, 'multi_value_headers',
                                           {})
             for key, values in multi_value_headers.items():
                 for value in values:
                     response.headers.add_header(key, value)
             # set default headers, if required
             if 'Content-Length' not in response.headers and not is_chunked:
                 response.headers['Content-Length'] = str(
                     len(result_content) if result_content else 0)
             if 'Connection' not in response.headers:
                 response.headers['Connection'] = 'close'
     return response
Пример #2
0
 async def index(path=None):
     response = await make_response("{}")
     if handler:
         data = await request.get_data()
         try:
             result = await run_sync(handler, request, data)
             if isinstance(result, Exception):
                 raise result
         except Exception as e:
             LOG.warning(
                 "Error in proxy handler for request %s %s: %s %s",
                 request.method,
                 request.url,
                 e,
                 traceback.format_exc(),
             )
             response.status_code = 500
             if isinstance(e, HTTPErrorResponse):
                 response.status_code = e.code or response.status_code
             return response
         if result is not None:
             # check if this is an async generator (for HTTP2 push event responses)
             async_gen = get_async_generator_result(result)
             if async_gen:
                 return async_gen
             # prepare and return regular response
             is_chunked = uses_chunked_encoding(result)
             result_content = result.content or ""
             response = await make_response(result_content)
             response.status_code = result.status_code
             if is_chunked:
                 response.headers.pop("Content-Length", None)
             result.headers.pop("Server", None)
             result.headers.pop("Date", None)
             headers = {
                 k: str(v).replace("\n", r"\n")
                 for k, v in result.headers.items()
             }
             response.headers.update(headers)
             # set multi-value headers
             multi_value_headers = getattr(result, "multi_value_headers",
                                           {})
             for key, values in multi_value_headers.items():
                 for value in values:
                     response.headers.add_header(key, value)
             # set default headers, if required
             if not is_chunked and request.method not in [
                     "OPTIONS", "HEAD"
             ]:
                 response_data = await response.get_data()
                 response.headers["Content-Length"] = str(
                     len(response_data or ""))
             if "Connection" not in response.headers:
                 response.headers["Connection"] = "close"
             # fix headers for OPTIONS requests (possible fix for Firefox requests)
             if request.method == "OPTIONS":
                 response.headers.pop("Content-Type", None)
                 if not response.headers.get("Cache-Control"):
                     response.headers["Cache-Control"] = "no-cache"
     return response
Пример #3
0
def add_reponse_metadata_headers(response):
    if response.headers.get('content-language') is None:
        response.headers['content-language'] = 'en-US'
    if response.headers.get('cache-control') is None:
        response.headers['cache-control'] = 'no-cache'
    if response.headers.get('content-encoding') is None:
        if not uses_chunked_encoding(response):
            response.headers['content-encoding'] = 'identity'
Пример #4
0
 async def index(path=None):
     response = await make_response('{}')
     if handler:
         data = await request.get_data()
         try:
             result = await run_sync(handler, request, data)
             if isinstance(result, Exception):
                 raise result
         except Exception as e:
             LOG.warning(
                 'Error in proxy handler for request %s %s: %s %s' %
                 (request.method, request.url, e, traceback.format_exc()))
             response.status_code = 500
             if isinstance(e, HTTPErrorResponse):
                 response.status_code = e.code or response.status_code
             return response
         if result is not None:
             # check if this is an async generator (for HTTP2 push event responses)
             async_gen = get_async_generator_result(result)
             if async_gen:
                 return async_gen
             # prepare and return regular response
             is_chunked = uses_chunked_encoding(result)
             result_content = result.content or ''
             response = await make_response(result_content)
             response.status_code = result.status_code
             if is_chunked:
                 response.headers.pop('Content-Length', None)
             result.headers.pop('Server', None)
             result.headers.pop('Date', None)
             headers = {
                 k: str(v).replace('\n', r'\n')
                 for k, v in result.headers.items()
             }
             response.headers.update(headers)
             # set multi-value headers
             multi_value_headers = getattr(result, 'multi_value_headers',
                                           {})
             for key, values in multi_value_headers.items():
                 for value in values:
                     response.headers.add_header(key, value)
             # set default headers, if required
             if not is_chunked and request.method not in [
                     'OPTIONS', 'HEAD'
             ]:
                 response_data = await response.get_data()
                 response.headers['Content-Length'] = str(
                     len(response_data or ''))
             if 'Connection' not in response.headers:
                 response.headers['Connection'] = 'close'
     return response
Пример #5
0
    def forward(self, method):
        data = self.data_bytes
        path = self.path
        forward_headers = CaseInsensitiveDict(self.headers)

        # force close connection
        connection_header = forward_headers.get('Connection') or ''
        if connection_header.lower() not in ['keep-alive', '']:
            self.close_connection = 1

        client_address = self.client_address[0]
        server_address = ':'.join(map(str, self.server.server_address))

        try:
            # run the actual response forwarding
            response = modify_and_forward(
                method=method,
                path=path,
                data_bytes=data,
                headers=forward_headers,
                forward_base_url=self.proxy.forward_base_url,
                listeners=self._listeners(),
                request_handler=self,
                client_address=client_address,
                server_address=server_address)

            # copy headers and return response
            self.send_response(response.status_code)

            # set content for chunked encoding
            is_chunked = uses_chunked_encoding(response)
            if is_chunked:
                response._content = create_chunked_data(response._content)

            # send headers
            content_length_sent = False
            for header_key, header_value in iteritems(response.headers):
                # filter out certain headers that we don't want to transmit
                if header_key.lower() not in ('transfer-encoding', 'date',
                                              'server'):
                    self.send_header(header_key, header_value)
                    content_length_sent = content_length_sent or header_key.lower(
                    ) == 'content-length'

            # fix content-type header if needed
            if not content_length_sent and not is_chunked:
                self.send_header(
                    'Content-Length',
                    '%s' % len(response.content) if response.content else 0)

            if isinstance(response, LambdaResponse):
                self.send_multi_value_headers(response.multi_value_headers)

            self.end_headers()
            if response.content and len(response.content):
                self.wfile.write(to_bytes(response.content))
        except Exception as e:
            trace = str(traceback.format_exc())
            conn_errors = ('ConnectionRefusedError', 'NewConnectionError',
                           'Connection aborted', 'Unexpected EOF',
                           'Connection reset by peer',
                           'cannot read from timed out object')
            conn_error = any(e in trace for e in conn_errors)
            error_msg = 'Error forwarding request: %s %s' % (e, trace)
            if 'Broken pipe' in trace:
                LOG.warn(
                    'Connection prematurely closed by client (broken pipe).')
            elif not self.proxy.quiet or not conn_error:
                LOG.error(error_msg)
                if is_local_test_mode():
                    # During a test run, we also want to print error messages, because
                    # log messages are delayed until the entire test run is over, and
                    # hence we are missing messages if the test hangs for some reason.
                    print('ERROR: %s' % error_msg)
            self.send_response(502)  # bad gateway
            self.end_headers()
            # force close connection
            self.close_connection = 1
        finally:
            try:
                self.wfile.flush()
            except Exception as e:
                LOG.warning('Unable to flush write file: %s' % e)