Ejemplo n.º 1
0
        def __handle_request(self):
            """Handle GET or POST request."""

            path = self.__normalize_path(self.path)

            # Try "/path" and "/path/"
            paths_to_try = [path]
            if path.endswith('/'):
                paths_to_try.append(path[:-1])
            else:
                paths_to_try.append(path + '/')

            # Try URLdecoded versions too
            unquoted_paths = []
            for path_to_try in paths_to_try:
                unquoted_paths.append(unquote(path_to_try))
            paths_to_try = paths_to_try + unquoted_paths

            page = None
            for path_to_try in paths_to_try:
                if path_to_try in self._pages:
                    page = self._pages[path_to_try]
                    path = path_to_try
                    break

            if page is None:
                self.send_response(HTTPStatus.NOT_FOUND)
                self.send_header("Content-Type", "text/plain")
                self.end_headers()
                self.__write_response_string("Not found :(")
                return

            page = self._pages[path]

            if isinstance(page, str) or isinstance(page, bytes):
                page = {'content': page}

            # HTTP auth
            if not self.__request_passed_authentication(page=page):
                self.send_response(HTTPStatus.UNAUTHORIZED)
                self.send_header("WWW-Authenticate",
                                 'Basic realm="HashServer"')
                self.end_headers()
                return

            # MC_REWRITE_TO_PYTHON: Decode strings from Perl's bytes
            if b'redirect' in page:
                # noinspection PyTypeChecker
                page['redirect'] = decode_object_from_bytes_if_needed(
                    page[b'redirect'])
            if b'http_status_code' in page:
                # noinspection PyTypeChecker
                page['http_status_code'] = page[b'http_status_code']
            if b'callback' in page:
                # noinspection PyTypeChecker
                page['callback'] = page[b'callback']
            if b'content' in page:
                # noinspection PyTypeChecker
                page['content'] = page[b'content']
            if b'header' in page:
                # noinspection PyTypeChecker
                page['header'] = decode_object_from_bytes_if_needed(
                    page[b'header'])

            if 'redirect' in page:
                redirect_url = page['redirect']
                http_status_code = page.get(
                    'http_status_code',
                    HashServer._DEFAULT_REDIRECT_STATUS_CODE)
                self.send_response(http_status_code)
                self.send_header("Content-Type", "text/html; charset=UTF-8")
                self.send_header('Location', redirect_url)
                self.end_headers()
                self.__write_response_string("Redirecting.")
                return

            elif 'callback' in page:
                callback_function = page['callback']

                post_data = None
                if self.command.lower() == 'post':
                    post_data = self.rfile.read(
                        int(self.headers['Content-Length'])).decode('utf-8')

                request = HashServer.Request(
                    port=self._port,
                    method=self.command,
                    path=self.path,
                    headers=dict(self.headers.items()),
                    content=post_data,
                )

                response = callback_function(request)

                if isinstance(response, str):
                    response = str.encode(response)

                # log.debug("Raw callback response: %s" % str(response))

                if b"\r\n\r\n" not in response:
                    raise McHashServerException(
                        "Response must include both HTTP headers and data, separated by CRLF."
                    )

                response_headers, response_content = response.split(
                    b"\r\n\r\n", 1)
                for response_header in response_headers.split(b"\r\n"):

                    if response_header.startswith(b'HTTP/'):
                        first_response_line = response_header.split(b' ',
                                                                    maxsplit=2)
                        if not 2 <= len(first_response_line) <= 3:
                            raise McHashServerException(
                                "Unexpected response line: %s" %
                                response_header)

                        # protocol = first_response_line[0]
                        http_status_code = first_response_line[1]
                        if len(first_response_line) == 3:
                            http_status_message = first_response_line[2]
                        else:
                            # Some responses might not have status message, e.g. respond with just "HTTP 200"
                            http_status_message = b''
                        self.send_response(
                            code=int(http_status_code.decode('utf-8')),
                            message=http_status_message.decode('utf-8'))

                    else:
                        header_name, header_value = response_header.split(
                            b':', 1)
                        header_value = header_value.strip()
                        self.send_header(header_name.decode('utf-8'),
                                         header_value.decode('utf-8'))

                self.end_headers()
                self.__write_response_string(response_content)

                return

            elif 'content' in page:
                content = page['content']

                headers = page.get('header',
                                   'Content-Type: text/html; charset=UTF-8')
                if not isinstance(headers, list):
                    headers = [headers]
                http_status_code = page.get('http_status_code', HTTPStatus.OK)

                self.send_response(http_status_code)

                for header in headers:
                    header_name, header_value = header.split(':', 1)
                    header_value = header_value.strip()
                    self.send_header(header_name, header_value)

                self.end_headers()
                self.__write_response_string(content)

                return

            else:
                log.info("Invalid page for path %s" % self.path)
                raise McHashServerException('Invalid page: %s' % str(page))
