Skip to content

Commit a32edf5

Browse files
authored
Less allocations in flash impl (#627)
* restructure cursiv cookie handling * own cookie signing using blake3 * fix routes
1 parent 8531dbb commit a32edf5

File tree

7 files changed

+172
-78
lines changed

7 files changed

+172
-78
lines changed

Cargo.lock

+5-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

+1-5
Original file line numberDiff line numberDiff line change
@@ -113,11 +113,7 @@ color-eyre = "0.6.3"
113113
colored_json = "5.0.0"
114114
const_format = "0.2.34"
115115
const-oid = { version = "0.9.6", features = ["db"] }
116-
cookie = { version = "0.18.1", features = [
117-
"key-expansion",
118-
"percent-encode",
119-
"signed",
120-
] }
116+
cookie = { version = "0.18.1", features = ["percent-encode"] }
121117
derive_builder = "0.20.2"
122118
derive_more = { version = "1.0.0", features = ["from"] }
123119
diesel = { version = "2.2.6", default-features = false, features = [

kitsune/src/http/router.rs

+34-30
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,15 @@ use tower_http_digest::VerifyDigestLayer;
1616
use tower_stop_using_brave::StopUsingBraveLayer;
1717
use tower_x_clacks_overhead::XClacksOverheadLayer;
1818

19+
#[allow(clippy::too_many_lines)]
1920
pub fn create(state: Zustand, server_config: &server::Configuration) -> eyre::Result<Router> {
2021
let router = Router::new()
2122
.route(
22-
"/confirm-account/:confirmation_token",
23+
"/confirm-account/{confirmation_token}",
2324
routing::get(handler::confirm_account::get),
2425
)
25-
.route("/emojis/:id", routing::get(handler::custom_emojis::get))
26-
.route("/media/:id", routing::get(handler::media::get))
26+
.route("/emojis/{id}", routing::get(handler::custom_emojis::get))
27+
.route("/media/{id}", routing::get(handler::media::get))
2728
.route(
2829
"/nodeinfo/2.1",
2930
routing::get(handler::nodeinfo::two_one::get),
@@ -42,27 +43,30 @@ pub fn create(state: Zustand, server_config: &server::Configuration) -> eyre::Re
4243
.nest(
4344
"/posts",
4445
Router::new()
45-
.route("/:id", routing::get(handler::posts::get))
46-
.route("/:id/activity", routing::get(handler::posts::activity::get)),
46+
.route("/{id}", routing::get(handler::posts::get))
47+
.route(
48+
"/{id}/activity",
49+
routing::get(handler::posts::activity::get),
50+
),
4751
)
4852
.nest(
4953
"/users",
5054
Router::new()
51-
.route("/:user_id", routing::get(handler::users::get))
55+
.route("/{user_id}", routing::get(handler::users::get))
5256
.route(
53-
"/:user_id/followers",
57+
"/{user_id}/followers",
5458
routing::get(handler::users::followers::get),
5559
)
5660
.route(
57-
"/:user_id/following",
61+
"/{user_id}/following",
5862
routing::get(handler::users::following::get),
5963
)
6064
.route(
61-
"/:user_id/inbox",
65+
"/{user_id}/inbox",
6266
routing::post(handler::users::inbox::post).layer(VerifyDigestLayer::default()),
6367
)
6468
.route(
65-
"/:user_id/outbox",
69+
"/{user_id}/outbox",
6670
routing::get(handler::users::outbox::get),
6771
),
6872
)
@@ -78,7 +82,7 @@ pub fn create(state: Zustand, server_config: &server::Configuration) -> eyre::Re
7882
routing::get(handler::well_known::webfinger::get),
7983
),
8084
)
81-
.route("/public/*path", routing::get(handler::public::get));
85+
.route("/public/{*path}", routing::get(handler::public::get));
8286

8387
#[cfg(feature = "oidc")]
8488
let router = router.route("/oidc/callback", routing::get(handler::oidc::callback::get));
@@ -110,19 +114,19 @@ pub fn create(state: Zustand, server_config: &server::Configuration) -> eyre::Re
110114
"/accounts",
111115
Router::new()
112116
.route(
113-
"/:id",
117+
"/{id}",
114118
routing::get(handler::mastodon::api::v1::accounts::get),
115119
)
116120
.route(
117-
"/:id/follow",
121+
"/{id}/follow",
118122
routing::post(handler::mastodon::api::v1::accounts::follow::post),
119123
)
120124
.route(
121-
"/:id/statuses",
125+
"/{id}/statuses",
122126
routing::get(handler::mastodon::api::v1::accounts::statuses::get),
123127
)
124128
.route(
125-
"/:id/unfollow",
129+
"/{id}/unfollow",
126130
routing::post(handler::mastodon::api::v1::accounts::unfollow::post),
127131
)
128132
.route(
@@ -164,13 +168,13 @@ pub fn create(state: Zustand, server_config: &server::Configuration) -> eyre::Re
164168
routing::get(handler::mastodon::api::v1::follow_requests::get),
165169
)
166170
.route(
167-
"/:id/authorize",
171+
"/{id}/authorize",
168172
routing::post(
169173
handler::mastodon::api::v1::follow_requests::accept::post,
170174
),
171175
)
172176
.route(
173-
"/:id/reject",
177+
"/{id}/reject",
174178
routing::post(
175179
handler::mastodon::api::v1::follow_requests::reject::post,
176180
),
@@ -192,7 +196,7 @@ pub fn create(state: Zustand, server_config: &server::Configuration) -> eyre::Re
192196
),
193197
)
194198
.route(
195-
"/:id",
199+
"/{id}",
196200
routing::get(handler::mastodon::api::v1::media::get)
197201
.put(handler::mastodon::api::v1::media::put),
198202
),
@@ -205,11 +209,11 @@ pub fn create(state: Zustand, server_config: &server::Configuration) -> eyre::Re
205209
routing::get(handler::mastodon::api::v1::notifications::get),
206210
)
207211
.route(
208-
"/:id",
212+
"/{id}",
209213
routing::get(handler::mastodon::api::v1::notifications::get_by_id),
210214
)
211215
.route(
212-
"/:id/dismiss",
216+
"/{id}/dismiss",
213217
routing::post(
214218
handler::mastodon::api::v1::notifications::dismiss::post,
215219
),
@@ -229,49 +233,49 @@ pub fn create(state: Zustand, server_config: &server::Configuration) -> eyre::Re
229233
routing::post(handler::mastodon::api::v1::statuses::post),
230234
)
231235
.route(
232-
"/:id",
236+
"/{id}",
233237
routing::delete(handler::mastodon::api::v1::statuses::delete)
234238
.get(handler::mastodon::api::v1::statuses::get)
235239
.put(handler::mastodon::api::v1::statuses::put),
236240
)
237241
.route(
238-
"/:id/context",
242+
"/{id}/context",
239243
routing::get(handler::mastodon::api::v1::statuses::context::get),
240244
)
241245
.route(
242-
"/:id/favourite",
246+
"/{id}/favourite",
243247
routing::post(
244248
handler::mastodon::api::v1::statuses::favourite::post,
245249
),
246250
)
247251
.route(
248-
"/:id/favourited_by",
252+
"/{id}/favourited_by",
249253
routing::get(
250254
handler::mastodon::api::v1::statuses::favourited_by::get,
251255
),
252256
)
253257
.route(
254-
"/:id/reblog",
258+
"/{id}/reblog",
255259
routing::post(handler::mastodon::api::v1::statuses::reblog::post),
256260
)
257261
.route(
258-
"/:id/reblogged_by",
262+
"/{id}/reblogged_by",
259263
routing::get(
260264
handler::mastodon::api::v1::statuses::reblogged_by::get,
261265
),
262266
)
263267
.route(
264-
"/:id/source",
268+
"/{id}/source",
265269
routing::get(handler::mastodon::api::v1::statuses::source::get),
266270
)
267271
.route(
268-
"/:id/unfavourite",
272+
"/{id}/unfavourite",
269273
routing::post(
270274
handler::mastodon::api::v1::statuses::unfavourite::post,
271275
),
272276
)
273277
.route(
274-
"/:id/unreblog",
278+
"/{id}/unreblog",
275279
routing::post(handler::mastodon::api::v1::statuses::unreblog::post),
276280
),
277281
)
@@ -303,7 +307,7 @@ pub fn create(state: Zustand, server_config: &server::Configuration) -> eyre::Re
303307
),
304308
)
305309
.route(
306-
"/:id",
310+
"/{id}",
307311
routing::get(handler::mastodon::api::v1::media::get)
308312
.put(handler::mastodon::api::v1::media::put),
309313
),

