Skip to content

Commit 09f0957

Browse files
authored
Helpers to transform Twisted requests to Rust http Requests/Responses (#17081)
This adds functions to transform a Twisted request to the `http::Request`, and then to send back an `http::Response` through it. It also imports the SynapseError exception so that we can throw that from Rust code directly Example usage of this would be: ```rust use crate::http::{http_request_from_twisted, http_response_to_twisted, HeaderMapPyExt}; fn handler(twisted_request: &PyAny) -> PyResult<()> { let request = http_request_from_twisted(twisted_request)?; let ua: headers::UserAgent = request.headers().typed_get_required()?; if whatever { return Err((crate::errors::SynapseError::new( StatusCode::UNAUTHORIZED, "Whatever".to_owned "M_UNAUTHORIZED", None, None, ))); } let response = Response::new("hello".as_bytes()); http_response_to_twisted(twisted_request, response)?; Ok(()) } ```
1 parent 803f05f commit 09f0957

File tree

6 files changed

+321
-2
lines changed

6 files changed

+321
-2
lines changed

Cargo.lock

Lines changed: 90 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

changelog.d/17081.misc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Add helpers to transform Twisted requests to Rust http Requests/Responses.

rust/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ name = "synapse.synapse_rust"
2323

2424
[dependencies]
2525
anyhow = "1.0.63"
26+
bytes = "1.6.0"
27+
headers = "0.4.0"
28+
http = "1.1.0"
2629
lazy_static = "1.4.0"
2730
log = "0.4.17"
2831
pyo3 = { version = "0.20.0", features = [

rust/src/errors.rs

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
/*
2+
* This file is licensed under the Affero General Public License (AGPL) version 3.
3+
*
4+
* Copyright (C) 2024 New Vector, Ltd
5+
*
6+
* This program is free software: you can redistribute it and/or modify
7+
* it under the terms of the GNU Affero General Public License as
8+
* published by the Free Software Foundation, either version 3 of the
9+
* License, or (at your option) any later version.
10+
*
11+
* See the GNU Affero General Public License for more details:
12+
* <https://www.gnu.org/licenses/agpl-3.0.html>.
13+
*/
14+
15+
#![allow(clippy::new_ret_no_self)]
16+
17+
use std::collections::HashMap;
18+
19+
use http::{HeaderMap, StatusCode};
20+
use pyo3::{exceptions::PyValueError, import_exception};
21+
22+
import_exception!(synapse.api.errors, SynapseError);
23+
24+
impl SynapseError {
25+
pub fn new(
26+
code: StatusCode,
27+
message: String,
28+
errcode: &'static str,
29+
additional_fields: Option<HashMap<String, String>>,
30+
headers: Option<HeaderMap>,
31+
) -> pyo3::PyErr {
32+
// Transform the HeaderMap into a HashMap<String, String>
33+
let headers = if let Some(headers) = headers {
34+
let mut map = HashMap::with_capacity(headers.len());
35+
for (key, value) in headers.iter() {
36+
let Ok(value) = value.to_str() else {
37+
// This should never happen, but we don't want to panic in case it does
38+
return PyValueError::new_err(
39+
"Could not construct SynapseError: header value is not valid ASCII",
40+
);
41+
};
42+
43+
map.insert(key.as_str().to_owned(), value.to_owned());
44+
}
45+
Some(map)
46+
} else {
47+
None
48+
};
49+
50+
SynapseError::new_err((code.as_u16(), message, errcode, additional_fields, headers))
51+
}
52+
}
53+
54+
import_exception!(synapse.api.errors, NotFoundError);
55+
56+
impl NotFoundError {
57+
pub fn new() -> pyo3::PyErr {
58+
NotFoundError::new_err(())
59+
}
60+
}

0 commit comments

Comments
 (0)