Skip to content

Commit 6827c5d

Browse files
committed
fix: introduce PyRequest and PyResponse struct
1 parent 9a8d770 commit 6827c5d

18 files changed

+328
-360
lines changed

integration_tests/base_routes.py

+4-12
Original file line numberDiff line numberDiff line change
@@ -57,17 +57,13 @@ def shutdown_handler():
5757

5858
@app.before_request("/sync/middlewares")
5959
def sync_before_request(request: Request):
60-
new_headers = request.headers
61-
new_headers["before"] = "sync_before_request"
62-
request.headers = new_headers
60+
request.headers["before"] = "sync_before_request"
6361
return request
6462

6563

6664
@app.after_request("/sync/middlewares")
6765
def sync_after_request(response: Response):
68-
new_headers = response.headers
69-
new_headers["after"] = "sync_after_request"
70-
response.headers = new_headers
66+
response.headers["after"] = "sync_after_request"
7167
response.body = response.body + " after"
7268
return response
7369

@@ -81,17 +77,13 @@ def sync_middlewares(request: Request):
8177

8278
@app.before_request("/async/middlewares")
8379
async def async_before_request(request: Request):
84-
new_headers = request.headers
85-
new_headers["before"] = "async_before_request"
86-
request.headers = new_headers
80+
request.headers["before"] = "async_before_request"
8781
return request
8882

8983

9084
@app.after_request("/async/middlewares")
9185
async def async_after_request(response: Response):
92-
new_headers = response.headers
93-
new_headers["after"] = "async_after_request"
94-
response.headers = new_headers
86+
response.headers["after"] = "async_after_request"
9587
response.body = response.body + " after"
9688
return response
9789

integration_tests/test_middlewares.py

+2
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
@pytest.mark.parametrize("function_type", ["sync", "async"])
88
def test_middlewares(function_type: str, session):
99
r = get(f"/{function_type}/middlewares")
10+
# We do not want the request headers to be in the response
11+
assert "before" not in r.headers
1012
assert "after" in r.headers
1113
assert r.headers["after"] == f"{function_type}_after_request"
1214
assert r.text == f"{function_type} middlewares after"

robyn/robyn.pyi

+5-14
Original file line numberDiff line numberDiff line change
@@ -15,30 +15,21 @@ class FunctionInfo:
1515
is_async: bool
1616
number_of_params: int
1717

18-
@dataclass
19-
class Body:
20-
content: Union[str, bytes]
21-
22-
def as_bytes(self) -> bytes:
23-
pass
24-
def set(self, content: Union[str, bytes]):
25-
pass
26-
2718
@dataclass
2819
class Request:
2920
queries: dict[str, str]
3021
headers: dict[str, str]
3122
params: dict[str, str]
32-
body: Body
23+
body: Union[str, bytes]
24+
method: str
3325

3426
@dataclass
3527
class Response:
3628
status_code: int
29+
response_type: str
3730
headers: dict[str, str]
38-
body: Body
39-
40-
def set_file_path(self, file_path: str):
41-
pass
31+
body: Union[str, bytes]
32+
file_path: str
4233

4334
class Server:
4435
def __init__(self) -> None:

robyn/router.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ def _format_response(self, res):
3737
response = Response(status_code=status_code, headers=headers, body=body)
3838
file_path = res.get("file_path")
3939
if file_path is not None:
40-
response.set_file_path(file_path)
40+
response.file_path = file_path
4141
elif isinstance(res, Response):
4242
response = res
4343
elif isinstance(res, bytes):

src/executors/mod.rs

+21-19
Original file line numberDiff line numberDiff line change
@@ -1,55 +1,56 @@
11
/// This is the module that has all the executor functions
22
/// i.e. the functions that have the responsibility of parsing and executing functions.
3-
use crate::types::{FunctionInfo, Request, Response};
4-
53
use std::sync::Arc;
64

7-
use anyhow::{anyhow, Context, Result};
5+
use anyhow::{Context, Result};
86
use log::debug;
7+
use pyo3::prelude::*;
98
use pyo3_asyncio::TaskLocals;
10-
// pyO3 module
11-
use pyo3::{prelude::*, PyClass};
9+
10+
use crate::types::{function_info::FunctionInfo, request::Request, response::Response};
1211

1312
fn get_function_output<'a, T>(
1413
function: &'a FunctionInfo,
1514
py: Python<'a>,
1615
input: &T,
1716
) -> Result<&'a PyAny, PyErr>
1817
where
19-
T: Clone + IntoPy<Py<PyAny>>,
18+
T: ToPyObject,
2019
{
2120
let handler = function.handler.as_ref(py);
2221

2322
// this makes the request object accessible across every route
2423
match function.number_of_params {
2524
0 => handler.call0(),
26-
1 => handler.call1((input.clone(),)),
25+
1 => handler.call1((input.to_object(py),)),
2726
// this is done to accommodate any future params
28-
2_u8..=u8::MAX => handler.call1((input.clone(),)),
27+
2_u8..=u8::MAX => handler.call1((input.to_object(py),)),
2928
}
3029
}
3130

