Skip to content

Commit

Permalink
feat: get rid of intermediate representations of requests and responses
Browse files Browse the repository at this point in the history
  • Loading branch information
AntoineRR committed Feb 27, 2023
1 parent 91ffd1c commit b1c580f
Show file tree
Hide file tree
Showing 9 changed files with 346 additions and 245 deletions.
186 changes: 112 additions & 74 deletions integration_tests/base_routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import pathlib

from robyn import WS, Robyn, jsonify, serve_file, serve_html
from robyn.robyn import Response
from robyn.robyn import Request, Response
from robyn.templating import JinjaTemplate

from views import SyncView, AsyncView
Expand Down Expand Up @@ -56,27 +56,62 @@ def shutdown_handler():
# ===== Middlewares =====


@app.before_request("/")
async def hello_before_request(request):
request["headers"]["before"] = "before_request"
@app.before_request("/sync/middlewares")
def sync_before_request(request: Request):
new_headers = request.headers
new_headers["before"] = "sync_before_request"
request.headers = new_headers
return request


@app.after_request("/")
async def hello_after_request(request):
request["headers"]["after"] = "after_request"
@app.after_request("/sync/middlewares")
def sync_after_request(response: Response):
new_headers = response.headers
new_headers["after"] = "sync_after_request"
response.headers = new_headers
response.body = response.body + " after"
return response


@app.get("/sync/middlewares")
def sync_middlewares():
return "sync middlewares"


@app.before_request("/async/middlewares")
async def async_before_request(request: Request):
new_headers = request.headers
new_headers["before"] = "async_before_request"
request.headers = new_headers
return request


@app.get("/")
async def middlewares():
return ""
@app.after_request("/async/middlewares")
async def async_after_request(response: Response):
new_headers = response.headers
new_headers["after"] = "async_after_request"
response.headers = new_headers
response.body = response.body + " after"
return response


@app.get("/async/middlewares")
async def async_middlewares():
return "async middlewares"


# ===== Routes =====

# --- GET ---

# Hello world


@app.get("/")
async def hello_world():
return "Hello world"


# str


Expand Down Expand Up @@ -166,6 +201,37 @@ async def async_response_const_get():
return Response(200, {"async_const": "response"}, "async response const get")


# Binary


@app.get("/sync/octet")
def sync_octet_get():
return b"sync octet"


@app.get("/async/octet")
async def async_octet_get():
return b"async octet"


@app.get("/sync/octet/response")
def sync_octet_response_get():
return Response(
status_code=200,
headers={"Content-Type": "application/octet-stream"},
body="sync octet response",
)


@app.get("/async/octet/response")
async def async_octet_response_get():
return Response(
status_code=200,
headers={"Content-Type": "application/octet-stream"},
body="async octet response",
)


# JSON


Expand Down Expand Up @@ -193,14 +259,14 @@ async def async_json_const_get():


@app.get("/sync/param/:id")
def sync_param(request):
id = request["params"]["id"]
def sync_param(request: Request):
id = request.params["id"]
return id


@app.get("/async/param/:id")
async def async_param(request):
id = request["params"]["id"]
async def async_param(request: Request):
id = request.params["id"]
return id


Expand Down Expand Up @@ -255,14 +321,14 @@ async def file_download_async():


@app.get("/sync/queries")
def sync_queries(request):
query_data = request["queries"]
def sync_queries(request: Request):
query_data = request.queries
return jsonify(query_data)


@app.get("/async/queries")
async def async_query(request):
query_data = request["queries"]
async def async_query(request: Request):
query_data = request.queries
return jsonify(query_data)


Expand All @@ -280,7 +346,7 @@ def return_202():


