Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add the static directory serving #64

Merged
merged 2 commits into from
Aug 11, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 54 additions & 0 deletions Cargo.lock

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

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ dashmap = {git = "https://github.com/quake/dashmap", branch = "parking_lot", fea
pyo3-asyncio = { version="0.14.0" , features = ["attributes", "tokio-runtime"] }
anyhow = "1.0.38"
actix-web = "4.0.0-beta.8"
actix-files = "0.6.0-beta.4"
futures-util = "0.3.15"

[package.metadata.maturin]
Expand Down
3 changes: 3 additions & 0 deletions robyn/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ def add_route(self, route_type, endpoint, handler):
route_type, endpoint, handler, asyncio.iscoroutinefunction(handler)
)

def add_directory(self, route, directory_path, index_file=None, show_files_listing=False):
self.server.add_directory(route, directory_path, index_file, show_files_listing)

def add_header(self, key, value):
self.server.add_header(key, value)

Expand Down
9 changes: 0 additions & 9 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,9 @@ use server::Server;
use pyo3::prelude::*;
use pyo3::wrap_pyfunction;

#[pyfunction]
pub fn start_server() {
// this is a wrapper function for python
// to start a server
Server::new();
}

#[pymodule]
pub fn robyn(_py: Python<'_>, m: &PyModule) -> PyResult<()> {
// the pymodule class to make the rustPyFunctions available
// in python
m.add_wrapped(wrap_pyfunction!(start_server))?;
m.add_class::<Server>()?;
pyo3::prepare_freethreaded_python();
Ok(())
Expand Down
55 changes: 51 additions & 4 deletions src/server.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
use crate::processor::{apply_headers, handle_request};
use crate::router::Router;
use crate::types::Headers;
use actix_files::Files;
use std::sync::atomic::AtomicBool;
use std::sync::atomic::Ordering::{Relaxed, SeqCst};
use std::sync::Arc;
use std::sync::{Arc, RwLock};
use std::thread;
// pyO3 module
use actix_web::*;
Expand All @@ -14,10 +15,19 @@ use pyo3::types::PyAny;
// hyper modules
static STARTED: AtomicBool = AtomicBool::new(false);

#[derive(Clone)]
struct Directory {
route: String,
directory_path: String,
index_file: Option<String>,
show_files_listing: bool,
}

#[pyclass]
pub struct Server {
router: Arc<Router>,
headers: Arc<DashMap<String, String>>,
directories: Arc<RwLock<Vec<Directory>>>,
}

#[pymethods]
Expand All @@ -27,6 +37,7 @@ impl Server {
Self {
router: Arc::new(Router::new()),
headers: Arc::new(DashMap::new()),
directories: Arc::new(RwLock::new(Vec::new())),
}
}

Expand All @@ -41,6 +52,7 @@ impl Server {

let router = self.router.clone();
let headers = self.headers.clone();
let directories = self.directories.clone();

let asyncio = py.import("asyncio").unwrap();

Expand All @@ -56,9 +68,29 @@ impl Server {
let addr = format!("127.0.0.1:{}", port);

HttpServer::new(move || {
let mut app = App::new();
let directories = directories.read().unwrap();
for directory in directories.iter() {
if let Some(index_file) = &directory.index_file {
app = app.service(
Files::new(&directory.route, &directory.directory_path)
.index_file(index_file)
.redirect_to_slash_directory(), // .show_files_listing(), // .index_file(index_file),
);
} else if directory.show_files_listing {
app = app.service(
Files::new(&directory.route, &directory.directory_path)
.redirect_to_slash_directory()
.show_files_listing(),
);
} else {
app = app
.service(Files::new(&directory.route, &directory.directory_path));
}
}

let event_loop_hdl = event_loop_hdl.clone();
App::new()
.app_data(web::Data::new(router.clone()))
app.app_data(web::Data::new(router.clone()))
.app_data(web::Data::new(headers.clone()))
.default_service(web::route().to(move |router, headers, payload, req| {
pyo3_asyncio::tokio::scope_local(event_loop_hdl.clone(), async move {
Expand All @@ -77,6 +109,21 @@ impl Server {
event_loop.call_method0("run_forever").unwrap();
}

pub fn add_directory(
&mut self,
route: String,
directory_path: String,
index_file: Option<String>,
show_files_listing: bool,
) {
self.directories.write().unwrap().push(Directory {
route,
directory_path,
index_file,
show_files_listing,
});
}

/// Adds a new header to our concurrent hashmap
/// this can be called after the server has started.
pub fn add_header(&self, key: &str, value: &str) {
Expand Down Expand Up @@ -110,7 +157,7 @@ async fn index(
handle_request(handler_function, &headers, &mut payload, &req).await
}
None => {
let mut response = HttpResponse::NotFound();
let mut response = HttpResponse::Ok();
apply_headers(&mut response, &headers);
response.finish()
}
Expand Down
3 changes: 2 additions & 1 deletion test.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,4 +54,5 @@ def blocker():

if __name__ == "__main__":
app.add_header("server", "robyn")
app.start(port=5001)
app.add_directory(route="/",directory_path="./test_dir/build", index_file="index.html")
app.start(port=5000)
15 changes: 0 additions & 15 deletions test_fast_api.py

This file was deleted.