В этом мире написано много действительно хороших WebFrameWorks. Вы знаете эти веб -фреймворки на WSGI, так что давайте сейчас создадим свою оригинальную веб -структуру!
Если вы хотите узнать подробную информацию о спецификации WSGI, пожалуйста, обратитесь к PEP3333 Анкет Этот пост не заботится о каких -либо деталях, просто реализуя.
К счастью, у вас уже есть сервер WSGI, определенный по адресу wsgiref
модуль. Все, что вам нужно, это создание точки записи приложения WSGI.
Самое простое приложение похоже на ниже.
# app.py from wsgiref.simple_server import make_server def app(environ, start_response): start_response('200 OK', headers=[('Content-Type', 'text/plain:charset=utf-8')]) response = [b'my toy app'] return response with make_server('', 8088, app) as server: server.serve_forever()
Хм, это так скучно. Как правило, в WebFramework должна быть обработчики HTTP -запросов и системы маршрутизации. Так что я должен иметь это. Сначала я должен подумать о том, как использовать в реальном мире.
from wsgiref.simple_server import make_server things = {x: x.upper() for x in ('a', 'b', 'c')} def get_all_things(request): return ','.join(things.keys()) def create_things(request): # do something return 'ok' class App: def get(self, path, handler): # TODO return self def post(self, path, handler): # TODO return self def __call__(self, environment, start_response): # TODO return response def start(self): with make_server('', 8088, self) as server: server.serve_forever() app = App().get('/things', get_all_things).post('/things', create_things) app.start()
У этой веб -рамки есть
- Маршрутинг
- Строка запроса
- Параметр пути
- Только получить и публиковать обработчики
- Класс приложений включает в себя стартер WSGI Server
и нет
- Промежуточное программное обеспечение
- Любая обработка ошибок
- Статическая порция
- Шаблон
- Гибкий тип контента
- Перенаправить
- Еще еще еще..
Это реализует пример.
from urllib.parse import parse_qs from collections import defaultdict import re from wsgiref.simple_server import make_server class App: handler_map = defaultdict(dict) def _register(self, method_name, path, handler): self.handler_map[fr'^{path}$'].update({method_name: handler}) return self def get(self, path, handler): return self._register('get', path, handler) def post(self, path, handler): return self._register('post', path, handler) def _find_handler(self, path, method): for pattern, info in self.handler_map.items(): matched = re.match(pattern, path) if matched: return info[method], matched.groupdict() def __call__(self, environment, start_response): method = environment['REQUEST_METHOD'].lower() path = environment['PATH_INFO'] status = { 'get': '200 OK', 'post': '201 Created', }[method] start_response(status, headers=[('Content-Type', 'text/plain:charset=utf-8')]) request_body = { 'get': lambda: environment['QUERY_STRING'], 'post': lambda: environment['wsgi.input'].read(int(environment.get('CONTENT_LENGTH', 0))).decode(), }[method] handler, path_params = self._find_handler(path, method) response = handler(parse_qs(request_body), **path_params) return [response.encode()] def start(self): with make_server('', 8088, self) as server: server.serve_forever()
Пути маршрутизации и картирование обработчиков являются важными вещами.
Приложение
Пути маршрутизации воспоминаний и соответствующие обработчики в handler_map
Анкет
Смотрите _ Регистрация
Анкет
def _register(self, method_name, path, handler): self.handler_map[fr'^{path}$'].update({method_name: handler}) return self def get(self, path, handler): return self._register('get', path, handler) def post(self, path, handler): return self._register('post', path, handler)
Это справедливая обертка метода против каждого метода HTTP. Так Приложение
Получает запрашиваемый обратный путь.
Я выбор Re
модуль для обнаружения пути, такого как Джанго и т. Д.
Запрос на обработку в __call__
Анкет
def __call__(self, environment, start_response): method = environment['REQUEST_METHOD'].lower() path = environment['PATH_INFO'] status = { 'get': '200 OK', 'post': '201 Created', }[method] start_response(status, headers=[('Content-Type', 'text/plain:charset=utf-8')]) request_body = { 'get': lambda: environment['QUERY_STRING'], 'post': lambda: environment['wsgi.input'].read(int(environment.get('CONTENT_LENGTH', 0))).decode(), }[method]() handler, path_params = self._find_handler(path, method) response = handler(parse_qs(request_body), **path_params) return [response.encode()]
__call__
делает простые процессы.
- получает метод HTTP
- получает путь запроса
- Создает тело запроса, соответствующее методу HTTP
- Приносит обработчик
- вызывает обработчик
Хорошо, теперь я получаю свой собственный веб -фреймворк! Попробуйте бежать.
Начальный сервер.
$ python3 app.py
И запрос.
$ curl localhost:8088 $ curl localhost:8088/things $ curl localhost:8088/things/a $ curl -X POST -d 'x=X' localhost:8088/things
Наконец, я создал крошечную игрушку, а не продуктивную WebFramework с именем Томойо что немного сложнее, чем выше WebFramework.
Пока!
Оригинал: “https://dev.to/mtwtkman/build-your-we-framework-in-python-2nj0”