32-
pub async fn execute_middleware_function<'a, T>(input: &T, function: FunctionInfo) -> Result<T>
31+
pub async fn execute_middleware_function<T>(input: &T, function: FunctionInfo) -> Result<T>
3332
where
34-
T: Clone + PyClass + IntoPy<Py<PyAny>>,
33+
T: for<'a> FromPyObject<'a> + ToPyObject,
3534
{
3635
if function.is_async {
37-
let output = Python::with_gil(|py| {
36+
let output: Py<PyAny> = Python::with_gil(|py| {
3837
pyo3_asyncio::tokio::into_future(get_function_output(&function, py, input)?)
3938
})?
4039
.await?;
4140

42-
Python::with_gil(|py| -> PyResult<T> {
43-
let output: (T,) = output.extract(py)?;
41+
Python::with_gil(|py| -> Result<T> {
42+
let output: (T,) = output
43+
.extract(py)
44+
.context("Failed to get middleware response")?;
4445
Ok(output.0)
4546
})
46-
.map_err(|e| anyhow!(e))
4747
} else {
48-
Python::with_gil(|py| -> PyResult<T> {
49-
let output: (T,) = get_function_output(&function, py, input)?.extract()?;
48+
Python::with_gil(|py| -> Result<T> {
49+
let output: (T,) = get_function_output(&function, py, input)?
50+
.extract()
51+
.context("Failed to get middleware response")?;
5052
Ok(output.0)
5153
})
52-
.map_err(|e| anyhow!(e))
5354
}
5455
}
5556

@@ -67,8 +68,9 @@ pub async fn execute_http_function(request: &Request, function: FunctionInfo) ->
6768
})
6869
} else {
6970
Python::with_gil(|py| -> Result<Response> {
70-
let output = get_function_output(&function, py, request)?;
71-
output.extract().context("Failed to get route response")
71+
get_function_output(&function, py, request)?
72+
.extract()
73+
.context("Failed to get route response")
7274
})
7375
}
7476
}

src/lib.rs

+3-4
Original file line numberDiff line numberDiff line change
@@ -11,17 +11,16 @@ use shared_socket::SocketHeld;
1111

1212
// pyO3 module
1313
use pyo3::prelude::*;
14-
use types::{ActixBytesWrapper, FunctionInfo, Request, Response};
14+
use types::{function_info::FunctionInfo, request::PyRequest, response::PyResponse};
1515

1616
#[pymodule]
1717
pub fn robyn(_py: Python<'_>, m: &PyModule) -> PyResult<()> {
1818
// the pymodule class to make the rustPyFunctions available
1919
m.add_class::<Server>()?;
2020
m.add_class::<SocketHeld>()?;
2121
m.add_class::<FunctionInfo>()?;
22-
m.add_class::<Request>()?;
23-
m.add_class::<Response>()?;
24-
m.add_class::<ActixBytesWrapper>()?;
22+
m.add_class::<PyRequest>()?;
23+
m.add_class::<PyResponse>()?;
2524
pyo3::prepare_freethreaded_python();
2625
Ok(())
2726
}

src/routers/const_router.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,9 @@ use std::sync::Arc;
44
use std::sync::RwLock;
55

66
use crate::executors::execute_http_function;
7-
use crate::types::Response;
8-
use crate::types::{FunctionInfo, Request};
7+
use crate::types::function_info::FunctionInfo;
8+
use crate::types::request::Request;
9+
use crate::types::response::Response;
910
use anyhow::Context;
1011
use log::debug;
1112
use matchit::Router as MatchItRouter;

src/routers/http_router.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
11
use std::sync::RwLock;
22
use std::{collections::HashMap, str::FromStr};
3-
// pyo3 modules
4-
use crate::types::FunctionInfo;
5-
use pyo3::types::PyAny;
63

74
use actix_web::http::Method;
85
use matchit::Router as MatchItRouter;
6+
use pyo3::types::PyAny;
97

108
use anyhow::{Context, Result};
119

1210
use super::Router;
11+
use crate::types::function_info::FunctionInfo;
1312

1413
type RouteMap = RwLock<MatchItRouter<FunctionInfo>>;
1514

src/routers/middleware_router.rs

+2-4
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,12 @@
11
use std::collections::HashMap;
22
use std::sync::RwLock;
3-
// pyo3 modules
4-
use crate::types::FunctionInfo;
3+
54
use anyhow::{Context, Error, Result};
65
use matchit::Router as MatchItRouter;
76
use pyo3::types::PyAny;
87

9-
use crate::routers::types::MiddlewareRoute;
10-
118
use super::Router;
9+
use crate::{routers::types::MiddlewareRoute, types::function_info::FunctionInfo};
1210

1311
type RouteMap = RwLock<MatchItRouter<FunctionInfo>>;
1412

src/routers/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use anyhow::Result;
22
use pyo3::PyAny;
33

4-
use crate::types::FunctionInfo;
4+
use crate::types::function_info::FunctionInfo;
55

66
pub mod const_router;
77
pub mod http_router;

src/routers/web_socket_router.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
use std::collections::HashMap;
22
use std::sync::RwLock;
3-
// pyo3 modules
4-
use crate::types::FunctionInfo;
3+
54
use log::debug;
65

7-
/// Contains the thread safe hashmaps of different routes
6+
use crate::types::function_info::FunctionInfo;
87

8+
/// Contains the thread safe hashmaps of different routes
99
type WebSocketRoutes = RwLock<HashMap<String, HashMap<String, FunctionInfo>>>;
1010

1111
pub struct WebSocketRouter {

src/server.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
use crate::executors::{execute_event_handler, execute_http_function, execute_middleware_function};
2-
use crate::types::{Request, Response};
32

43
use crate::routers::const_router::ConstRouter;
54
use crate::routers::Router;
@@ -8,7 +7,9 @@ use crate::routers::http_router::HttpRouter;
87
use crate::routers::types::MiddlewareRoute;
98
use crate::routers::{middleware_router::MiddlewareRouter, web_socket_router::WebSocketRouter};
109
use crate::shared_socket::SocketHeld;
11-
use crate::types::FunctionInfo;
10+
use crate::types::function_info::FunctionInfo;
11+
use crate::types::request::Request;
12+
use crate::types::response::Response;
1213
use crate::web_socket_connection::start_web_socket;
1314

1415
use std::convert::TryInto;

0 commit comments

Comments
 (0)