Пример #1
0
    def handle_event(self, event):
        # read headers
        if isinstance(event, h2.events.ResponseReceived):
            # TODO: look at content-encoding and set the decompressor
            headers = httputil.HTTPHeaders()
            for name, value in event.headers:
                headers.add(name, value)

            self.headers = headers
            self.code = int(headers.pop(':status'))
            self.reason = httplib.responses.get(self.code, 'Unknown')

            start_line = httputil.ResponseStartLine(
                'HTTP/2.0', self.code, self.reason
            )

            if self.request.header_callback is not None:
                # Reassemble the start line.
                self.request.header_callback('%s %s %s\r\n' % start_line)

                for k, v in self.headers.get_all():
                    self.request.header_callback('%s: %s\r\n' % (k, v))

                self.request.header_callback('\r\n')

        elif isinstance(event, h2.events.DataReceived):
            # TODO: decompress if necessary
            self._chunks.append(event.data)
        elif isinstance(event, h2.events.WindowUpdated):
            self.flow_control_window.produce(event.delta)
        elif isinstance(event, h2.events.StreamEnded):
            self.finish()
        elif isinstance(event, h2.events.StreamReset):
            self.finish()
Пример #2
0
 def handle_event(self, event):
     if isinstance(event, h2.events.ResponseReceived):
         headers = self.build_http_headers(event.headers)
         status_code = int(headers.pop(':status'))
         start_line = httputil.ResponseStartLine(
             'HTTP/2.0', status_code, http.client.responses[status_code]
         )
         self.headers_received(start_line, headers)
     elif isinstance(event, h2.events.DataReceived):
         self.data_received(event.data)
     elif isinstance(event, h2.events.StreamEnded):
         self._stream_ended = True
         if self._pending_body is not None:
             # we still have data to send, server responded earlier
             self._pending_body = None
             self.context.reset_stream(
                 self.stream_id, reason=ErrorCodes.NO_ERROR, flush=True
             )
         self.context.remove_stream_delegate(self.stream_id)
         if len(self._pushed_responses) == len(self._pushed_streams):
             self.finish()
     elif isinstance(event, h2.events.PushedStreamReceived):
         stream = self.from_push_stream(event)
         self._pushed_streams[event.pushed_stream_id] = stream
     elif isinstance(event, h2.events.StreamReset):
         self.context.reset_stream(self.stream_id)
     elif isinstance(event, h2.events.WindowUpdated):
         self.window_updated()
     else:
         logger.warning('ignored event: %r, %r', event, event.__dict__)
Пример #3
0
def fill_response_in(request, code, status, message, headers=None):
    headers = headers or httputil.HTTPHeaders()
    if "Content-Length" not in headers:
        content_length = str(len(message))
        request.logger.debug("Content-Length header was generated by the proxy: %s", content_length)
        headers.add("Content-Length", content_length)

    headers.add("X-Powered-By", "Cocaine")
    headers["X-XSS-Protection"] = "1; mode=block"
    request.logger.debug("Content-Length: %s", headers["Content-Length"])

    if getattr(request, "traceid", None) is not None:
        headers.add("X-Request-Id", request.traceid)

    if request.method == "HEAD":
        message = None

    request.connection.write_headers(
        # start_line
        httputil.ResponseStartLine(request.version, code, status),
        # headers
        headers,
        # data
        message)
    request.connection.finish()
    request.logger.info("finish request: %d %s %.2fms",
                        code, status, 1000.0 * request.request_time())
Пример #4
0
    def flush(self, include_footers=False, callback=None):
        chunk = b"".join(self._write_buffer)
        self._write_buffer = []
        if not self._headers_written:
            self._headers_written = True
            if self.request.method == "HEAD":
                chunk = None

            if hasattr(self, "_new_cookie"):
                for cookie in self._new_cookie.values():
                    self.add_header("Set-Cookie", cookie.OutputString(None))

            start_line = httputil.ResponseStartLine('', self._status_code,
                                                    self._reason)
            return self.request.connection.write_headers(start_line,
                                                         self._headers,
                                                         chunk,
                                                         callback=callback)
        else:
            if self.request.method != "HEAD":
                return self.request.connection.write(chunk, callback=callback)
            else:
                future = Future()
                future.set_result(None)
                return future