@app.get("/307")
async def redirect(request):
async def redirect():
return {
"status_code": 307,
"body": "",
Expand All @@ -290,10 +356,20 @@ async def redirect(request):


@app.get("/redirect_route")
async def redirect_route(request):
async def redirect_route():
return "This is the redirected route"


@app.get("/sync/raise")
def sync_raise():
raise Exception()


@app.get("/async/raise")
async def async_raise():
raise Exception()


# --- POST ---

# dict
Expand Down Expand Up @@ -323,13 +399,13 @@ async def async_dict_post():


@app.post("/sync/body")
def sync_body_post(request):
return bytearray(request["body"]).decode("utf-8")
def sync_body_post(request: Request):
return request.body.content


@app.post("/async/body")
async def async_body_post(request):
return bytearray(request["body"]).decode("utf-8")
async def async_body_post(request: Request):
return request.body.content


# --- PUT ---
Expand Down Expand Up @@ -361,13 +437,13 @@ async def async_dict_put():


@app.put("/sync/body")
def sync_body_put(request):
return bytearray(request["body"]).decode("utf-8")
def sync_body_put(request: Request):
return request.body.content


@app.put("/async/body")
async def async_body_put(request):
return bytearray(request["body"]).decode("utf-8")
async def async_body_put(request: Request):
return request.body.content


# --- DELETE ---
Expand Down Expand Up @@ -399,13 +475,13 @@ async def async_dict_delete():


@app.delete("/sync/body")
def sync_body_delete(request):
return bytearray(request["body"]).decode("utf-8")
def sync_body_delete(request: Request):
return request.body.content


@app.delete("/async/body")
async def async_body_delete(request):
return bytearray(request["body"]).decode("utf-8")
async def async_body_delete(request: Request):
return request.body.content


# --- PATCH ---
Expand Down Expand Up @@ -437,51 +513,13 @@ async def async_dict_patch():


@app.patch("/sync/body")
def sync_body_patch(request):
return bytearray(request["body"]).decode("utf-8")
def sync_body_patch(request: Request):
return request.body.content


@app.patch("/async/body")
async def async_body_patch(request):
return bytearray(request["body"]).decode("utf-8")


@app.get("/binary_output_sync")
def binary_output_sync(request):
return b"OK"


@app.get("/binary_output_response_sync")
def binary_output_response_sync(request):
return Response(
status_code=200,
headers={"Content-Type": "application/octet-stream"},
body="OK",
)


@app.get("/binary_output_async")
async def binary_output_async(request):
return b"OK"


@app.get("/binary_output_response_async")
async def binary_output_response_async(request):
return Response(
status_code=200,
headers={"Content-Type": "application/octet-stream"},
body="OK",
)


@app.get("/sync/raise")
def sync_raise():
raise Exception()


@app.get("/async/raise")
async def async_raise():
raise Exception()
async def async_body_patch(request: Request):
return request.body.content


# ===== Views =====
Expand Down
41 changes: 15 additions & 26 deletions integration_tests/test_binary_output.py
Original file line number Diff line number Diff line change
@@ -1,31 +1,20 @@
import requests

BASE_URL = "http://127.0.0.1:8080"


def test_binary_output_sync(session):
r = requests.get(f"{BASE_URL}/binary_output_sync")
assert r.status_code == 200
assert r.headers["Content-Type"] == "application/octet-stream"
assert r.text == "OK"
import pytest

from http_methods_helpers import get

def test_binary_output_response_sync(session):
r = requests.get(f"{BASE_URL}/binary_output_response_sync")
assert r.status_code == 200
assert r.headers["Content-Type"] == "application/octet-stream"
assert r.text == "OK"


def test_binary_output_async(session):
r = requests.get(f"{BASE_URL}/binary_output_async")
assert r.status_code == 200
assert r.headers["Content-Type"] == "application/octet-stream"
assert r.text == "OK"
BASE_URL = "http://127.0.0.1:8080"


def test_binary_output_response_async(session):
r = requests.get(f"{BASE_URL}/binary_output_response_async")
assert r.status_code == 200
@pytest.mark.parametrize(
"route, text",
[
("/sync/octet", "sync octet"),
("/async/octet", "async octet"),
("/sync/octet/response", "sync octet response"),
("/async/octet/response", "async octet response"),
],
)
def test_binary_output(route: str, text: str, session):
r = get(route)
assert r.headers["Content-Type"] == "application/octet-stream"
assert r.text == "OK"
assert r.text == text
11 changes: 6 additions & 5 deletions integration_tests/test_middlewares.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@
from helpers.http_methods_helpers import get


@pytest.mark.skip(reason="Fix middleware request headers modification")
def test_middlewares(session):
r = get("/")
@pytest.mark.parametrize("function_type", ["sync", "async"])
def test_middlewares(function_type: str, session):
r = get(f"/{function_type}/middlewares")
assert "before" in r.headers
assert r.headers["before"] == "before_request"
assert r.headers["before"] == f"{function_type}_before_request"
assert "after" in r.headers
assert r.headers["after"] == "after_request"
assert r.headers["after"] == f"{function_type}_after_request"
assert r.text == f"{function_type} middlewares after"
23 changes: 22 additions & 1 deletion robyn/robyn.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,32 @@ class FunctionInfo:
is_async: bool
number_of_params: int

@dataclass
class Body:
content: Union[str, bytes]

def __add__(self, other: Union[Body, str]):
if isinstance(other, self.__class__):
return Body(self.content + other.content)
elif isinstance(other, str):
return Body(self.content + other)
else:
raise TypeError("unsupported operand type(s) for +: '{}' and '{}'").format(
self.__class__, type(other)
)

@dataclass
class Request:
queries: dict[str, str]
headers: dict[str, str]
params: dict[str, str]
body: Body

@dataclass
class Response:
status_code: int
headers: dict[str, str]
body: Union[str, bytes]
body: Body

def set_file_path(self, file_path: str):
pass
Expand Down
Loading

0 comments on commit b1c580f

Please sign in to comment.