diff --git a/dev-requirements.txt b/dev-requirements.txt index 591458162..e2f9f4e9f 100644 --- a/dev-requirements.txt +++ b/dev-requirements.txt @@ -1,2 +1,3 @@ flake8==4.0.1 black==21.12b0 +websockets==10.1 diff --git a/docs/api.md b/docs/api.md index c4ec8c475..af8b4e51d 100644 --- a/docs/api.md +++ b/docs/api.md @@ -102,6 +102,17 @@ async def json(request): return jsonify({"hello": "world"}) ``` +### Getting URL form data +You can access URL form data with the request object similar to how you access params. + +```python3 +@app.get("/get") +async def query(request): + form_data = request.get("queries", {}) + print(form_data) + return jsonify({"queries": form_data}) +``` + ### Returning a JSON Response You can also serve JSON responses when serving HTTP request using the following way. diff --git a/integration_tests/base_routes.py b/integration_tests/base_routes.py index dbb6836cd..873f18c7d 100644 --- a/integration_tests/base_routes.py +++ b/integration_tests/base_routes.py @@ -51,6 +51,11 @@ async def test(request): async def json_get(): return jsonify({"hello": "world"}) +@app.get("/query") +async def query_get(request): + query_data = request["queries"] + return jsonify(query_data) + @app.post("/jsonify/:id") async def json(request): diff --git a/integration_tests/test_get_requests.py b/integration_tests/test_get_requests.py index 2823f9025..629d25d45 100644 --- a/integration_tests/test_get_requests.py +++ b/integration_tests/test_get_requests.py @@ -15,3 +15,9 @@ def test_html(session): r = requests.get(f"{BASE_URL}/test/123") assert "Hello world. How are you?" in r.text +def test_queries(session): + r = requests.get(f"{BASE_URL}/query?hello=robyn") + assert r.json()=={"hello":"robyn"} + + r = requests.get(f"{BASE_URL}/query") + assert r.json()=={} diff --git a/src/processor.rs b/src/processor.rs index dac303db9..640416999 100644 --- a/src/processor.rs +++ b/src/processor.rs @@ -40,6 +40,7 @@ pub async fn handle_request( payload: &mut web::Payload, req: &HttpRequest, route_params: HashMap, + queries: HashMap<&str, &str>, ) -> HttpResponse { let contents = match execute_http_function( function, @@ -47,6 +48,7 @@ pub async fn handle_request( headers, req, route_params, + queries, number_of_params, ) .await @@ -87,6 +89,7 @@ async fn execute_http_function( headers: &Headers, req: &HttpRequest, route_params: HashMap, + queries: HashMap<&str, &str>, number_of_params: u8, ) -> Result { let mut data: Option> = None; @@ -115,11 +118,13 @@ async fn execute_http_function( for elem in headers.into_iter() { headers_python.insert(elem.key().clone(), elem.value().clone()); } + match function { PyFunction::CoRoutine(handler) => { let output = Python::with_gil(|py| { let handler = handler.as_ref(py); request.insert("params", route_params.into_py(py)); + request.insert("queries", queries.into_py(py)); request.insert("headers", headers_python.into_py(py)); match data { diff --git a/src/server.rs b/src/server.rs index a88e8aeb3..e252d343c 100644 --- a/src/server.rs +++ b/src/server.rs @@ -9,6 +9,7 @@ use std::sync::atomic::AtomicBool; use std::sync::atomic::Ordering::{Relaxed, SeqCst}; use std::sync::{Arc, RwLock}; use std::thread; +use std::collections::HashMap; use actix_files::Files; use actix_http::KeepAlive; @@ -234,6 +235,16 @@ async fn index( mut payload: web::Payload, req: HttpRequest, ) -> impl Responder { + let mut queries = HashMap::new(); + + if req.query_string().len() > 0 { + let split = req.query_string().split("&"); + for s in split { + let params = s.split_once("=").unwrap_or((s, "")); + queries.insert(params.0, params.1); + } + } + match router.get_route(req.method().clone(), req.uri().path()) { Some(((handler_function, number_of_params), route_params)) => { handle_request( @@ -243,6 +254,7 @@ async fn index( &mut payload, &req, route_params, + queries, ) .await }