Skip to content

Commit

Permalink
Reqeusts object is now optional
Browse files Browse the repository at this point in the history
  • Loading branch information
sansyrox committed Oct 25, 2021
1 parent dfb1f3c commit ba5ba62
Show file tree
Hide file tree
Showing 5 changed files with 73 additions and 28 deletions.
4 changes: 3 additions & 1 deletion robyn/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import os
import argparse
import asyncio
from inspect import signature

from .robyn import Server
from .responses import static_file, jsonify
Expand Down Expand Up @@ -40,8 +41,9 @@ def add_route(self, route_type, endpoint, handler):

""" We will add the status code here only
"""
number_of_params = len(signature(handler).parameters)
self.server.add_route(
route_type, endpoint, handler, asyncio.iscoroutinefunction(handler)
route_type, endpoint, handler, asyncio.iscoroutinefunction(handler), number_of_params
)

def add_directory(self, route, directory_path, index_file=None, show_files_listing=False):
Expand Down
32 changes: 26 additions & 6 deletions src/processor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,22 @@ pub fn apply_headers(response: &mut HttpResponseBuilder, headers: &Arc<Headers>)
///
pub async fn handle_request(
function: PyFunction,
number_of_params: u8,
headers: &Arc<Headers>,
payload: &mut web::Payload,
req: &HttpRequest,
route_params: HashMap<String, String>,
) -> HttpResponse {
let contents = match execute_function(function, payload, headers, req, route_params).await {
let contents = match execute_function(
function,
payload,
headers,
req,
route_params,
number_of_params,
)
.await
{
Ok(res) => res,
Err(err) => {
println!("Error: {:?}", err);
Expand Down Expand Up @@ -76,6 +86,7 @@ async fn execute_function(
headers: &Headers,
req: &HttpRequest,
route_params: HashMap<String, String>,
number_of_params: u8,
) -> Result<String> {
let mut data: Option<Vec<u8>> = None;

Expand Down Expand Up @@ -119,7 +130,12 @@ async fn execute_function(
};

// this makes the request object to be accessible across every route
let coro: PyResult<&PyAny> = handler.call1((request,));
let coro: PyResult<&PyAny> = match number_of_params {
0 => handler.call0(),
1 => handler.call1((request,)),
// this is done to accomodate any future params
2_u8..=u8::MAX => handler.call1((request,)),
};
pyo3_asyncio::tokio::into_future(coro?)
})?;

Expand Down Expand Up @@ -166,16 +182,20 @@ async fn execute_function(
let handler = handler.as_ref(py);
request.insert("params", route_params.into_py(py));
request.insert("headers", headers_python.into_py(py));
let output: PyResult<&PyAny> = match data {
match data {
Some(res) => {
let data = res.into_py(py);
request.insert("body", data);

handler.call1((request,))
}
None => handler.call1((request,)),
None => {}
};

let output: PyResult<&PyAny> = match number_of_params {
0 => handler.call0(),
1 => handler.call1((request,)),
// this is done to accomodate any future params
2_u8..=u8::MAX => handler.call1((request,)),
};
let output: &str = output?.extract()?;
Ok(output.to_string())
})
Expand Down
35 changes: 21 additions & 14 deletions src/router.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,15 @@ use matchit::Node;
/// Contains the thread safe hashmaps of different routes
pub struct Router {
get_routes: Arc<RwLock<Node<PyFunction>>>,
post_routes: Arc<RwLock<Node<PyFunction>>>,
put_routes: Arc<RwLock<Node<PyFunction>>>,
delete_routes: Arc<RwLock<Node<PyFunction>>>,
patch_routes: Arc<RwLock<Node<PyFunction>>>,
head_routes: Arc<RwLock<Node<PyFunction>>>,
options_routes: Arc<RwLock<Node<PyFunction>>>,
connect_routes: Arc<RwLock<Node<PyFunction>>>,
trace_routes: Arc<RwLock<Node<PyFunction>>>,
get_routes: Arc<RwLock<Node<(PyFunction, u8)>>>,
post_routes: Arc<RwLock<Node<(PyFunction, u8)>>>,
put_routes: Arc<RwLock<Node<(PyFunction, u8)>>>,
delete_routes: Arc<RwLock<Node<(PyFunction, u8)>>>,
patch_routes: Arc<RwLock<Node<(PyFunction, u8)>>>,
head_routes: Arc<RwLock<Node<(PyFunction, u8)>>>,
options_routes: Arc<RwLock<Node<(PyFunction, u8)>>>,
connect_routes: Arc<RwLock<Node<(PyFunction, u8)>>>,
trace_routes: Arc<RwLock<Node<(PyFunction, u8)>>>,
}

impl Router {
Expand All @@ -38,7 +38,7 @@ impl Router {
}

#[inline]
fn get_relevant_map(&self, route: Method) -> Option<&Arc<RwLock<Node<PyFunction>>>> {
fn get_relevant_map(&self, route: Method) -> Option<&Arc<RwLock<Node<(PyFunction, u8)>>>> {
match route {
Method::GET => Some(&self.get_routes),
Method::POST => Some(&self.post_routes),
Expand All @@ -54,7 +54,7 @@ impl Router {
}

#[inline]
fn get_relevant_map_str(&self, route: &str) -> Option<&Arc<RwLock<Node<PyFunction>>>> {
fn get_relevant_map_str(&self, route: &str) -> Option<&Arc<RwLock<Node<(PyFunction, u8)>>>> {
let method = match Method::from_bytes(route.as_bytes()) {
Ok(res) => res,
Err(_) => return None,
Expand All @@ -65,7 +65,14 @@ impl Router {

// Checks if the functions is an async function
// Inserts them in the router according to their nature(CoRoutine/SyncFunction)
pub fn add_route(&self, route_type: &str, route: &str, handler: Py<PyAny>, is_async: bool) {
pub fn add_route(
&self,
route_type: &str,
route: &str,
handler: Py<PyAny>,
is_async: bool,
number_of_params: u8,
) {
let table = match self.get_relevant_map_str(route_type) {
Some(table) => table,
None => return,
Expand All @@ -80,15 +87,15 @@ impl Router {
table
.write()
.unwrap()
.insert(route.to_string(), function)
.insert(route.to_string(), (function, number_of_params))
.unwrap();
}

pub fn get_route(
&self,
route_method: Method,
route: &str,
) -> Option<(PyFunction, HashMap<String, String>)> {
) -> Option<((PyFunction, u8), HashMap<String, String>)> {
let table = self.get_relevant_map(route_method)?;
match table.read().unwrap().at(route) {
Ok(res) => {
Expand Down
24 changes: 20 additions & 4 deletions src/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -143,9 +143,17 @@ impl Server {

/// Add a new route to the routing tables
/// can be called after the server has been started
pub fn add_route(&self, route_type: &str, route: &str, handler: Py<PyAny>, is_async: bool) {
pub fn add_route(
&self,
route_type: &str,
route: &str,
handler: Py<PyAny>,
is_async: bool,
number_of_params: u8,
) {
println!("Route added for {} {} ", route_type, route);
self.router.add_route(route_type, route, handler, is_async);
self.router
.add_route(route_type, route, handler, is_async, number_of_params);
}
}

Expand All @@ -164,8 +172,16 @@ async fn index(
req: HttpRequest,
) -> impl Responder {
match router.get_route(req.method().clone(), req.uri().path()) {
Some((handler_function, route_params)) => {
handle_request(handler_function, &headers, &mut payload, &req, route_params).await
Some(((handler_function, number_of_params), route_params)) => {
handle_request(
handler_function,
number_of_params,
&headers,
&mut payload,
&req,
route_params,
)
.await
}
None => {
let mut response = HttpResponse::Ok();
Expand Down
6 changes: 3 additions & 3 deletions test_python/base_routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@


@app.get("/")
async def h(request):
print(request)
async def h(requests):
print(requests)
global callCount
callCount += 1
message = "Called " + str(callCount) + " times"
Expand All @@ -26,7 +26,7 @@ async def test(request):
return static_file("./index.html")

@app.get("/jsonify")
async def json_get(request):
async def json_get():
return jsonify({"hello": "world"})


Expand Down

0 comments on commit ba5ba62

Please sign in to comment.