Skip to content

Commit

Permalink
Code clean up | Modularise rust code (sparckles#185)
Browse files Browse the repository at this point in the history
* Add experimental io-uring

* Code cleanup
  • Loading branch information
sansyrox authored Apr 9, 2022
1 parent 9b1ca2c commit cb416f8
Show file tree
Hide file tree
Showing 8 changed files with 204 additions and 142 deletions.
31 changes: 31 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,5 +34,10 @@ uuid = { version = "0.8", features = ["serde", "v4"] }
serde = "1.0.136"
serde_json = "1.0.79"

[features]
# Defines a feature named `webp` that does not enable any other features.
io-uring = ["actix-web/experimental-io-uring"]


[package.metadata.maturin]
name = "robyn"
135 changes: 7 additions & 128 deletions src/processor.rs → src/executors/mod.rs
Original file line number Diff line number Diff line change
@@ -1,143 +1,22 @@
/// This is the module that has all the executor functions
/// i.e. the functions that have the responsibility of parsing and executing functions.
use crate::io_helpers::read_file;

use std::collections::HashMap;
use std::str::FromStr;
use std::sync::Arc;

use actix_web::{http::Method, web, HttpRequest, HttpResponse, HttpResponseBuilder};
use actix_web::{http::Method, web, HttpRequest};
use anyhow::{bail, Result};
use serde_json::Value;
// pyO3 module
use crate::types::{Headers, PyFunction};
use futures_util::stream::StreamExt;
use pyo3::prelude::*;
use pyo3::types::PyDict;

use std::fs::File;
use std::io::Read;

/// @TODO make configurable
const MAX_SIZE: usize = 10_000;

#[inline]
pub fn apply_headers(response: &mut HttpResponseBuilder, headers: HashMap<String, String>) {
for (key, val) in (headers).iter() {
response.insert_header((key.clone(), val.clone()));
}
}

/// This functions handles the incoming request matches it to the function and serves the response
///
/// # Arguments
///
/// * `function` - a PyFunction matched from the router
///
/// # Errors
///
/// When the route is not found. It should check if the 404 route exist and then serve it back
/// There can also be PyError due to any mis processing of the files
///
pub async fn handle_request(
function: PyFunction,
number_of_params: u8,
headers: HashMap<String, String>,
payload: &mut web::Payload,
req: &HttpRequest,
route_params: HashMap<String, String>,
queries: HashMap<String, String>,
) -> HttpResponse {
let contents = match execute_http_function(
function,
payload,
headers.clone(),
req,
route_params,
queries,
number_of_params,
)
.await
{
Ok(res) => res,
Err(err) => {
println!("Error: {:?}", err);
let mut response = HttpResponse::InternalServerError();
apply_headers(&mut response, headers.clone());
return response.finish();
}
};

let body = contents.get("body").unwrap().to_owned();
let status_code =
actix_http::StatusCode::from_str(contents.get("status_code").unwrap()).unwrap();

let headers: HashMap<String, String> = match contents.get("headers") {
Some(headers) => {
let h: HashMap<String, String> = serde_json::from_str(headers).unwrap();
h
}
None => HashMap::new(),
};

println!("These are the headers from serde {:?}", headers);

let mut response = HttpResponse::build(status_code);
apply_headers(&mut response, headers.clone());
let final_response = if !body.is_empty() {
response.body(body)
} else {
response.finish()
};

println!(
"The status code is {} and the headers are {:?}",
final_response.status(),
final_response.headers()
);
// response.body(contents.get("body").unwrap().to_owned())
final_response
}

pub async fn handle_middleware_request(
function: PyFunction,
number_of_params: u8,
headers: &Arc<Headers>,
payload: &mut web::Payload,
req: &HttpRequest,
route_params: HashMap<String, String>,
queries: HashMap<String, String>,
) -> HashMap<String, HashMap<String, String>> {
let contents = match execute_middleware_function(
function,
payload,
headers,
req,
route_params,
queries,
number_of_params,
)
.await
{
Ok(res) => res,
Err(_err) => HashMap::new(),
};

println!("These are the middleware response {:?}", contents);
contents
}

// ideally this should be async
/// A function to read lossy files and serve it as a html response
///
/// # Arguments
///
/// * `file_path` - The file path that we want the function to read
///
fn read_file(file_path: &str) -> String {
let mut file = File::open(file_path).unwrap();
let mut buf = vec![];
file.read_to_end(&mut buf).unwrap();
String::from_utf8_lossy(&buf).to_string()
}

async fn execute_middleware_function<'a>(
pub async fn execute_middleware_function<'a>(
function: PyFunction,
payload: &mut web::Payload,
headers: &Headers,
Expand Down Expand Up @@ -238,7 +117,7 @@ async fn execute_middleware_function<'a>(

// Change this!
#[inline]
async fn execute_http_function(
pub async fn execute_http_function(
function: PyFunction,
payload: &mut web::Payload,
headers: HashMap<String, String>,
Expand Down
29 changes: 29 additions & 0 deletions src/io_helpers/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
use std::collections::HashMap;

use std::fs::File;
use std::io::Read;

use actix_web::HttpResponseBuilder;

// this should be something else
// probably inside the submodule of the http router
#[inline]
pub fn apply_headers(response: &mut HttpResponseBuilder, headers: HashMap<String, String>) {
for (key, val) in (headers).iter() {
response.insert_header((key.clone(), val.clone()));
}
}

/// A function to read lossy files and serve it as a html response
///
/// # Arguments
///
/// * `file_path` - The file path that we want the function to read
///
// ideally this should be async
pub fn read_file(file_path: &str) -> String {
let mut file = File::open(file_path).unwrap();
let mut buf = vec![];
file.read_to_end(&mut buf).unwrap();
String::from_utf8_lossy(&buf).to_string()
}
4 changes: 3 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
mod processor;
mod executors;
mod io_helpers;
mod request_handler;
mod routers;
mod server;
mod shared_socket;
Expand Down
115 changes: 115 additions & 0 deletions src/request_handler/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
use crate::executors::{execute_http_function, execute_middleware_function};

use std::collections::HashMap;
use std::str::FromStr;
use std::sync::Arc;

use actix_web::{web, HttpRequest, HttpResponse, HttpResponseBuilder};
// pyO3 module
use crate::types::{Headers, PyFunction};

#[inline]
pub fn apply_headers(response: &mut HttpResponseBuilder, headers: HashMap<String, String>) {
for (key, val) in (headers).iter() {
response.insert_header((key.clone(), val.clone()));
}
}

/// This functions handles the incoming request matches it to the function and serves the response
///
/// # Arguments
///
/// * `function` - a PyFunction matched from the router
///
/// # Errors
///
/// When the route is not found. It should check if the 404 route exist and then serve it back
/// There can also be PyError due to any mis processing of the files
///
pub async fn handle_http_request(
function: PyFunction,
number_of_params: u8,
headers: HashMap<String, String>,
payload: &mut web::Payload,
req: &HttpRequest,
route_params: HashMap<String, String>,
queries: HashMap<String, String>,
) -> HttpResponse {
let contents = match execute_http_function(
function,
payload,
headers.clone(),
req,
route_params,
queries,
number_of_params,
)
.await
{
Ok(res) => res,
Err(err) => {
println!("Error: {:?}", err);
let mut response = HttpResponse::InternalServerError();
apply_headers(&mut response, headers.clone());
return response.finish();
}
};

let body = contents.get("body").unwrap().to_owned();
let status_code =
actix_http::StatusCode::from_str(contents.get("status_code").unwrap()).unwrap();

let headers: HashMap<String, String> = match contents.get("headers") {
Some(headers) => {
let h: HashMap<String, String> = serde_json::from_str(headers).unwrap();
h
}
None => HashMap::new(),
};

println!("These are the headers from serde {:?}", headers);

let mut response = HttpResponse::build(status_code);
apply_headers(&mut response, headers.clone());
let final_response = if !body.is_empty() {
response.body(body)
} else {
response.finish()
};

println!(
"The status code is {} and the headers are {:?}",
final_response.status(),
final_response.headers()
);
// response.body(contents.get("body").unwrap().to_owned())
final_response
}

pub async fn handle_http_middleware_request(
function: PyFunction,
number_of_params: u8,
headers: &Arc<Headers>,
payload: &mut web::Payload,
req: &HttpRequest,
route_params: HashMap<String, String>,
queries: HashMap<String, String>,
) -> HashMap<String, HashMap<String, String>> {
let contents = match execute_middleware_function(
function,
payload,
headers,
req,
route_params,
queries,
number_of_params,
)
.await
{
Ok(res) => res,
Err(_err) => HashMap::new(),
};

println!("These are the middleware response {:?}", contents);
contents
}
Loading

0 comments on commit cb416f8

Please sign in to comment.