Пример #5
0
    def __call__(self, request: httputil.HTTPServerRequest) -> None:
        data = {}  # type: Dict[str, Any]
        response = []  # type: List[bytes]

        def start_response(
            status: str,
            headers: List[Tuple[str, str]],
            exc_info: Optional[Tuple["Optional[Type[BaseException]]",
                                     Optional[BaseException],
                                     Optional[TracebackType], ]] = None,
        ) -> Callable[[bytes], Any]:
            data["status"] = status
            data["headers"] = headers
            return response.append

        app_response = self.wsgi_application(self.environ(request),
                                             start_response)
        try:
            response.extend(app_response)
            body = b"".join(response)
        finally:
            if hasattr(app_response, "close"):
                app_response.close()  # type: ignore
        if not data:
            raise HurricaneWSGIException(
                "WSGI app did not call start_response")

        status_code_str, reason = data["status"].split(" ", 1)
        status_code = int(status_code_str)
        headers = data["headers"]  # type: List[Tuple[str, str]]
        header_set = set(k.lower() for (k, v) in headers)
        # handle WSGI's protocol assumption the web server to strip content from HEAD requests
        # and leave content length header as is.
        # - from Django documentation:
        # Web servers should automatically strip the content of responses to HEAD requests while leaving the headers
        # unchanged, so you may handle HEAD requests exactly like GET requests in your views. Since some software,
        # such as link checkers, rely on HEAD requests, you might prefer using require_safe instead of require_GET.
        if request.method != "HEAD":
            body = escape.utf8(body)
        else:
            body = ""
        if status_code != 304:
            if "content-length" not in header_set:
                headers.append(("Content-Length", str(len(body))))
            if "content-type" not in header_set:
                headers.append(("Content-Type", "text/html; charset=UTF-8"))
        if "server" not in header_set:
            headers.append(("Server", "TornadoServer/%s" % tornado.version))

        start_line = httputil.ResponseStartLine("HTTP/1.1", status_code,
                                                reason)
        header_obj = httputil.HTTPHeaders()
        for key, value in headers:
            header_obj.add(key, value)
        if request.connection is None:
            raise ValueError("No connection")
        request.connection.write_headers(start_line, header_obj, chunk=body)
        request.connection.finish()
        self._log(status_code, request)
Пример #6
0
def _write_token_mismatch_error(request):
    start_line = httputil.ResponseStartLine("", 400,
                                            "bad request: token mismatch")
    headers = httputil.HTTPHeaders({
        "Content-Type":
        "text/html; charset=UTF-8",
        "Date":
        httputil.format_timestamp(time.time()),
    })
    return request.connection.write_headers(start_line, headers, b"")
Пример #7
0
    def response(self, conn, src, dst):
        keep_alive = True
        resp = None
        conn = conn.copy()

        start_line = yield 
        while keep_alive and start_line is not None:
            body = ""
            headers = MultiOrderedDict()
            try:
                resp = httputil.ResponseStartLine(*start_line.split())
            except ValueError:
                if start_line != "":
                    self.log("Error: Malformed response start line: '{}'", start_line)
                start_line = yield
                continue
            while True:
                header_line = yield
                if header_line is None:
                    self.log("Warning: Terminated early?")
                    return
                if not header_line.strip():
                    break
                self.parse_header_line(headers, header_line.strip())

            if resp.version != "RTSP/1.0":
                self.log("Unknown version! '{}'", resp.version)

            if "content-length" in headers:
                try:
                    content_length = int(headers.last("content-length"))
                except ValueError:
                    content_length = None
                    self.log("Warning: invalid content length '{}'", headers.last('content-length'))
            else:
                content_length = 0


            if header_line is not None:
                conn["lbl_disable"](dst)
                while len(body) < content_length or content_length is None:
                    data = yield
                    if data is None:
                        break
                    body += data

            if "content-encoding" in headers:
                encoding = headers.last("content-encoding")
                if encoding in self.ENCODERS:
                    body = self.ENCODERS[encoding](body)

            conn["lbl_enable"](dst)
            conn["rtsp_headers"] = headers
            conn["rtsp_response"] = resp
            start_line = yield self.bubble(dst, conn, body)
