Skip to content

Commit

Permalink
Add URL queries support (#146)
Browse files Browse the repository at this point in the history
* Add support for providing URL form quries to Python as a dict.
The data can be accessed similar to POST requests, using "queries"
instead of "params".

* Update docs to include notes about accessing form data.
Update unit tests to verify URL form queries work correctly.

* Fix query return value when there are no values are passed.
Fix query return value when only a keyword is passed for the key-value pair.
  • Loading branch information
patchgamestudio authored Jan 5, 2022
1 parent 1576ea5 commit ba4aae8
Show file tree
Hide file tree
Showing 6 changed files with 40 additions and 0 deletions.
1 change: 1 addition & 0 deletions dev-requirements.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
flake8==4.0.1
black==21.12b0
websockets==10.1
11 changes: 11 additions & 0 deletions docs/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand Down
5 changes: 5 additions & 0 deletions integration_tests/base_routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down
6 changes: 6 additions & 0 deletions integration_tests/test_get_requests.py
Original file line number Diff line number Diff line change
Expand Up @@ -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()=={}
5 changes: 5 additions & 0 deletions src/processor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,15 @@ pub async fn handle_request(
payload: &mut web::Payload,
req: &HttpRequest,
route_params: HashMap<String, String>,
queries: HashMap<&str, &str>,
) -> HttpResponse {
let contents = match execute_http_function(
function,
payload,
headers,
req,
route_params,
queries,
number_of_params,
)
.await
Expand Down Expand Up @@ -87,6 +89,7 @@ async fn execute_http_function(
headers: &Headers,
req: &HttpRequest,
route_params: HashMap<String, String>,
queries: HashMap<&str, &str>,
number_of_params: u8,
) -> Result<String> {
let mut data: Option<Vec<u8>> = None;
Expand Down Expand Up @@ -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 {
Expand Down
12 changes: 12 additions & 0 deletions src/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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(
Expand All @@ -243,6 +254,7 @@ async fn index(
&mut payload,
&req,
route_params,
queries,
)
.await
}
Expand Down

0 comments on commit ba4aae8

Please sign in to comment.