swadhinbiswas

[email protected]
2026-07-25 15:36:25 +0600 committed NaN years ago
afc0c6e
commit afc0c6e
1 file changed
+63 -37
Showing 1 changed file+63-37
▼crates/justapi-py/src/request.rs
+63-37
39
39
(host.to_string(), None)
40
40
}
41
41
42
-pub(crate) fn build_headers(py: Python<'_>, conn: &Conn) -> Py<PyAny> {
42
+pub(crate) fn build_headers(py: Python<'_>, conn: &Conn) -> PyResult<Py<PyAny>> {
43
43
let raw: Vec<(Vec<u8>, Vec<u8>)> = conn.headers_raw.clone();
44
- Bound::new(py, Headers { raw }).unwrap().into_any().unbind()
44
+ Ok(Bound::new(py, Headers { raw })?.into_any().unbind())
45
45
}
46
46
47
-pub(crate) fn build_query_params(py: Python<'_>, conn: &Conn) -> Py<PyAny> {
47
+pub(crate) fn build_query_params(py: Python<'_>, conn: &Conn) -> PyResult<Py<PyAny>> {
48
48
let qs = String::from_utf8_lossy(&conn.query_string_raw).to_string();
49
49
let mut items: Vec<(String, String)> = Vec::new();
50
50
for pair in qs.split('&') {
57
57
};
58
58
items.push((percent_decode(k), percent_decode(v)));
59
59
}
60
- Bound::new(py, QueryParams { items }).unwrap().into_any().unbind()
60
+ Ok(Bound::new(py, QueryParams { items })?.into_any().unbind())
61
61
}
62
62
63
63
pub(crate) fn build_cookies(py: Python<'_>, conn: &Conn) -> Py<PyAny> {
83
83
path: &str,
84
84
query: &[u8],
85
85
fragment: &str,
86
-) -> Py<PyAny> {
86
+) -> PyResult<Py<PyAny>> {
87
87
let (hostname, port) = split_host_port(host);
88
88
let url = URL {
89
89
scheme: scheme.to_string(),
93
93
query: String::from_utf8_lossy(query).to_string(),
94
94
fragment: fragment.to_string(),
95
95
};
96
- Bound::new(py, url).unwrap().into_any().unbind()
96
+ Ok(Bound::new(py, url)?.into_any().unbind())
97
97
}
98
98
99
99
fn build_scope(py: Python<'_>, conn: &Conn) -> Py<PyAny> {
195
195
client: Option<(String, u16)>,
196
196
app: Option<Py<PyAny>>,
197
197
http_version: String,
198
+ auth_claims: Option<String>,
198
199
) -> Self {
199
- let state = PyDict::new(py).into();
200
+ let state = PyDict::new(py);
201
+ // Bridge JWT claims from the Rust middleware into request.state["auth"].
202
+ // The `auth_claims` is a JSON string of the decoded JWT payload, set by
203
+ // the middleware and forwarded through `call_python_handler`.
204
+ if let Some(claims_json) = &auth_claims {
205
+ if let Ok(serde_json::Value::Object(map)) =
206
+ serde_json::from_str::<serde_json::Value>(claims_json)
207
+ {
208
+ let d = PyDict::new(py);
209
+ for (k, v) in &map {
210
+ if let Ok(val) = json_value_to_request(py, v) {
211
+ d.set_item(k.as_str(), val).ok();
212
+ }
213
+ }
214
+ state.set_item("auth", d).ok();
215
+ }
216
+ }
217
+ let state = state.into();
200
218
let conn = Conn {
201
219
method,
202
220
path,
232
250
}
233
251
}
234
252
253
+fn json_value_to_request<'py>(
254
+ py: Python<'py>,
255
+ v: &serde_json::Value,
256
+) -> PyResult<Bound<'py, PyAny>> {
257
+ match v {
258
+ serde_json::Value::Null => Ok(py.None().into_bound(py)),
259
+ serde_json::Value::Bool(b) => Ok((*b).into_pyobject(py)?.as_any().clone()),
260
+ serde_json::Value::Number(n) => {
261
+ if let Some(i) = n.as_i64() {
262
+ Ok(i.into_pyobject(py)?.as_any().clone())
263
+ } else if let Some(f) = n.as_f64() {
264
+ Ok(f.into_pyobject(py)?.as_any().clone())
265
+ } else {
266
+ Ok(py.None().into_bound(py))
267
+ }
268
+ }
269
+ serde_json::Value::String(s) => Ok(s.into_pyobject(py)?.as_any().clone()),
270
+ serde_json::Value::Array(arr) => {
271
+ let list = PyList::empty(py);
272
+ for item in arr {
273
+ list.append(json_value_to_request(py, item)?).ok();
274
+ }
275
+ Ok(list.as_any().clone())
276
+ }
277
+ serde_json::Value::Object(_) => Ok(py.None().into_bound(py)),
278
+ }
279
+}
280
+
235
281
#[pymethods]
236
282
impl Request {
237
283
#[getter]
270
316
271
317
#[getter]
272
318
fn headers(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
273
- Ok(build_headers(py, &self.conn))
319
+ build_headers(py, &self.conn)
274
320
}
275
321
276
322
#[getter]
280
326
281
327
#[getter]
282
328
fn query_params(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
283
- Ok(build_query_params(py, &self.conn))
329
+ build_query_params(py, &self.conn)
284
330
}
285
331
286
332
#[getter]
305
351
#[getter]
306
352
fn url(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
307
353
let host = host_of(&self.conn).unwrap_or_else(|| "localhost".to_string());
308
- Ok(build_url(
309
- py,
310
- &self.conn.scheme,
311
- &host,
312
- &self.conn.path,
313
- &self.conn.query_string_raw,
314
- "",
315
- ))
354
+ build_url(py, &self.conn.scheme, &host, &self.conn.path, &self.conn.query_string_raw, "")
316
355
}
317
356
318
357
#[getter]
319
358
fn base_url(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
320
359
let host = host_of(&self.conn).unwrap_or_else(|| "localhost".to_string());
321
- Ok(build_url(py, &self.conn.scheme, &host, "", b"", ""))
360
+ build_url(py, &self.conn.scheme, &host, "", b"", "")
322
361
}
323
362
324
363
#[getter]
328
367
329
368
#[getter]
330
369
fn state(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
331
- Ok(Bound::new(py, State { dict: self.conn.state.clone_ref(py) })
332
- .unwrap()
333
- .into_any()
334
- .unbind())
370
+ Ok(Bound::new(py, State { dict: self.conn.state.clone_ref(py) })?.into_any().unbind())
335
371
}
336
372
337
373
#[getter]
636
672
637
673
#[getter]
638
674
fn headers(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
639
- Ok(build_headers(py, &self.conn))
675
+ build_headers(py, &self.conn)
640
676
}
641
677
642
678
#[getter]
646
682
647
683
#[getter]
648
684
fn query_params(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
649
- Ok(build_query_params(py, &self.conn))
685
+ build_query_params(py, &self.conn)
650
686
}
651
687
652
688
#[getter]
666
702
#[getter]
667
703
fn url(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
668
704
let host = host_of(&self.conn).unwrap_or_else(|| "localhost".to_string());
669
- Ok(build_url(
670
- py,
671
- &self.conn.scheme,
672
- &host,
673
- &self.conn.path,
674
- &self.conn.query_string_raw,
675
- "",
676
- ))
705
+ build_url(py, &self.conn.scheme, &host, &self.conn.path, &self.conn.query_string_raw, "")
677
706
}
678
707
679
708
#[getter]
680
709
fn base_url(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
681
710
let host = host_of(&self.conn).unwrap_or_else(|| "localhost".to_string());
682
- Ok(build_url(py, &self.conn.scheme, &host, "", b"", ""))
711
+ build_url(py, &self.conn.scheme, &host, "", b"", "")
683
712
}
684
713
685
714
#[getter]
689
718
690
719
#[getter]
691
720
fn state(&self, py: Python<'_>) -> PyResult<Py<PyAny>> {
692
- Ok(Bound::new(py, State { dict: self.conn.state.clone_ref(py) })
693
- .unwrap()
694
- .into_any()
695
- .unbind())
721
+ Ok(Bound::new(py, State { dict: self.conn.state.clone_ref(py) })?.into_any().unbind())
696
722
}
697
723
698
724
#[getter]
699
725