Пример #8
0
    async def process_request(self, request):
        data = {}
        response = []

        def start_response(status, response_headers, exc_info=None):
            data["status"] = status
            data["headers"] = response_headers
            return response.append

        if config.features.forensic:
            in_label = "%s %s %s %s" % (
                request.remote_ip,
                request.headers.get("Remote-User", "-"),
                request.method,
                request.uri,
            )
        else:
            in_label = None
        wsgi = django.core.handlers.wsgi.WSGIHandler()
        app_response = await self.service.run_in_executor(
            "max",
            wsgi,
            tornado.wsgi.WSGIContainer.environ(request),
            start_response,
            _in_label=in_label,
        )
        try:
            response.extend(app_response)
            body = b"".join(response)
        finally:
            if hasattr(app_response, "close"):
                app_response.close()
        if not data:
            raise Exception("WSGI app did not call start_response")

        status_code, reason = data["status"].split(" ", 1)
        status_code = int(status_code)
        headers = data["headers"]
        header_set = set(k.lower() for (k, v) in headers)
        body = escape.utf8(body)
        if status_code != 304:
            if "content-length" not in header_set:
                headers.append(("Content-Length", str(len(body))))
            if "content-type" not in header_set:
                headers.append(("Content-Type", "text/html; charset=UTF-8"))
        if "server" not in header_set:
            headers.append(("Server", "TornadoServer/%s" % tornado.version))
        headers.append(("X-NOC-Backend", self.backend_id))
        data["status_code"] = status_code
        data["start_line"] = httputil.ResponseStartLine(
            "HTTP/1.1", status_code, reason)
        data["body"] = body
        return data
Пример #9
0
    def _handle_request(self, request):
        """
        Callback method called directly by the HTTP server. This method
        decodes received HTTP request and calls provided upper layer
        receive_cb() method which process decoded primitive and returns another
        primitive object as result. The resulting primitive object is encoded
        to HTTP response message and sent back to client.
        """
        primitive = self.decoder.decode(request)

        rsp_primitive = self.receive_cb(primitive)
        if not rsp_primitive:
            code = httplib.INTERNAL_SERVER_ERROR
            reason = status_codes._codes[code]
            start_line = httputil.ResponseStartLine(version='HTTP/1.1',
                                                    code=code,
                                                    reason=reason)
            request.connection.write_headers(start_line,
                                             httputil.HTTPHeaders())
            request.finish()
            return

        encoded = self.encoder.encode(rsp_primitive)

        headers = httputil.HTTPHeaders()
        headers.update(encoded.headers)

        code = encoded.status_code
        reason = encoded.reason

        start_line = httputil.ResponseStartLine(version='HTTP/1.1',
                                                code=code,
                                                reason=reason)
        request.connection.write_headers(start_line, headers)

        # set content
        if encoded.content:
            request.connection.write(json.dumps(encoded.content))

        request.finish()
Пример #10
0
    def __call__(self, request):
        data = {}
        response = []

        def start_response(status, response_headers, exc_info=None):
            data["status"] = status
            data["headers"] = response_headers
            return response.append

        app_response = self.wsgi_app(
            WSGIContainer.environ(request), start_response)
        try:
            response.extend(app_response)
            body = b"".join(response)
        finally:
            if hasattr(app_response, "close"):
                app_response.close()
        if not data:
            raise Exception("WSGI app did not call start_response")

        status_code, reason = data["status"].split(' ', 1)
        status_code = int(status_code)
        headers = data["headers"]
        header_set = set(k.lower() for (k, v) in headers)
        body = escape.utf8(body)

        if HEAD_END in body:
            body = body.replace(HEAD_END, self.script + HEAD_END)

        if status_code != 304:
            if "content-type" not in header_set:
                headers.append((
                    "Content-Type",
                    "application/octet-stream; charset=UTF-8"
                ))
            if "content-length" not in header_set:
                headers.append(("Content-Length", str(len(body))))

        if "server" not in header_set:
            headers.append(("Server", "LiveServer"))

        start_line = httputil.ResponseStartLine(
            "HTTP/1.1", status_code, reason
        )
        header_obj = httputil.HTTPHeaders()
        for key, value in headers:
            if key.lower() == 'content-length':
                value = str(len(body))
            header_obj.add(key, value)
        request.connection.write_headers(start_line, header_obj, chunk=body)
        request.connection.finish()
        self._log(status_code, request)
