Skip to main content

tuwunel_api/router/
request.rs

1use std::str;
2
3use axum::{RequestExt, RequestPartsExt, extract::Path};
4use axum_extra::extract::cookie::CookieJar;
5use bytes::Bytes;
6use http::request::Parts;
7use serde::Deserialize;
8use tuwunel_core::{Result, err, smallstr::SmallString, smallvec::SmallVec};
9use tuwunel_service::Services;
10
11#[derive(Debug, Deserialize)]
12pub(super) struct QueryParams {
13	pub(super) access_token: Option<String>,
14
15	pub(super) user_id: Option<UserId>,
16
17	pub(super) device_id: Option<DeviceId>,
18
19	#[serde(rename = "org.matrix.msc3202.device_id")]
20	pub(super) msc3202_device_id: Option<DeviceId>,
21}
22
23impl QueryParams {
24	pub(super) fn device_id(&self) -> Option<&str> {
25		self.device_id
26			.as_deref()
27			.or(self.msc3202_device_id.as_deref())
28	}
29}
30
31pub(super) type UserId = SmallString<[u8; 48]>;
32pub(super) type DeviceId = SmallString<[u8; 24]>;
33
34#[derive(Debug)]
35pub(super) struct Request {
36	pub(super) cookie: CookieJar,
37	pub(super) path: Path<PathParams>,
38	pub(super) query: QueryParams,
39	pub(super) body: Bytes,
40	pub(super) parts: Parts,
41}
42
43pub(super) type PathParams = SmallVec<[PathParam; 8]>;
44pub(super) type PathParam = SmallString<[u8; 32]>;
45
46pub(super) async fn from(
47	services: &Services,
48	request: http::Request<axum::body::Body>,
49) -> Result<Request> {
50	let limited = request.with_limited_body();
51	let (mut parts, body) = limited.into_parts();
52
53	let cookie: CookieJar = parts.extract().await?;
54	let path: Path<PathParams> = parts.extract().await?;
55	let query = parts.uri.query().unwrap_or_default();
56	let query = serde_html_form::from_str(query)
57		.map_err(|e| err!(Request(Unknown("Failed to read query parameters: {e}"))))?;
58
59	let max_body_size = services.server.config.max_request_size;
60
61	let body = axum::body::to_bytes(body, max_body_size)
62		.await
63		.map_err(|e| err!(Request(TooLarge("Request body too large: {e}"))))?;
64
65	Ok(Request { cookie, path, query, body, parts })
66}