Skip to content

Refact/allow dynamic name request #49

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

Merged
merged 3 commits into from
Jun 12, 2025
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
34 changes: 17 additions & 17 deletions src/catcher.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@ use pyo3::prelude::*;
/// handler (callable): The handler function that will be called when this status occurs.
///
/// Example:
/// ```python
/// from oxapy import catcher, Status
///
/// @catcher(Status.NOT_FOUND)
/// def handle_not_found(request, response):
/// return Response("<h1>Custom 404 Page</h1>", content_type="text/html")
/// ```
/// ```python
/// from oxapy import catcher, Status
///
/// @catcher(Status.NOT_FOUND)
/// def handle_not_found(request, response):
/// return Response("<h1>Custom 404 Page</h1>", content_type="text/html")
/// ```
#[pyclass]
pub struct Catcher {
pub status: Status,
Expand Down Expand Up @@ -61,16 +61,16 @@ impl CatcherBuilder {
/// CatcherBuilder: A builder that creates a Catcher when called with a handler function.
///
/// Example:
/// ```python
/// from oxapy import catcher, Status, Response
///
/// @catcher(Status.NOT_FOUND)
/// def handle_404(request, response):
/// return Response("<h1>Page Not Found</h1>", content_type="text/html")
///
/// # Add the catcher to your server
/// app.catchers([handle_404])
/// ```
/// ```python
/// from oxapy import catcher, Status, Response
///
/// @catcher(Status.NOT_FOUND)
/// def handle_404(request, response):
/// return Response("<h1>Page Not Found</h1>", content_type="text/html")
///
/// # Add the catcher to your server
/// app.catchers([handle_404])
/// ```
#[pyfunction]
pub fn catcher(status: Status) -> CatcherBuilder {
CatcherBuilder { status }
Expand Down
42 changes: 21 additions & 21 deletions src/cors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,19 +13,19 @@ use pyo3::prelude::*;
/// Cors: A new CORS configuration with default settings.
///
/// Example:
/// ```python
/// from oxapy import HttpServer, Cors
///
/// app = HttpServer(("127.0.0.1", 8000))
///
/// # Set up CORS with custom configuration
/// cors = Cors()
/// cors.origins = ["https://example.com", "https://app.example.com"]
/// cors.methods = ["GET", "POST", "OPTIONS"]
/// cors.headers = ["Content-Type", "Authorization"]
///
/// app.cors(cors)
/// ```
/// ```python
/// from oxapy import HttpServer, Cors
///
/// app = HttpServer(("127.0.0.1", 8000))
///
/// # Set up CORS with custom configuration
/// cors = Cors()
/// cors.origins = ["https://example.com", "https://app.example.com"]
/// cors.methods = ["GET", "POST", "OPTIONS"]
/// cors.headers = ["Content-Type", "Authorization"]
///
/// app.cors(cors)
/// ```
#[derive(Clone, Debug)]
#[pyclass]
pub struct Cors {
Expand Down Expand Up @@ -66,14 +66,14 @@ impl Cors {
/// Cors: A new CORS configuration with default values.
///
/// Example:
/// ```python
/// # Create CORS with default configuration (allows all origins)
/// cors = Cors()
///
/// # Customize CORS settings
/// cors.origins = ["https://example.com"]
/// cors.allow_credentials = False
/// ```
/// ```python
/// # Create CORS with default configuration (allows all origins)
/// cors = Cors()
///
/// # Customize CORS settings
/// cors.origins = ["https://example.com"]
/// cors.allow_credentials = False
/// ```
#[new]
fn new() -> Self {
Self::default()
Expand Down
7 changes: 3 additions & 4 deletions src/handling/response_handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,14 +99,13 @@ fn process_response(
let route = route.value;

let kwargs = prepare_route_params(params, py)?;

kwargs.set_item("request", request.clone())?;
let request = request.clone();

let result = if !router.middlewares.is_empty() {
let chain = MiddlewareChain::new(router.middlewares.clone());
chain.execute(py, &route.handler.clone(), kwargs.clone())?
chain.execute(py, &route.handler.clone(), (request,), kwargs.clone())?
} else {
route.handler.call(py, (), Some(&kwargs))?
route.handler.call(py, (request,), Some(&kwargs))?
};
convert_to_response(result, py)
} else {
Expand Down
192 changes: 96 additions & 96 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,35 +85,35 @@ struct RequestContext {
/// HttpServer: A new server instance.
///
/// Example:
/// ```python
/// from oxapy import HttpServer, Router
/// ```python
/// from oxapy import HttpServer, Router
///
/// # Create a server on localhost port 8000
/// app = HttpServer(("127.0.0.1", 8000))
/// # Create a server on localhost port 8000
/// app = HttpServer(("127.0.0.1", 8000))
///
/// # Create a router
/// router = Router()
/// # Create a router
/// router = Router()
///
/// # Define route handlers
/// @router.get("/")
/// def home(request):
/// return "Hello, World!"
/// # Define route handlers
/// @router.get("/")
/// def home(request):
/// return "Hello, World!"
///
/// @router.get("/users/{user_id}")
/// def get_user(request, user_id: int):
/// return {"user_id": user_id, "name": f"User {user_id}"}
/// @router.get("/users/{user_id}")
/// def get_user(request, user_id: int):
/// return {"user_id": user_id, "name": f"User {user_id}"}
///
/// @router.post("/api/data")
/// def create_data(request):
/// # Access JSON data from the request
/// data = request.json()
/// return {"status": "success", "received": data}
/// @router.post("/api/data")
/// def create_data(request):
/// # Access JSON data from the request
/// data = request.json()
/// return {"status": "success", "received": data}
///
/// # Attach the router to the server
/// app.attach(router)
/// # Attach the router to the server
/// app.attach(router)
///
/// # Run the server
/// app.run()
/// # Run the server
/// app.run()
/// ```
#[derive(Clone)]
#[pyclass]
Expand All @@ -140,9 +140,9 @@ impl HttpServer {
/// HttpServer: A new server instance ready to be configured.
///
/// Example:
/// ```python
/// server = HttpServer(("127.0.0.1", 5555))
/// ```
/// ```python
/// server = HttpServer(("127.0.0.1", 5555))
/// ```
#[new]
fn new(addr: (String, u16)) -> PyResult<Self> {
let (ip, port) = addr;
Expand Down Expand Up @@ -171,23 +171,23 @@ impl HttpServer {
/// None
///
/// Example:
/// ```python
/// class AppState:
/// def __init__(self):
/// self.counter = 0
/// # You can store database connection pools here
/// self.db_pool = create_database_pool()
///
/// app = HttpServer(("127.0.0.1", 5555))
/// app.app_data(AppState())
///
/// # Example of a handler that increments the counter
/// @router.get("/counter")
/// def increment_counter(request):
/// state = request.app_data
/// state.counter += 1
/// return {"count": state.counter}
/// ```
/// ```python
/// class AppState:
/// def __init__(self):
/// self.counter = 0
/// # You can store database connection pools here
/// self.db_pool = create_database_pool()
///
/// app = HttpServer(("127.0.0.1", 5555))
/// app.app_data(AppState())
///
/// # Example of a handler that increments the counter
/// @router.get("/counter")
/// def increment_counter(request):
/// state = request.app_data
/// state.counter += 1
/// return {"count": state.counter}
/// ```
fn app_data(&mut self, app_data: Py<PyAny>) {
self.app_data = Some(Arc::new(app_data))
}
Expand All @@ -201,27 +201,27 @@ impl HttpServer {
/// None
///
/// Example:
/// ```python
/// router = Router()
///
/// # Define a simple hello world handler
/// @router.get("/")
/// def hello(request):
/// return "Hello, World!"
///
/// # Handler with path parameters
/// @router.get("/users/{user_id}")
/// def get_user(request, user_id: int):
/// return f"User ID: {user_id}"
///
/// # Handler that returns JSON
/// @router.get("/api/data")
/// def get_data(request):
/// return {"message": "Success", "data": [1, 2, 3]}
///
/// # Attach the router to the server
/// server.attach(router)
/// ```
/// ```python
/// router = Router()
///
/// # Define a simple hello world handler
/// @router.get("/")
/// def hello(request):
/// return "Hello, World!"
///
/// # Handler with path parameters
/// @router.get("/users/{user_id}")
/// def get_user(request, user_id: int):
/// return f"User ID: {user_id}"
///
/// # Handler that returns JSON
/// @router.get("/api/data")
/// def get_data(request):
/// return {"message": "Success", "data": [1, 2, 3]}
///
/// # Attach the router to the server
/// server.attach(router)
/// ```
fn attach(&mut self, router: Router) {
self.routers.push(Arc::new(router));
}
Expand All @@ -237,9 +237,9 @@ impl HttpServer {
/// None
///
/// Example:
/// ```python
/// server.session_store(SessionStore())
/// ```
/// ```python
/// server.session_store(SessionStore())
/// ```
fn session_store(&mut self, session_store: SessionStore) {
self.session_store = Some(Arc::new(session_store));
}
Expand All @@ -253,11 +253,11 @@ impl HttpServer {
/// None
///
/// Example:
/// ```python
/// from oxapy import templating
/// ```python
/// from oxapy import templating
///
/// server.template(templating.Template())
/// ```
/// server.template(templating.Template())
/// ```
fn template(&mut self, template: Template) {
self.template = Some(Arc::new(template))
}
Expand All @@ -271,11 +271,11 @@ impl HttpServer {
/// None
///
/// Example:
/// ```python
/// cors = Cors()
/// cors.origins = ["https://example.com"]
/// server.cors(cors)
/// ```
/// ```python
/// cors = Cors()
/// cors.origins = ["https://example.com"]
/// server.cors(cors)
/// ```
fn cors(&mut self, cors: Cors) {
self.cors = Some(Arc::new(cors));
}
Expand All @@ -289,9 +289,9 @@ impl HttpServer {
/// None
///
/// Example:
/// ```python
/// server.max_connections(1000)
/// ```
/// ```python
/// server.max_connections(1000)
/// ```
fn max_connections(&mut self, max_connections: usize) {
self.max_connections = Arc::new(Semaphore::new(max_connections));
}
Expand All @@ -308,9 +308,9 @@ impl HttpServer {
/// None
///
/// Example:
/// ```python
/// server.channel_capacity(200)
/// ```
/// ```python
/// server.channel_capacity(200)
/// ```
fn channel_capacity(&mut self, channel_capacity: usize) {
self.channel_capacity = channel_capacity;
}
Expand All @@ -324,13 +324,13 @@ impl HttpServer {
/// None
///
/// Example:
/// ```python
/// @catcher(Status.NOT_FOUND)
/// def not_found(request, response):
/// return Response("<h1>Page Not Found</h1>", content_type="text/html")
/// ```python
/// @catcher(Status.NOT_FOUND)
/// def not_found(request, response):
/// return Response("<h1>Page Not Found</h1>", content_type="text/html")
///
/// server.catchers([not_found])
/// ```
/// server.catchers([not_found])
/// ```
fn catchers(&mut self, catchers: Vec<PyRef<Catcher>>, py: Python<'_>) {
let mut map = HashMap::default();

Expand All @@ -353,15 +353,15 @@ impl HttpServer {
/// None
///
/// Example:
/// ```python
/// # Run with default number of workers
/// server.run()
///
/// # Or specify number of workers based on CPU count
/// import multiprocessing
/// workers = multiprocessing.cpu_count()
/// server.run(workers)
/// ```
/// ```python
/// # Run with default number of workers
/// server.run()
///
/// # Or specify number of workers based on CPU count
/// import multiprocessing
/// workers = multiprocessing.cpu_count()
/// server.run(workers)
/// ```
#[pyo3(signature=(workers=None))]
fn run(&self, workers: Option<usize>, py: Python<'_>) -> PyResult<()> {
let mut runtime = tokio::runtime::Builder::new_multi_thread();
Expand Down
Loading