Пример #11
0
    def __call__(self, request: httputil.HTTPServerRequest) -> None:
        data = {}  # type: Dict[str, Any]
        response = []  # type: List[bytes]

        def start_response(
            status: str,
            headers: List[Tuple[str, str]],
            exc_info: Optional[
                Tuple[
                    "Optional[Type[BaseException]]",
                    Optional[BaseException],
                    Optional[TracebackType],
                ]
            ] = None,
        ) -> Callable[[bytes], Any]:
            data["status"] = status
            data["headers"] = headers
            return response.append

        app_response = self.wsgi_application(
            WSGIContainer.environ(request), start_response
        )
        try:
            response.extend(app_response)
            body = b"".join(response)
        finally:
            if hasattr(app_response, "close"):
                app_response.close()  # type: ignore
        if not data:
            raise Exception("WSGI app did not call start_response")

        status_code_str, reason = data["status"].split(" ", 1)
        status_code = int(status_code_str)
        headers = data["headers"]  # type: List[Tuple[str, str]]
        header_set = set(k.lower() for (k, v) in headers)
        body = escape.utf8(body)
        if status_code != 304:
            if "content-length" not in header_set:
                headers.append(("Content-Length", str(len(body))))
            if "content-type" not in header_set:
                headers.append(("Content-Type", "text/html; charset=UTF-8"))
        if "server" not in header_set:
            headers.append(("Server", "TornadoServer/%s" % tornado.version))

        start_line = httputil.ResponseStartLine("HTTP/1.1", status_code, reason)
        header_obj = httputil.HTTPHeaders()
        for key, value in headers:
            header_obj.add(key, value)
        assert request.connection is not None
        request.connection.write_headers(start_line, header_obj, chunk=body)
        request.connection.finish()
        self._log(status_code, request)
Пример #12
0
    def _execute(self, transforms, *args, **kwargs):
        if not self.check_connection():
            return

        self.open_args = [self.decode_argument(arg) for arg in args]
        self.open_kwargs = dict(
            (k, self.decode_argument(v, name=k)) for (k, v) in kwargs.items())

        start_line = httputil.ResponseStartLine('', self._status_code,
                                                self._reason)
        # EventSource only supports GET method
        if self.request.method != 'GET':
            self.error(405, 'Method Not Allowed')
        yield self.request.connection.write_headers(start_line, self._headers)

        self.open(*self.open_args, **self.open_kwargs)
Пример #13
0
 def handler(request):
     method, uri, version, headers, body = msgpack.unpackb(request.body)
     self.assertEqual(method, "PUT")
     self.assertEqual(uri, "/blabla")
     self.assertEqual(version, "1.1")
     self.assertEqual(body, "body")
     self.assertEqual(len(headers), 6)  # 4 + 2
     self.assertEqual(request.query_arguments["timeout"], ["30"])
     request.connection.write_headers(httputil.ResponseStartLine(
         "HTTP/1.1", 200, "OK"),
                                      httputil.HTTPHeaders(),
                                      chunk=msgpack.packb(
                                          (202, [("A", "B")])))
     request.connection.write("CHUNK1")
     request.connection.write("CHUNK2")
     request.connection.write("CHUNK3")
     request.connection.finish()
Пример #14
0
 def handle_event(self, event):
     if isinstance(event, h2.events.ResponseReceived):
         headers = self.build_http_headers(event.headers)
         status_code = int(headers.pop(':status'))
         start_line = httputil.ResponseStartLine(
             'HTTP/2.0', status_code, httplib.responses[status_code])
         self.headers_received(start_line, headers)
     elif isinstance(event, h2.events.DataReceived):
         self.data_received(event.data)
     elif isinstance(event, h2.events.StreamEnded):
         self._stream_ended = True
         self.context.remove_stream_delegate(self.stream_id)
         if len(self._pushed_responses) == len(self._pushed_streams):
             self.finish()
     elif isinstance(event, h2.events.PushedStreamReceived):
         stream = self.from_push_stream(event)
         self._pushed_streams[event.pushed_stream_id] = stream
     else:
         logger.warning('ignored event: %r, %r', event, event.__dict__)
Пример #15
0
def fill_response_in(request,
                     code,
                     status,
                     message,
                     headers=None,
                     chunked=False):
    headers = headers or httputil.HTTPHeaders()

    if not ("Content-Length" in headers or chunked):
        content_length = str(len(message))
        request.logger.debug(
            "Content-Length header was generated by the proxy: %s",
            content_length)
        headers.add("Content-Length", content_length)

    headers.add("X-Powered-By", "Cocaine")
    headers["X-XSS-Protection"] = "1; mode=block"

    if not chunked:
        request.logger.debug("Content-Length: %s", headers["Content-Length"])

    if getattr(request, "traceid", None) is not None:
        headers.add("X-Request-Id", request.traceid)

    if request.method == "HEAD":
        message = None

    request.connection.write_headers(
        # start_line
        httputil.ResponseStartLine(request.version, code, status),
        # headers
        headers,
        # data
        message)

    if not chunked:
        finalize_response(request, code, status)
Пример #16
0
 def finish(self) -> None:
     self.connection.write_headers(
         httputil.ResponseStartLine("HTTP/1.1", 404, "Not Found"),
         httputil.HTTPHeaders(),
     )
     self.connection.finish()