- def do_GET(self) -> None:
- """Handle any GET request."""
- try:
- self._init_handling()
- if hasattr(self, f'do_GET_{self._site}'):
- template = f'{self._site}.html'
- ctx = getattr(self, f'do_GET_{self._site}')()
- html = self.server.jinja.get_template(template).render(**ctx)
- self._send_html(html)
- elif '' == self._site:
- self._redirect('/day')
- else:
- raise NotFoundException(f'Unknown page: /{self._site}')
- except HandledException as error:
- self._send_msg(error, code=error.http_code)
- finally:
- self.conn.close()
+ def send_html(self, html: str, code: int = 200) -> None:
+ """Send HTML as proper HTTP response."""
+ self.send_response(code)
+ self.end_headers()
+ self.wfile.write(bytes(html, 'utf-8'))
+
+ @staticmethod
+ def _wrap(method: str, not_found_msg: str
+ ) -> Callable[..., Callable[..., None]]:
+ def decorator(http_method_handler: Callable[..., str]
+ ) -> Callable[..., None]:
+ def wrapper(self: TaskHandler) -> None:
+ try:
+ self.conn = DatabaseConnection(self.server.db)
+ parsed_url = urlparse(self.path)
+ self.site = path_split(parsed_url.path)[1]
+ params = parse_qs(parsed_url.query, strict_parsing=True)
+ self.params = InputsParser(params, False)
+ handler_name = f'do_{method}_{self.site}'
+ if hasattr(self, handler_name):
+ handler = getattr(self, handler_name)
+ redir_target = http_method_handler(self, handler)
+ if redir_target:
+ self.send_response(302)
+ self.send_header('Location', redir_target)
+ self.end_headers()
+ else:
+ msg = f'{not_found_msg}: {self.site}'
+ raise NotFoundException(msg)
+ except HandledException as error:
+ html = self.server.jinja.\
+ get_template('msg.html').render(msg=error)
+ self.send_html(html, error.http_code)
+ finally:
+ self.conn.close()
+ return wrapper
+ return decorator
+
+ @_wrap('GET', 'Unknown page')
+ def do_GET(self, handler: Callable[..., str | dict[str, object]]
+ ) -> str | None:
+ """Render page with result of handler, or redirect if result is str."""
+ template = f'{self.site}.html'
+ ctx_or_redir = handler()
+ if str == type(ctx_or_redir):
+ return ctx_or_redir
+ assert isinstance(ctx_or_redir, dict)
+ html = self.server.jinja.get_template(template).render(**ctx_or_redir)
+ self.send_html(html)
+ return None
+
+ @_wrap('POST', 'Unknown POST target')
+ def do_POST(self, handler: Callable[..., str]) -> str:
+ """Handle POST with handler, prepare redirection to result."""
+ length = int(self.headers['content-length'])
+ postvars = parse_qs(self.rfile.read(length).decode(),
+ keep_blank_values=True, strict_parsing=True)
+ self.form_data = InputsParser(postvars)
+ redir_target = handler()
+ self.conn.commit()
+ return redir_target