Ejemplo n.º 2
0
        def __handle_request(self):
            """Handle GET or POST request."""

            path = self.__normalize_path(self.path)

            # Try "/path" and "/path/"
            paths_to_try = [path]
            if path.endswith('/'):
                paths_to_try.append(path[:-1])
            else:
                paths_to_try.append(path + '/')

            # Try URLdecoded versions too
            unquoted_paths = []
            for path_to_try in paths_to_try:
                unquoted_paths.append(unquote(path_to_try))
            paths_to_try = paths_to_try + unquoted_paths

            page = None
            for path_to_try in paths_to_try:
                if path_to_try in self._pages:
                    page = self._pages[path_to_try]
                    path = path_to_try
                    break

            if page is None:
                self.send_response(HTTPStatus.NOT_FOUND)
                self.send_header("Content-Type", "text/plain")
                self.end_headers()
                self.__write_response_string("Not found :(")
                return

            page = self._pages[path]

            if isinstance(page, str) or isinstance(page, bytes):
                page = {'content': page}

            # HTTP auth
            if not self.__request_passed_authentication(page=page):
                self.send_response(HTTPStatus.UNAUTHORIZED)
                self.send_header("WWW-Authenticate", 'Basic realm="HashServer"')
                self.end_headers()
                return

            # MC_REWRITE_TO_PYTHON: Decode strings from Perl's bytes
            if b'redirect' in page:
                # noinspection PyTypeChecker
                page['redirect'] = decode_object_from_bytes_if_needed(page[b'redirect'])
            if b'http_status_code' in page:
                # noinspection PyTypeChecker
                page['http_status_code'] = page[b'http_status_code']
            if b'callback' in page:
                # noinspection PyTypeChecker
                page['callback'] = page[b'callback']
            if b'content' in page:
                # noinspection PyTypeChecker
                page['content'] = page[b'content']
            if b'header' in page:
                # noinspection PyTypeChecker
                page['header'] = decode_object_from_bytes_if_needed(page[b'header'])

            if 'redirect' in page:
                redirect_url = page['redirect']
                http_status_code = page.get('http_status_code', HashServer._DEFAULT_REDIRECT_STATUS_CODE)
                self.send_response(http_status_code)
                self.send_header("Content-Type", "text/html; charset=UTF-8")
                self.send_header('Location', redirect_url)
                self.end_headers()
                self.__write_response_string("Redirecting.")
                return

            elif 'callback' in page:
                callback_function = page['callback']

                post_data = None
                if self.command.lower() == 'post':
                    post_data = self.rfile.read(int(self.headers['Content-Length'])).decode('utf-8')

                request = HashServer.Request(
                    port=self._port,
                    method=self.command,
                    path=self.path,
                    headers=dict(self.headers.items()),
                    content=post_data,
                )

                response = callback_function(request)

                if isinstance(response, str):
                    response = str.encode(response)

                log.debug("Raw callback response: %s" % str(response))

                if b"\r\n\r\n" not in response:
                    raise McHashServerException("Response must include both HTTP headers and data, separated by CRLF.")

                response_headers, response_content = response.split(b"\r\n\r\n", 1)
                for response_header in response_headers.split(b"\r\n"):

                    if response_header.startswith(b'HTTP/'):
                        first_response_line = response_header.split(b' ', maxsplit=2)
                        if not 2 <= len(first_response_line) <= 3:
                            raise McHashServerException("Unexpected response line: %s" % response_header)

                        # protocol = first_response_line[0]
                        http_status_code = first_response_line[1]
                        if len(first_response_line) == 3:
                            http_status_message = first_response_line[2]
                        else:
                            # Some responses might not have status message, e.g. respond with just "HTTP 200"
                            http_status_message = b''
                        self.send_response(
                            code=int(http_status_code.decode('utf-8')),
                            message=http_status_message.decode('utf-8')
                        )

                    else:
                        header_name, header_value = response_header.split(b':', 1)
                        header_value = header_value.strip()
                        self.send_header(header_name.decode('utf-8'), header_value.decode('utf-8'))

                self.end_headers()
                self.__write_response_string(response_content)

                return

            elif 'content' in page:
                content = page['content']

                headers = page.get('header', 'Content-Type: text/html; charset=UTF-8')
                if not isinstance(headers, list):
                    headers = [headers]
                http_status_code = page.get('http_status_code', HTTPStatus.OK)

                self.send_response(http_status_code)

                for header in headers:
                    header_name, header_value = header.split(':', 1)
                    header_value = header_value.strip()
                    self.send_header(header_name, header_value)

                self.end_headers()
                self.__write_response_string(content)

                return

            else:
                log.info("Invalid page for path %s" % self.path)
                raise McHashServerException('Invalid page: %s' % str(page))