lib/cursiv/src/service.rs

+27-18
Original file line numberDiff line numberDiff line change
@@ -35,25 +35,34 @@ where
3535
}
3636

3737
fn call(&mut self, mut req: Request<ReqBody>) -> Self::Future {
38-
let csrf_cookie = req
39-
.headers()
40-
.get_all(header::COOKIE)
41-
.into_iter()
42-
.filter_map(|value| value.to_str().ok()) // Filter out all the values that aren't valid UTF-8
43-
.flat_map(Cookie::split_parse_encoded) // Parse all the cookie headers and flatten the resulting iterator into a contiguous one
44-
.flatten() // Call `.flatten()` to turn `Result<Cookie, Error>` -> `Cookie`, ignoring all the errors
45-
.find(|cookie| cookie.name() == CSRF_COOKIE_NAME); // Find the cookie with the name of our CSRF cookie
38+
let read_data = {
39+
let mut csrf_data = None;
40+
'outer: for header in req.headers().get_all(header::COOKIE) {
41+
let Ok(value_str) = header.to_str() else {
42+
continue;
43+
};
4644

47-
let read_data = if let Some(csrf_cookie) = csrf_cookie {
48-
csrf_cookie
49-
.value_trimmed()
50-
.split_once('.')
51-
.map(|(hash, message)| CsrfData {
52-
hash: hash.into(),
53-
message: message.into(),
54-
})
55-
} else {
56-
None
45+
for cookie in Cookie::split_parse_encoded(value_str) {
46+
let Ok(cookie) = cookie else {
47+
continue;
48+
};
49+
50+
if cookie.name() == CSRF_COOKIE_NAME {
51+
let Some((hash, message)) = cookie.value_trimmed().split_once('.') else {
52+
continue;
53+
};
54+
55+
csrf_data = Some(CsrfData {
56+
hash: hash.into(),
57+
message: message.into(),
58+
});
59+
60+
break 'outer;
61+
}
62+
}
63+
}
64+
65+
csrf_data
5766
};
5867

5968
let handle = CsrfHandle {

lib/flashy/Cargo.toml

+5
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,19 @@ license = "MIT OR Apache-2.0"
77

88
[dependencies]
99
axum-core = { workspace = true, optional = true }
10+
blake3.workspace = true
1011
cookie.workspace = true
1112
futures-test.workspace = true
13+
hex-simd.workspace = true
1214
http.workspace = true
1315
pin-project-lite.workspace = true
16+
rand.workspace = true
1417
serde.workspace = true
1518
sonic-rs.workspace = true
19+
subtle.workspace = true
1620
tower.workspace = true
1721
triomphe.workspace = true
22+
zeroize.workspace = true
1823

1924
[features]
2025
axum = ["dep:axum-core"]

0 commit comments

Comments
 (0)