From 4d85b32efd71d0fec03e80aa4b0d6e74a2a06735 Mon Sep 17 00:00:00 2001 From: bvn13 Date: Wed, 5 Jun 2024 23:22:58 +0300 Subject: [PATCH] simple web server --- .gitignore | 3 ++ .vscode/launch.json | 17 +++++++++ Dockerfile | 0 README.md | 0 docker-compose.yaml | 0 requirements.txt | 3 ++ src/main.py | 91 +++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 114 insertions(+) create mode 100644 .gitignore create mode 100644 .vscode/launch.json create mode 100644 Dockerfile create mode 100644 README.md create mode 100644 docker-compose.yaml create mode 100644 requirements.txt create mode 100644 src/main.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3333883 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +local.env +**/*.pyc +test/ \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..0fc8fb2 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,17 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "Python Debugger: main.py", + "type": "debugpy", + "request": "launch", + "program": "~/.local/bin/gunicorn", + //"console": "integratedTerminal", + "args": ["main:app", "--chdir=src", "--bind=127.0.0.1:8080", "--reload", "-w", "1", "--timeout=7200"], + "envFile": "${workspaceFolder}/local.env" + } + ] +} \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..e69de29 diff --git a/README.md b/README.md new file mode 100644 index 0000000..e69de29 diff --git a/docker-compose.yaml b/docker-compose.yaml new file mode 100644 index 0000000..e69de29 diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..d010166 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,3 @@ +falcon==3.1.3 +gunicorn==22.0.0 +greenlet==3.0.3 \ No newline at end of file diff --git a/src/main.py b/src/main.py new file mode 100644 index 0000000..da45ecd --- /dev/null +++ b/src/main.py @@ -0,0 +1,91 @@ +import falcon +import json + + +class RequireJSON: + def process_request(self, req, resp): + if not req.client_accepts_json: + raise falcon.HTTPNotAcceptable( + description='This API only supports responses encoded as JSON.', + href='http://docs.examples.com/api/json', + ) + + if req.method in ('POST', 'PUT'): + if req.content_type == None or 'application/json' not in req.content_type: + raise falcon.HTTPUnsupportedMediaType( + title='This API only supports requests encoded as JSON.', + href='http://docs.examples.com/api/json', + ) + +class JSONTranslator: + # NOTE: Normally you would simply use req.media and resp.media for + # this particular use case; this example serves only to illustrate + # what is possible. + + def process_request(self, req, resp): + # req.stream corresponds to the WSGI wsgi.input environ variable, + # and allows you to read bytes from the request body. + # + # See also: PEP 3333 + if req.content_length in (None, 0): + # Nothing to do + return + + body = req.stream.read() + if not body: + raise falcon.HTTPBadRequest( + title='Empty request body', + description='A valid JSON document is required.', + ) + + try: + req.context.doc = json.loads(body.decode('utf-8')) + + except (ValueError, UnicodeDecodeError): + description = ( + 'Could not decode the request body. The ' + 'JSON was incorrect or not encoded as ' + 'UTF-8.' + ) + + raise falcon.HTTPBadRequest(title='Malformed JSON', description=description) + + def process_response(self, req, resp, resource, req_succeeded): + if not hasattr(resp.context, 'result'): + return + + resp.text = json.dumps(resp.context.result) + + +def max_body(limit): + def hook(req, resp, resource, params): + length = req.content_length + if length is not None and length > limit: + msg = ( + 'The size of the request is too large. The body must not ' + 'exceed ' + str(limit) + ' bytes in length.' + ) + + raise falcon.HTTPPayloadTooLarge( + title='Request body is too large', description=msg + ) + + return hook + +class CreateTaskResource: + def on_post(self, req, resp): + quote = { + 'title': 'Получена задача', + 'description': req.context.doc['task'] + } + + resp.media = quote + + +app = falcon.App( + middleware=[ + RequireJSON(), + JSONTranslator() + ] +) +app.add_route('/create-task', CreateTaskResource())