Exemplo n.º 1
0
    def transform_request(self) -> None:
        loop = self.server.loop
        # FIXME: should we shutdown() read or write depending on what
        # we do here ? (i.e. SHUT_RD for GETs, SHUT_WD for sources)

        self.server.logger.info(
            "%s:%s %s %s %s, request headers: %s",
            self.address[0],
            self.address[1],
            self.request_parser.request_method,
            self.request_parser.request_path,
            self.request_parser.http_version,
            self.request_parser.headers,
        )

        # Squash any consecutive / into one
        self.request_parser.request_path = re.sub(
            b"//+", b"/", self.request_parser.request_path)

        self.server.request_in(self.request_parser, self.sock)

        # Authorization
        for auth_handler in self.server.auth_handlers:
            auth_result = auth_handler.authorize(self.address,
                                                 self.request_parser)
            if auth_result is None:
                continue
            elif not isinstance(auth_result, HTTPResponse):
                # Wrong response from auth handler
                raise RuntimeError(
                    "Wrong response from authorization handler %s" %
                    auth_handler)
            elif auth_result.status == 200:
                # Request authorized
                break
            else:
                # Access denied
                loop.register(
                    helpers.HTTPEventHandler(self.server, self.sock,
                                             self.address, self.request_parser,
                                             auth_result),
                    looping.POLLOUT,
                )
                return

        path = self.request_parser.request_path.decode("ascii")

        response = None

        if self.request_parser.request_method in [b"PUT", b"SOURCE", b"POST"]:
            self.server.register_source(
                sources.find_source(self.server, self.sock, self.address,
                                    self.request_parser, path))
        elif self.request_parser.request_method in [b"GET", b"HEAD"]:
            # New client

            # Is our client asking for status ?
            if path in self.server.status_handlers:
                # FIXME: should we handle HEAD requests ?
                if self.request_parser.request_method not in [b"GET"]:
                    response = HTTPResponse(405, b"Method Not Allowed")
                else:
                    loop.register(
                        self.server.status_handlers[path].get_status(
                            self.sock, self.address, self.request_parser),
                        looping.POLLOUT,
                    )
            else:
                # New client for one of our sources
                if path in self.server.sources:
                    # Used by some clients to know the stream type
                    # before attempting playout
                    if self.request_parser.request_method in [b"HEAD"]:
                        source = list(self.server.sources[path].keys())[0]
                        response = HTTPResponse(
                            200,
                            b"OK",
                            {
                                b"Content-Type":
                                bytes(source.content_type, "ascii"),
                                b"Content-Length":
                                None,
                                b"Connection":
                                b"close",
                            },
                        )
                    # Check for server clients limit
                    elif self.server.clients_limit is not None and (
                            self.server.clients_limit
                            == self.server.clients_connected):
                        response = HTTPResponse(
                            503, b"Cannot handle response."
                            b" Too many clients.")
                    else:
                        # FIXME: proper source selection
                        source = random.choice(
                            list(self.server.sources[path].keys()))
                        new_client = clients.find_client(
                            self.server, source, self.sock, self.address,
                            self.request_parser)
                        # FIXME: this call may actually need to instatiate
                        # the client itself (e.g. if the source needs some
                        # dedicated code in its clients)
                        source.new_client(new_client)
                        # FIXME: see above wrt to proper source selection
                        self.server.sources[path][source]["clients"][
                            new_client.fileno()] = new_client
                        self.server.clients_connected += 1
                        loop.register(new_client, looping.POLLOUT)
                else:
                    # Stream does not exist
                    response = HTTPResponse(404, b"Stream Not Found")

        else:
            # Unknown HTTP request method
            response = HTTPResponse(405, b"Method Not Allowed")

        if response is not None:
            loop.register(
                helpers.HTTPEventHandler(self.server, self.sock, self.address,
                                         self.request_parser, response),
                looping.POLLOUT,
            )
Exemplo n.º 2
0
    def transform_request(self):
        # FIXME: should we shutdown() read or write depending on what
        # we do here ? (i.e. SHUT_RD for GETs, SHUT_WD for sources)

        self.server.logger.debug('%s %s %s %s, request headers: %s',
                                self.address,
                                self.request_parser.request_method,
                                self.request_parser.request_path,
                                self.request_parser.http_version,
                                self.request_parser.headers)

        # Squash any consecutive / into one
        self.request_parser.request_path = re.sub('//+', '/',
                                                  self.request_parser.request_path)

        self.server.request_in(self.request_parser, self.sock)

        # Authorization
        for auth_handler in self.server.auth_handlers:
            auth_result = auth_handler.authorize(self.address, self.request_parser)
            if auth_result is None:
                continue
            elif not isinstance(auth_result, HTTPResponse):
                # Wrong response from auth handler
                raise RuntimeError('Wrong response from authorization handler %s' % auth_handler)
            elif auth_result.status == 200:
                # Request authorized
                break
            else:
                # Access denied
                response_handler = helpers.HTTPEventHandler(
                    self.server, self.sock, self.address,
                    self.request_parser, auth_result)
                response_handler.start()
                self.follow_up()
                return

        path = self.request_parser.request_path

        response = None

        if self.request_parser.request_method in [b'PUT', b'SOURCE', b'POST']:
            self.server.register_source(sources.find_source(
                self.server, self.sock, self.address, self.request_parser, path))
        elif self.request_parser.request_method in [b'GET']:
            # New client

            # Is our client asking for status ?
            if path in self.server.status_handlers:
                response_handler = self.server.status_handlers[path].get_status(
                    self.sock, self.address, self.request_parser)
                response_handler.start()
                self.follow_up()
            else:
                # New client for one of our sources
                if self.server.sources.get(path, []):
                    # Check for server clients limit
                    if self.server.clients_limit is not None and (
                        self.server.clients_limit == self.server.clients_connected):
                        response = HTTPResponse(503, b'Cannot handle response.'
                                                b' Too many clients.')
                    else:
                        # FIXME: proper source selection
                        source = random.choice(self.server.sources[path].keys())
                        new_client = clients.find_client(self.server,
                                                         source,
                                                         self.sock,
                                                         self.address,
                                                         self.request_parser)
                        # FIXME: this call may actually need to instatiate
                        # the client itself (e.g. if the source needs some
                        # dedicated code in its clients)
                        source.new_client(new_client)
                        # FIXME refactor following lines in source.new_client
                        new_client.start()
                        self.follow_up()
                        # FIXME: see above wrt to proper source selection
                        self.server.sources[path][source]['clients'][new_client.fileno()] = new_client
                        self.server.clients_connected += 1
                else:
                    # Stream does not exist
                    response = HTTPResponse(404, b'Stream Not Found')

        else:
            # Unknown HTTP request method
            response = HTTPResponse(405, b'Method Not Allowed')

        if response is not None:
            response_handler = helpers.HTTPEventHandler(
                self.server, self.sock, self.address,
                self.request_parser, response)
            response_handler.start()
            self.follow_up()