mirror of
https://gitlab.computer.surgery/matrix/grapevine.git
synced 2025-12-18 00:01:24 +01:00
axum: factor out non-generic parts of request conversion
This saves ~10% in binary size!
This commit is contained in:
parent
624ff57414
commit
bf1d54defc
1 changed files with 346 additions and 331 deletions
|
|
@ -15,12 +15,13 @@ use axum_extra::{
|
|||
typed_header::TypedHeaderRejectionReason,
|
||||
TypedHeader,
|
||||
};
|
||||
use bytes::{BufMut, BytesMut};
|
||||
use bytes::{BufMut, Bytes, BytesMut};
|
||||
use http::{Request, StatusCode};
|
||||
use http_body_util::BodyExt;
|
||||
use ruma::{
|
||||
api::{
|
||||
client::error::ErrorKind, AuthScheme, IncomingRequest, OutgoingResponse,
|
||||
client::error::ErrorKind, AuthScheme, IncomingRequest, Metadata,
|
||||
OutgoingResponse,
|
||||
},
|
||||
CanonicalJsonValue, OwnedDeviceId, OwnedServerName, OwnedUserId, UserId,
|
||||
};
|
||||
|
|
@ -37,18 +38,24 @@ enum Token {
|
|||
None,
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl<T, S> FromRequest<S> for Ar<T>
|
||||
where
|
||||
T: IncomingRequest,
|
||||
{
|
||||
type Rejection = Error;
|
||||
/// Return value of [`ar_from_request_inner()`], used to construct an [`Ar`].
|
||||
struct ArPieces {
|
||||
sender_user: Option<OwnedUserId>,
|
||||
sender_device: Option<OwnedDeviceId>,
|
||||
sender_servername: Option<OwnedServerName>,
|
||||
json_body: Option<CanonicalJsonValue>,
|
||||
appservice_info: Option<RegistrationInfo>,
|
||||
path_params: Path<Vec<String>>,
|
||||
http_request: Request<Bytes>,
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_lines)]
|
||||
async fn from_request(
|
||||
/// Non-generic part of [`Ar::from_request()`]. Splitting this out reduces
|
||||
/// binary size by ~10%.
|
||||
#[allow(clippy::too_many_lines)]
|
||||
async fn ar_from_request_inner(
|
||||
req: axum::extract::Request,
|
||||
_state: &S,
|
||||
) -> Result<Self, Self::Rejection> {
|
||||
metadata: Metadata,
|
||||
) -> Result<ArPieces> {
|
||||
#[derive(Deserialize)]
|
||||
struct QueryParams {
|
||||
access_token: Option<String>,
|
||||
|
|
@ -68,7 +75,6 @@ where
|
|||
(parts, body)
|
||||
};
|
||||
|
||||
let metadata = T::METADATA;
|
||||
let auth_header: Option<TypedHeader<Authorization<Bearer>>> =
|
||||
parts.extract().await?;
|
||||
let path_params: Path<Vec<String>> = parts.extract().await?;
|
||||
|
|
@ -177,10 +183,7 @@ where
|
|||
.extract::<TypedHeader<Authorization<XMatrix>>>()
|
||||
.await
|
||||
.map_err(|e| {
|
||||
warn!(
|
||||
"Missing or invalid Authorization header: {}",
|
||||
e
|
||||
);
|
||||
warn!("Missing or invalid Authorization header: {}", e);
|
||||
|
||||
let msg = match e.reason() {
|
||||
TypedHeaderRejectionReason::Missing => {
|
||||
|
|
@ -208,9 +211,7 @@ where
|
|||
let mut request_map = BTreeMap::from_iter([
|
||||
(
|
||||
"method".to_owned(),
|
||||
CanonicalJsonValue::String(
|
||||
parts.method.to_string(),
|
||||
),
|
||||
CanonicalJsonValue::String(parts.method.to_string()),
|
||||
),
|
||||
(
|
||||
"uri".to_owned(),
|
||||
|
|
@ -239,8 +240,7 @@ where
|
|||
]);
|
||||
|
||||
if let Some(json_body) = &json_body {
|
||||
request_map
|
||||
.insert("content".to_owned(), json_body.clone());
|
||||
request_map.insert("content".to_owned(), json_body.clone());
|
||||
};
|
||||
|
||||
let keys_result = services()
|
||||
|
|
@ -268,24 +268,20 @@ where
|
|||
keys,
|
||||
)]);
|
||||
|
||||
match ruma::signatures::verify_json(
|
||||
&pub_key_map,
|
||||
&request_map,
|
||||
) {
|
||||
match ruma::signatures::verify_json(&pub_key_map, &request_map)
|
||||
{
|
||||
Ok(()) => (None, None, Some(x_matrix.origin), None),
|
||||
Err(e) => {
|
||||
warn!(
|
||||
"Failed to verify json request from {}: \
|
||||
{}\n{:?}",
|
||||
"Failed to verify json request from {}: {}\n{:?}",
|
||||
x_matrix.origin, e, request_map
|
||||
);
|
||||
|
||||
if parts.uri.to_string().contains('@') {
|
||||
warn!(
|
||||
"Request uri contained '@' character. \
|
||||
Make sure your reverse proxy gives \
|
||||
Grapevine the raw uri (apache: use \
|
||||
nocanon)"
|
||||
"Request uri contained '@' character. Make \
|
||||
sure your reverse proxy gives Grapevine the \
|
||||
raw uri (apache: use nocanon)"
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -308,8 +304,7 @@ where
|
|||
) => {
|
||||
return Err(Error::BadRequest(
|
||||
ErrorKind::Unauthorized,
|
||||
"Only server signatures should be used on this \
|
||||
endpoint.",
|
||||
"Only server signatures should be used on this endpoint.",
|
||||
));
|
||||
}
|
||||
(AuthScheme::AppserviceToken, Token::User(_)) => {
|
||||
|
|
@ -327,10 +322,7 @@ where
|
|||
|
||||
if let Some(CanonicalJsonValue::Object(json_body)) = &mut json_body {
|
||||
let user_id = sender_user.clone().unwrap_or_else(|| {
|
||||
UserId::parse_with_server_name(
|
||||
"",
|
||||
services().globals.server_name(),
|
||||
)
|
||||
UserId::parse_with_server_name("", services().globals.server_name())
|
||||
.expect("we know this is valid")
|
||||
});
|
||||
|
||||
|
|
@ -347,8 +339,7 @@ where
|
|||
)
|
||||
});
|
||||
|
||||
if let Some(CanonicalJsonValue::Object(initial_request)) =
|
||||
uiaa_request
|
||||
if let Some(CanonicalJsonValue::Object(initial_request)) = uiaa_request
|
||||
{
|
||||
for (key, value) in initial_request {
|
||||
json_body.entry(key).or_insert(value);
|
||||
|
|
@ -360,15 +351,39 @@ where
|
|||
.expect("value serialization can't fail");
|
||||
body = buf.into_inner().freeze();
|
||||
}
|
||||
|
||||
let http_request = http_request.body(&*body).unwrap();
|
||||
let http_request = http_request.body(body).unwrap();
|
||||
|
||||
debug!("{:?}", http_request);
|
||||
|
||||
let body = T::try_from_http_request(http_request, &path_params)
|
||||
Ok(ArPieces {
|
||||
sender_user,
|
||||
sender_device,
|
||||
sender_servername,
|
||||
json_body,
|
||||
appservice_info,
|
||||
path_params,
|
||||
http_request,
|
||||
})
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl<T, S> FromRequest<S> for Ar<T>
|
||||
where
|
||||
T: IncomingRequest,
|
||||
{
|
||||
type Rejection = Error;
|
||||
|
||||
async fn from_request(
|
||||
req: axum::extract::Request,
|
||||
_state: &S,
|
||||
) -> Result<Self, Self::Rejection> {
|
||||
let pieces = ar_from_request_inner(req, T::METADATA).await?;
|
||||
|
||||
let body =
|
||||
T::try_from_http_request(pieces.http_request, &pieces.path_params)
|
||||
.map_err(|e| {
|
||||
warn!("try_from_http_request failed: {:?}", e);
|
||||
debug!("JSON body: {:?}", json_body);
|
||||
debug!("JSON body: {:?}", pieces.json_body);
|
||||
Error::BadRequest(
|
||||
ErrorKind::BadJson,
|
||||
"Failed to deserialize request.",
|
||||
|
|
@ -377,11 +392,11 @@ where
|
|||
|
||||
Ok(Ar {
|
||||
body,
|
||||
sender_user,
|
||||
sender_device,
|
||||
sender_servername,
|
||||
json_body,
|
||||
appservice_info,
|
||||
sender_user: pieces.sender_user,
|
||||
sender_device: pieces.sender_device,
|
||||
sender_servername: pieces.sender_servername,
|
||||
json_body: pieces.json_body,
|
||||
appservice_info: pieces.appservice_info,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue