🚧 progress
This commit is contained in:
parent
7f88c01156
commit
738adee6c2
@ -27,3 +27,7 @@ class ParseError(SpiderwebException):
|
|||||||
|
|
||||||
class GeneralException(SpiderwebException):
|
class GeneralException(SpiderwebException):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class UnusedMiddleware(SpiderwebException):
|
||||||
|
pass
|
||||||
|
@ -12,6 +12,7 @@ from typing import Callable, Any
|
|||||||
|
|
||||||
from spiderweb.converters import * # noqa: F403
|
from spiderweb.converters import * # noqa: F403
|
||||||
from spiderweb.exceptions import APIError, ConfigError, ParseError, GeneralException
|
from spiderweb.exceptions import APIError, ConfigError, ParseError, GeneralException
|
||||||
|
from spiderweb.request import Request
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -95,7 +96,7 @@ class APIServer(HTTPServer):
|
|||||||
self.add_route(route, method)
|
self.add_route(route, method)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
super().__init__(server_address, HandlerClass)
|
super().__init__(server_address, self.handler_class)
|
||||||
except OSError:
|
except OSError:
|
||||||
raise GeneralException("Port already in use.")
|
raise GeneralException("Port already in use.")
|
||||||
|
|
||||||
@ -137,21 +138,32 @@ class APIHandler(BaseHTTPRequestHandler):
|
|||||||
# BaseHTTPRequestHandler uses for some weird reason
|
# BaseHTTPRequestHandler uses for some weird reason
|
||||||
_routes = {}
|
_routes = {}
|
||||||
|
|
||||||
|
def get_request(self):
|
||||||
|
return Request(
|
||||||
|
content="",
|
||||||
|
body="",
|
||||||
|
method=self.command,
|
||||||
|
headers=self.headers,
|
||||||
|
path=self.path
|
||||||
|
)
|
||||||
|
|
||||||
def do_GET(self):
|
def do_GET(self):
|
||||||
self.do_action()
|
request = self.get_request()
|
||||||
|
self.handle_request(request)
|
||||||
|
|
||||||
def do_POST(self):
|
def do_POST(self):
|
||||||
content = "{}"
|
content = "{}"
|
||||||
if self.headers["Content-Length"]:
|
if self.headers["Content-Length"]:
|
||||||
length = int(self.headers["Content-Length"])
|
length = int(self.headers["Content-Length"])
|
||||||
content = self.rfile.read(length)
|
content = self.rfile.read(length)
|
||||||
info = None
|
request = self.get_request()
|
||||||
|
request.content = content
|
||||||
if content:
|
if content:
|
||||||
try:
|
try:
|
||||||
info = json.loads(content)
|
request.json()
|
||||||
except json.JSONDecodeError:
|
except json.JSONDecodeError:
|
||||||
raise APIError(400, "Invalid JSON", content)
|
raise APIError(400, "Invalid JSON", content)
|
||||||
self.do_action(info)
|
self.handle_request(request)
|
||||||
|
|
||||||
def get_route(self, path) -> tuple[Callable, dict[str, Any]]:
|
def get_route(self, path) -> tuple[Callable, dict[str, Any]]:
|
||||||
for option in self._routes.keys():
|
for option in self._routes.keys():
|
||||||
@ -161,23 +173,22 @@ class APIHandler(BaseHTTPRequestHandler):
|
|||||||
)
|
)
|
||||||
raise APIError(404, "No route found")
|
raise APIError(404, "No route found")
|
||||||
|
|
||||||
def do_action(self, info=None):
|
def handle_request(self, request):
|
||||||
info = info or {}
|
|
||||||
try:
|
try:
|
||||||
url = urlparse.urlparse(self.path)
|
request.url = urlparse.urlparse(request.path)
|
||||||
|
|
||||||
handler, additional_args = self.get_route(url.path)
|
handler, additional_args = self.get_route(request.url.path)
|
||||||
|
|
||||||
if url.query:
|
if request.url.query:
|
||||||
params = urlparse.parse_qs(url.query)
|
params = urlparse.parse_qs(request.url.query)
|
||||||
else:
|
else:
|
||||||
params = {}
|
params = {}
|
||||||
|
|
||||||
info.update(params)
|
request.query_params = params
|
||||||
|
|
||||||
if handler:
|
if handler:
|
||||||
try:
|
try:
|
||||||
response = handler(info, **additional_args)
|
response = handler(request, **additional_args)
|
||||||
self.send_response(200)
|
self.send_response(200)
|
||||||
if response is None:
|
if response is None:
|
||||||
response = ""
|
response = ""
|
||||||
|
@ -0,0 +1,31 @@
|
|||||||
|
from typing import Optional, NoReturn
|
||||||
|
|
||||||
|
from spiderweb.request import Request
|
||||||
|
from spiderweb.response import HttpResponse
|
||||||
|
|
||||||
|
|
||||||
|
class SpiderwebMiddleware:
|
||||||
|
"""
|
||||||
|
All middleware should inherit from this class and have the following
|
||||||
|
(optional!) methods:
|
||||||
|
|
||||||
|
process_request(self, request) -> None or Response
|
||||||
|
process_response(self, request, response) -> None
|
||||||
|
|
||||||
|
Middleware can be used to modify requests and responses in a variety of ways.
|
||||||
|
If one of the two methods is not defined, the request or response will be passed
|
||||||
|
through unmodified.
|
||||||
|
|
||||||
|
If `process_request` returns
|
||||||
|
|
||||||
|
"""
|
||||||
|
def process_request(self, request: Request) -> HttpResponse | None:
|
||||||
|
# example of a middleware that sets a flag on the request
|
||||||
|
request.spiderweb = True
|
||||||
|
|
||||||
|
|
||||||
|
def process_response(self, request: Request, response: HttpResponse) -> NoReturn:
|
||||||
|
# example of a middleware that sets a header on the response
|
||||||
|
if hasattr(request, 'spiderweb'):
|
||||||
|
response['X-Spiderweb'] = 'true'
|
||||||
|
return response
|
17
spiderweb/request.py
Normal file
17
spiderweb/request.py
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import json
|
||||||
|
|
||||||
|
|
||||||
|
class Request:
|
||||||
|
def __init__(self, content=None, body=None, method=None, headers=None, path=None, url=None, query_params=None):
|
||||||
|
self.content: str = content
|
||||||
|
self.body: str = body
|
||||||
|
self.method: str = method
|
||||||
|
self.headers: dict[str] = headers
|
||||||
|
self.path: str = path
|
||||||
|
self.url = url
|
||||||
|
self.query_params = query_params
|
||||||
|
|
||||||
|
def json(self):
|
||||||
|
return json.loads(self.content)
|
||||||
|
|
||||||
|
|
14
spiderweb/response.py
Normal file
14
spiderweb/response.py
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
class HttpResponse:
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
|
class JsonResponse(HttpResponse):
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
|
class RedirectResponse(HttpResponse):
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
|
class TemplateResponse(HttpResponse):
|
||||||
|
...
|
Loading…
Reference in New Issue
Block a user