示例#1
0
    def request(self, conn, src, dst):
        keep_alive = True
        req = None
        conn = conn.copy()

        req_line = yield 
        while keep_alive and req_line is not None:
            body = ""
            headers = MultiOrderedDict()
            try:
                req = httputil.RequestStartLine(*req_line.split())
            except ValueError:
                if req_line != "":
                    self.log("Error: Malformed request start line: '{}'", req_line)
                req_line = yield
                continue
            while True:
                header_line = yield
                if header_line is None:
                    break
                if not header_line.strip():
                    break
                self.parse_header_line(headers, header_line.strip())

            if req.version != "RTSP/1.0":
                self.log("Unknown version! '{}'", req.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_request"] = req
            req_line = yield self.bubble(dst, conn, body)
    def request_received(self, event, delegate, data):
        self.event = event
        self.stream_id = event.stream_id
        log.debug("_request_received: {}".format(self.stream_id))
        if event.headers:
            with _ExceptionLoggingContext(app_log):
                hd = {k: v for k, v in event.headers}
                start_line = httputil.RequestStartLine(
                    method=hd[':method'], path=hd[':path'],
                    version='HTTP/2.0')
                header_future = delegate.headers_received(
                    start_line,
                    httputil.HTTPHeaders(hd)
                )
                if header_future is not None:
                    yield header_future

        delegate.data_received(data)
        with _ExceptionLoggingContext(app_log):
            delegate.finish()
        raise gen.Return(True)
示例#3
0
 def _on_connect(self, stream):
     if self.final_callback is None:
         # final_callback is cleared if we've hit our timeout.
         stream.close()
         return
     self.stream = stream
     self.stream.set_close_callback(self._on_close)
     self._remove_timeout()
     if self.final_callback is None:
         return
     if self.request.request_timeout:
         self._timeout = self.io_loop.add_timeout(
             self.start_time + self.request.request_timeout,
             stack_context.wrap(self._on_timeout))
     if (self.request.method not in self._SUPPORTED_METHODS
             and not self.request.allow_nonstandard_methods):
         raise KeyError("unknown method %s" % self.request.method)
     for key in ('network_interface', 'proxy_host', 'proxy_port',
                 'proxy_username', 'proxy_password'):
         if getattr(self.request, key, None):
             raise NotImplementedError('%s not supported' % key)
     if "Connection" not in self.request.headers:
         self.request.headers["Connection"] = "close"
     if "Host" not in self.request.headers:
         if '@' in self.parsed.netloc:
             self.request.headers["Host"] = self.parsed.netloc.rpartition(
                 '@')[-1]
         else:
             self.request.headers["Host"] = self.parsed.netloc
     username, password = None, None
     if self.parsed.username is not None:
         username, password = self.parsed.username, self.parsed.password
     elif self.request.auth_username is not None:
         username = self.request.auth_username
         password = self.request.auth_password or ''
     if username is not None:
         if self.request.auth_mode not in (None, "basic"):
             raise ValueError("unsupported auth_mode %s",
                              self.request.auth_mode)
         auth = utf8(username) + b":" + utf8(password)
         self.request.headers["Authorization"] = (b"Basic " +
                                                  base64.b64encode(auth))
     if self.request.user_agent:
         self.request.headers["User-Agent"] = self.request.user_agent
     if not self.request.allow_nonstandard_methods:
         if self.request.method in ("POST", "PATCH", "PUT"):
             if (self.request.body is None
                     and self.request.body_producer is None):
                 raise AssertionError(
                     'Body must not be empty for "%s" request' %
                     self.request.method)
         else:
             if (self.request.body is not None
                     or self.request.body_producer is not None):
                 raise AssertionError(
                     'Body must be empty for "%s" request' %
                     self.request.method)
     if self.request.expect_100_continue:
         self.request.headers["Expect"] = "100-continue"
     if self.request.body is not None:
         # When body_producer is used the caller is responsible for
         # setting Content-Length (or else chunked encoding will be used).
         self.request.headers["Content-Length"] = str(len(
             self.request.body))
     if (self.request.method == "POST"
             and "Content-Type" not in self.request.headers):
         self.request.headers[
             "Content-Type"] = "application/x-www-form-urlencoded"
     if self.request.decompress_response:
         self.request.headers["Accept-Encoding"] = "gzip"
     req_path = ((self.parsed.path or '/') +
                 (('?' + self.parsed.query) if self.parsed.query else ''))
     self.stream.set_nodelay(True)
     self.connection = HTTP1Connection(
         self.stream, True,
         HTTP1ConnectionParameters(
             no_keep_alive=True,
             max_header_size=self.max_header_size,
             decompress=self.request.decompress_response), self._sockaddr)
     start_line = httputil.RequestStartLine(self.request.method, req_path,
                                            'HTTP/1.1')
     self.connection.write_headers(start_line, self.request.headers)
     if self.request.expect_100_continue:
         self._read_response()
     else:
         self._write_body(True)
示例#4
0
 def _on_connect(self, stream):
     if self.final_callback is None:
         # final_callback is cleared if we've hit our timeout.
         stream.close()
         return
     self.stream = stream
     self.stream.set_close_callback(self.on_connection_close)
     self._remove_timeout()
     if self.final_callback is None:
         return
     if self.request.request_timeout:
         self._timeout = self.io_loop.add_timeout(
             self.start_time + self.request.request_timeout,
             stack_context.wrap(
                 functools.partial(self._on_timeout, "during request")))
     if (self.request.method not in self._SUPPORTED_METHODS
             and not self.request.allow_nonstandard_methods):
         raise KeyError("unknown method %s" % self.request.method)
     for key in ('network_interface', 'proxy_host', 'proxy_port',
                 'proxy_username', 'proxy_password', 'proxy_auth_mode'):
         if getattr(self.request, key, None):
             raise NotImplementedError('%s not supported' % key)
     if "Connection" not in self.request.headers:
         self.request.headers["Connection"] = "close"
     if "Host" not in self.request.headers:
         if '@' in self.parsed.netloc:
             self.request.headers["Host"] = self.parsed.netloc.rpartition(
                 '@')[-1]
         else:
             self.request.headers["Host"] = self.parsed.netloc
     username, password = None, None
     if self.parsed.username is not None:
         username, password = self.parsed.username, self.parsed.password
     elif self.request.auth_username is not None:
         username = self.request.auth_username
         password = self.request.auth_password or ''
     if username is not None:
         if self.request.auth_mode not in (None, "basic"):
             raise ValueError("unsupported auth_mode %s",
                              self.request.auth_mode)
         auth = utf8(username) + b":" + utf8(password)
         self.request.headers["Authorization"] = (b"Basic " +
                                                  base64.b64encode(auth))
     if self.request.user_agent:
         self.request.headers["User-Agent"] = self.request.user_agent
     if not self.request.allow_nonstandard_methods:
         # Some HTTP methods nearly always have bodies while others
         # almost never do. Fail in this case unless the user has
         # opted out of sanity checks with allow_nonstandard_methods.
         body_expected = self.request.method in ("POST", "PATCH", "PUT")
         body_present = (self.request.body is not None
                         or self.request.body_producer is not None)
         if ((body_expected and not body_present)
                 or (body_present and not body_expected)):
             raise ValueError(
                 'Body must %sbe None for method %s (unless '
                 'allow_nonstandard_methods is true)' %
                 ('not ' if body_expected else '', self.request.method))
     if self.request.expect_100_continue:
         self.request.headers["Expect"] = "100-continue"
     if self.request.body is not None:
         # When body_producer is used the caller is responsible for
         # setting Content-Length (or else chunked encoding will be used).
         self.request.headers["Content-Length"] = str(len(
             self.request.body))
     if (self.request.method == "POST"
             and "Content-Type" not in self.request.headers):
         self.request.headers[
             "Content-Type"] = "application/x-www-form-urlencoded"
     if self.request.decompress_response:
         self.request.headers["Accept-Encoding"] = "gzip"
     req_path = ((self.parsed.path or '/') +
                 (('?' + self.parsed.query) if self.parsed.query else ''))
     self.connection = self._create_connection(stream)
     start_line = httputil.RequestStartLine(self.request.method, req_path,
                                            '')
     self.connection.write_headers(start_line, self.request.headers)
     if self.request.expect_100_continue:
         self._read_response()
     else:
         self._write_body(True)
示例#5
0
    async def run(self) -> None:
        try:
            self.parsed = urllib.parse.urlsplit(_unicode(self.request.url))
            if self.parsed.scheme not in ("http", "https"):
                raise ValueError("Unsupported url scheme: %s" %
                                 self.request.url)
            # urlsplit results have hostname and port results, but they
            # didn't support ipv6 literals until python 2.7.
            netloc = self.parsed.netloc
            if "@" in netloc:
                userpass, _, netloc = netloc.rpartition("@")
            host, port = httputil.split_host_and_port(netloc)
            if port is None:
                port = 443 if self.parsed.scheme == "https" else 80
            if re.match(r"^\[.*\]$", host):
                # raw ipv6 addresses in urls are enclosed in brackets
                host = host[1:-1]
            self.parsed_hostname = host  # save final host for _on_connect

            if self.request.allow_ipv6 is False:
                af = socket.AF_INET
            else:
                af = socket.AF_UNSPEC

            ssl_options = self._get_ssl_options(self.parsed.scheme)

            source_ip = None
            if self.request.network_interface:
                if is_valid_ip(self.request.network_interface):
                    source_ip = self.request.network_interface
                else:
                    raise ValueError(
                        "Unrecognized IPv4 or IPv6 address for network_interface, got %r"
                        % (self.request.network_interface, ))

            timeout = min(self.request.connect_timeout,
                          self.request.request_timeout)
            if timeout:
                self._timeout = self.io_loop.add_timeout(
                    self.start_time + timeout,
                    functools.partial(self._on_timeout, "while connecting"),
                )
                stream = await self.tcp_client.connect(
                    host,
                    port,
                    af=af,
                    ssl_options=ssl_options,
                    max_buffer_size=self.max_buffer_size,
                    source_ip=source_ip,
                )

                if self.final_callback is None:
                    # final_callback is cleared if we've hit our timeout.
                    stream.close()
                    return
                self.stream = stream
                self.stream.set_close_callback(self.on_connection_close)
                self._remove_timeout()
                if self.final_callback is None:
                    return
                if self.request.request_timeout:
                    self._timeout = self.io_loop.add_timeout(
                        self.start_time + self.request.request_timeout,
                        functools.partial(self._on_timeout, "during request"),
                    )
                if (self.request.method not in self._SUPPORTED_METHODS
                        and not self.request.allow_nonstandard_methods):
                    raise KeyError("unknown method %s" % self.request.method)
                for key in (
                        "proxy_host",
                        "proxy_port",
                        "proxy_username",
                        "proxy_password",
                        "proxy_auth_mode",
                ):
                    if getattr(self.request, key, None):
                        raise NotImplementedError("%s not supported" % key)
                if "Connection" not in self.request.headers:
                    self.request.headers["Connection"] = "close"
                if "Host" not in self.request.headers:
                    if "@" in self.parsed.netloc:
                        self.request.headers[
                            "Host"] = self.parsed.netloc.rpartition("@")[-1]
                    else:
                        self.request.headers["Host"] = self.parsed.netloc
                username, password = None, None
                if self.parsed.username is not None:
                    username, password = self.parsed.username, self.parsed.password
                elif self.request.auth_username is not None:
                    username = self.request.auth_username
                    password = self.request.auth_password or ""
                if username is not None:
                    assert password is not None
                    if self.request.auth_mode not in (None, "basic"):
                        raise ValueError("unsupported auth_mode %s",
                                         self.request.auth_mode)
                    self.request.headers[
                        "Authorization"] = "Basic " + _unicode(
                            base64.b64encode(
                                httputil.encode_username_password(
                                    username, password)))
                if self.request.user_agent:
                    self.request.headers[
                        "User-Agent"] = self.request.user_agent
                if not self.request.allow_nonstandard_methods:
                    # Some HTTP methods nearly always have bodies while others
                    # almost never do. Fail in this case unless the user has
                    # opted out of sanity checks with allow_nonstandard_methods.
                    body_expected = self.request.method in ("POST", "PATCH",
                                                            "PUT")
                    body_present = (self.request.body is not None
                                    or self.request.body_producer is not None)
                    if (body_expected
                            and not body_present) or (body_present
                                                      and not body_expected):
                        raise ValueError(
                            "Body must %sbe None for method %s (unless "
                            "allow_nonstandard_methods is true)" %
                            ("not " if body_expected else "",
                             self.request.method))
                if self.request.expect_100_continue:
                    self.request.headers["Expect"] = "100-continue"
                if self.request.body is not None:
                    # When body_producer is used the caller is responsible for
                    # setting Content-Length (or else chunked encoding will be used).
                    self.request.headers["Content-Length"] = str(
                        len(self.request.body))
                if (self.request.method == "POST"
                        and "Content-Type" not in self.request.headers):
                    self.request.headers[
                        "Content-Type"] = "application/x-www-form-urlencoded"
                if self.request.decompress_response:
                    self.request.headers["Accept-Encoding"] = "gzip"
                req_path = (self.parsed.path or "/") + (
                    ("?" + self.parsed.query) if self.parsed.query else "")
                self.connection = self._create_connection(stream)
                start_line = httputil.RequestStartLine(self.request.method,
                                                       req_path, "")
                self.connection.write_headers(start_line, self.request.headers)
                if self.request.expect_100_continue:
                    await self.connection.read_response(self)
                else:
                    await self._write_body(True)
        except Exception:
            if not self._handle_exception(*sys.exc_info()):
                raise