Skip to content

Commit

Permalink
Merge pull request #3 from levkk/levkk-django
Browse files Browse the repository at this point in the history
uWSGI server
  • Loading branch information
levkk authored Oct 21, 2024
2 parents a033d6b + d46f6f4 commit 9641853
Show file tree
Hide file tree
Showing 25 changed files with 488 additions and 30 deletions.
105 changes: 105 additions & 0 deletions Cargo.lock

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

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,5 @@ members = [
"rwf",
"rwf-cli",
"rwf-macros",
"rwf-tests",
"rwf-tests", "examples/django",
]
4 changes: 0 additions & 4 deletions examples/django-asgi/pyrightconfig.json

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1 +1 @@
venv
venv
10 changes: 10 additions & 0 deletions examples/django/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
[package]
name = "django"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
rwf = { path = "../../rwf", features = ["wsgi"] }
tokio = { version = "1", features = ["full"] }
1 change: 1 addition & 0 deletions examples/django/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
django
33 changes: 33 additions & 0 deletions examples/django/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
use rwf::controller::WsgiController;
use rwf::http::Server;
use rwf::prelude::*;

#[derive(Default)]
struct RustIndex;

#[async_trait]
impl Controller for RustIndex {
async fn handle(&self, _request: &Request) -> Result<Response, Error> {
Ok(Response::new().html("This is served by Rust."))
}
}

#[tokio::main]
async fn main() {
Logger::init();

// Set PYTHONPATH to where the Django app is.
let cwd = std::env::current_dir().unwrap();
let pythonpath = cwd.join("todo");
std::env::set_var("PYTHONPATH", pythonpath.display().to_string());

Server::new(vec![
// Serve /rust with Rwf.
route!("/rust" => RustIndex),
// Serve every other path with Django.
WsgiController::new("todo.wsgi").wildcard("/"),
])
.launch("0.0.0.0:8002")
.await
.unwrap();
}
File renamed without changes.
File renamed without changes.
Empty file.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,12 @@
from django.contrib import admin
from django.urls import path

from django.http import HttpResponse

def index(request):
return HttpResponse("This is served by Django.")

urlpatterns = [
path('admin/', admin.site.urls),
path('', index, name='index'),
]
File renamed without changes.
5 changes: 5 additions & 0 deletions rwf/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ description = "Comprehensive framework for building web applications in Rust"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[features]
wsgi = ["pyo3"]
default = []

[dependencies]
time = { version = "0.3", features = ["formatting", "serde", "parsing"] }
tokio-postgres = { version = "0.7", features = [
Expand Down Expand Up @@ -38,3 +42,4 @@ rand = { version = "0.8", features = ["getrandom"] }
regex = "1"
sha1 = "0.10"
toml = "0.8"
pyo3 = { version = "0.22", features = ["auto-initialize"], optional = true }
9 changes: 7 additions & 2 deletions rwf/src/controller/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ pub mod ser;
pub mod static_files;
pub mod util;

#[cfg(feature = "wsgi")]
pub mod wsgi;
#[cfg(feature = "wsgi")]
pub use wsgi::WsgiController;

pub use auth::{AllowAll, AuthHandler, Authentication, BasicAuth, DenyAll, Session, SessionId};
pub use error::Error;
pub use middleware::{Middleware, MiddlewareHandler, MiddlewareSet, Outcome, RateLimiter};
Expand Down Expand Up @@ -59,7 +64,7 @@ pub trait Controller: Sync + Send {
where
Self: Sized + 'static,
{
todo!()
Handler::wildcard(path, self)
}

fn protocol(&self) -> Protocol {
Expand Down Expand Up @@ -160,7 +165,7 @@ pub trait PageController: Controller {
/// async fn handle(&self, request: &Request) -> Result<Response, Error> {
/// // Delegate handling of this controller to the `RestController`.
/// RestController::handle(self, request).await
/// }
/// }
/// }
///
/// #[async_trait]
Expand Down
45 changes: 45 additions & 0 deletions rwf/src/controller/wsgi.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
use super::{Controller, Error};
use crate::http::{wsgi::WsgiRequest, Request, Response};

use async_trait::async_trait;
use pyo3::prelude::*;

use tokio::time::{timeout, Duration};

pub struct WsgiController {
path: &'static str,
}

impl WsgiController {
pub fn new(path: &'static str) -> Self {
WsgiController { path }
}
}

#[async_trait]
impl Controller for WsgiController {
async fn handle(&self, request: &Request) -> Result<Response, Error> {
let request = WsgiRequest::from_request(request)?;
let path = self.path;

let response = timeout(
Duration::from_secs(5),
tokio::task::spawn_blocking(move || {
let response = Python::with_gil(|py| {
// Import is cached.
let module = PyModule::import_bound(py, path).unwrap();
let application: Py<PyAny> = module.getattr("application").unwrap().into();
request.send(&application)
})
.unwrap();

response
}),
)
.await
.unwrap()
.unwrap();

Ok(response.to_response()?)
}
}
4 changes: 4 additions & 0 deletions rwf/src/http/headers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ impl Headers {
self.headers.clear();
}

pub fn into_raw(self) -> HashMap<String, String> {
self.headers
}

/// Convert headers to bytes (UTF-8).
///
/// Used to send headers over the wire to the client as part of a response.
Expand Down
2 changes: 2 additions & 0 deletions rwf/src/http/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ pub mod router;
pub mod server;
pub mod url;
pub mod websocket;

#[cfg(feature = "wsgi")]
pub mod wsgi;

pub use authorization::Authorization;
Expand Down
7 changes: 7 additions & 0 deletions rwf/src/http/path/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,13 @@ pub struct Path {
base: String,
}

impl std::fmt::Display for Path {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "{}", self.base)?;
write!(f, "{}", self.query)
}
}

impl Default for Path {
fn default() -> Self {
Path {
Expand Down
Loading

0 comments on commit 9641853

Please sign in to comment.