Skip to main content

max / makenotwork

multithreaded: bump tower-http, tower_governor, and governor tower-http 0.6 to 0.7, tower_governor 0.6 to 0.8, governor 0.8 to 0.10. tower_governor made GovernorLayer's fields private, so the five struct literals become GovernorLayer::new(config). tower-sessions stays on 0.14: tower-sessions-sqlx-store 0.15.0 is the latest release and still builds against tower-sessions-core 0.14, so PostgresStore does not implement the 0.15 SessionStore trait. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Author: Max Johnson <me@maxj.phd> · 2026-07-22 17:01 UTC
Commit: 7fbc187655ae196100d673eaca6c0e18c7236c9b
Parent: 5978e13
4 files changed, +79 insertions, -33 deletions
@@ -1472,9 +1472,9 @@ dependencies = [
1472 1472
1473 1473 [[package]]
1474 1474 name = "governor"
1475 - version = "0.8.1"
1475 + version = "0.10.4"
1476 1476 source = "registry+https://github.com/rust-lang/crates.io-index"
1477 - checksum = "be93b4ec2e4710b04d9264c0c7350cdd62a8c20e5e4ac732552ebb8f0debe8eb"
1477 + checksum = "9efcab3c1958580ff1f25a2a41be1668f7603d849bb63af523b208a3cc1223b8"
1478 1478 dependencies = [
1479 1479 "cfg-if",
1480 1480 "dashmap",
@@ -1482,7 +1482,7 @@ dependencies = [
1482 1482 "futures-timer",
1483 1483 "futures-util",
1484 1484 "getrandom 0.3.4",
1485 - "no-std-compat",
1485 + "hashbrown 0.16.1",
1486 1486 "nonzero_ext",
1487 1487 "parking_lot",
1488 1488 "portable-atomic",
@@ -1748,6 +1748,19 @@ dependencies = [
1748 1748 ]
1749 1749
1750 1750 [[package]]
1751 + name = "hyper-timeout"
1752 + version = "0.5.2"
1753 + source = "registry+https://github.com/rust-lang/crates.io-index"
1754 + checksum = "2b90d566bffbce6a75bd8b09a05aa8c2cb1fabb6cb348f8840c9e4c90a0d83b0"
1755 + dependencies = [
1756 + "hyper",
1757 + "hyper-util",
1758 + "pin-project-lite",
1759 + "tokio",
1760 + "tower-service",
1761 + ]
1762 +
1763 + [[package]]
1751 1764 name = "hyper-util"
1752 1765 version = "0.1.20"
1753 1766 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2262,7 +2275,7 @@ dependencies = [
2262 2275 "tokio",
2263 2276 "tokio-util",
2264 2277 "tower",
2265 - "tower-http",
2278 + "tower-http 0.7.0",
2266 2279 "tower-sessions",
2267 2280 "tower-sessions-sqlx-store",
2268 2281 "tower_governor",
@@ -2281,12 +2294,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
2281 2294 checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086"
2282 2295
2283 2296 [[package]]
2284 - name = "no-std-compat"
2285 - version = "0.4.1"
2286 - source = "registry+https://github.com/rust-lang/crates.io-index"
2287 - checksum = "b93853da6d84c2e3c7d730d6473e8817692dd89be387eb01b94d7f108ecb5b8c"
2288 -
2289 - [[package]]
2290 2297 name = "nonempty"
2291 2298 version = "0.7.0"
2292 2299 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2910,7 +2917,7 @@ dependencies = [
2910 2917 "tokio",
2911 2918 "tokio-rustls",
2912 2919 "tower",
2913 - "tower-http",
2920 + "tower-http 0.6.8",
2914 2921 "tower-service",
2915 2922 "url",
2916 2923 "wasm-bindgen",
@@ -3929,6 +3936,35 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
3929 3936 checksum = "7d56353a2a665ad0f41a421187180aab746c8c325620617ad883a99a1cbe66d2"
3930 3937
3931 3938 [[package]]
3939 + name = "tonic"
3940 + version = "0.14.6"
3941 + source = "registry+https://github.com/rust-lang/crates.io-index"
3942 + checksum = "ac2a5518c70fa84342385732db33fb3f44bc4cc748936eb5833d2df34d6445ef"
3943 + dependencies = [
3944 + "async-trait",
3945 + "axum",
3946 + "base64",
3947 + "bytes",
3948 + "h2",
3949 + "http 1.4.0",
3950 + "http-body 1.0.1",
3951 + "http-body-util",
3952 + "hyper",
3953 + "hyper-timeout",
3954 + "hyper-util",
3955 + "percent-encoding",
3956 + "pin-project",
3957 + "socket2",
3958 + "sync_wrapper",
3959 + "tokio",
3960 + "tokio-stream",
3961 + "tower",
3962 + "tower-layer",
3963 + "tower-service",
3964 + "tracing",
3965 + ]
3966 +
3967 + [[package]]
3932 3968 name = "tower"
3933 3969 version = "0.5.3"
3934 3970 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -3936,9 +3972,12 @@ checksum = "ebe5ef63511595f1344e2d5cfa636d973292adc0eec1f0ad45fae9f0851ab1d4"
3936 3972 dependencies = [
3937 3973 "futures-core",
3938 3974 "futures-util",
3975 + "indexmap",
3939 3976 "pin-project-lite",
3977 + "slab",
3940 3978 "sync_wrapper",
3941 3979 "tokio",
3980 + "tokio-util",
3942 3981 "tower-layer",
3943 3982 "tower-service",
3944 3983 "tracing",
@@ -3968,6 +4007,24 @@ checksum = "d4e6559d53cc268e5031cd8429d05415bc4cb4aefc4aa5d6cc35fbf5b924a1f8"
3968 4007 dependencies = [
3969 4008 "bitflags",
3970 4009 "bytes",
4010 + "futures-util",
4011 + "http 1.4.0",
4012 + "http-body 1.0.1",
4013 + "iri-string",
4014 + "pin-project-lite",
4015 + "tower",
4016 + "tower-layer",
4017 + "tower-service",
4018 + ]
4019 +
4020 + [[package]]
4021 + name = "tower-http"
4022 + version = "0.7.0"
4023 + source = "registry+https://github.com/rust-lang/crates.io-index"
4024 + checksum = "b11f75e912b0c2be01b63d8cf8057b8c3f97cf34abb3d431a3a4c8675498e233"
4025 + dependencies = [
4026 + "bitflags",
4027 + "bytes",
3971 4028 "futures-core",
3972 4029 "futures-util",
3973 4030 "http 1.4.0",
@@ -3975,14 +4032,12 @@ dependencies = [
3975 4032 "http-body-util",
3976 4033 "http-range-header",
3977 4034 "httpdate",
3978 - "iri-string",
3979 4035 "mime",
3980 4036 "mime_guess",
3981 4037 "percent-encoding",
3982 4038 "pin-project-lite",
3983 4039 "tokio",
3984 4040 "tokio-util",
3985 - "tower",
3986 4041 "tower-layer",
3987 4042 "tower-service",
3988 4043 "tracing",
@@ -4067,9 +4122,9 @@ dependencies = [
4067 4122
4068 4123 [[package]]
4069 4124 name = "tower_governor"
4070 - version = "0.6.0"
4125 + version = "0.8.0"
4071 4126 source = "registry+https://github.com/rust-lang/crates.io-index"
4072 - checksum = "57a2ccff6830fa835371af7541e561a90e4c07b84f72991ebac4b3cb6790dc0d"
4127 + checksum = "44de9b94d849d3c46e06a883d72d408c2de6403367b39df2b1c9d9e7b6736fe6"
4073 4128 dependencies = [
4074 4129 "axum",
4075 4130 "forwarded-header-value",
@@ -4077,6 +4132,7 @@ dependencies = [
4077 4132 "http 1.4.0",
4078 4133 "pin-project",
4079 4134 "thiserror 2.0.18",
4135 + "tonic",
4080 4136 "tower",
4081 4137 "tracing",
4082 4138 ]
@@ -24,7 +24,7 @@ tracing-subscriber = { version = "0.3", features = ["env-filter"] }
24 24 # Web
25 25 axum = { version = "0.8", features = ["ws", "multipart"] }
26 26 tower = "0.5"
27 - tower-http = { version = "0.6", features = ["fs", "cors", "trace", "set-header", "timeout"] }
27 + tower-http = { version = "0.7", features = ["fs", "cors", "trace", "set-header", "timeout"] }
28 28 tower-sessions = "0.14"
29 29 tower-sessions-sqlx-store = { version = "0.15", features = ["postgres"] }
30 30
@@ -45,8 +45,8 @@ s3-storage = { path = "../shared/s3-storage" }
45 45 sqlx = { version = "0.8", features = ["runtime-tokio", "postgres", "chrono", "uuid"] }
46 46
47 47 # Rate limiting
48 - tower_governor = "0.6"
49 - governor = "0.8"
48 + tower_governor = "0.8"
49 + governor = "0.10"
50 50
51 51 # Utilities
52 52 chrono = { version = "0.4", features = ["serde"] }
@@ -389,9 +389,7 @@ pub fn internal_routes(state: AppState) -> Router {
389 389 .route("/internal/threads", post(create_thread))
390 390 .route("/internal/threads/{id}/posts", post(create_post))
391 391 .route("/internal/threads/{id}/stats", get(thread_stats))
392 - .route_layer(GovernorLayer {
393 - config: internal_rate_limit,
394 - })
392 + .route_layer(GovernorLayer::new(internal_rate_limit))
395 393 .with_state(state)
396 394 }
397 395
@@ -212,9 +212,7 @@ pub fn forum_routes(state: AppState) -> Router {
212 212 "/p/{slug}/uploads/{id}/remove",
213 213 post(uploads::remove_image_handler),
214 214 )
215 - .route_layer(GovernorLayer {
216 - config: write_rate_limit.clone(),
217 - });
215 + .route_layer(GovernorLayer::new(write_rate_limit.clone()));
218 216
219 217 // Search — rate limited per IP (expensive full-text queries)
220 218 let search_rate_limit = std::sync::Arc::new(
@@ -230,9 +228,7 @@ pub fn forum_routes(state: AppState) -> Router {
230 228
231 229 let search_routes = Router::new()
232 230 .route("/search", get(search::search_handler))
233 - .route_layer(GovernorLayer {
234 - config: search_rate_limit.clone(),
235 - });
231 + .route_layer(GovernorLayer::new(search_rate_limit.clone()));
236 232
237 233 // Auth endpoints — rate limited per IP (login/callback flood + refresh
238 234 // amplifier against MNW).
@@ -253,9 +249,7 @@ pub fn forum_routes(state: AppState) -> Router {
253 249 .route("/auth/callback", get(auth::callback))
254 250 .route("/auth/logout", post(auth::logout))
255 251 .route("/auth/refresh", post(auth::refresh))
256 - .route_layer(GovernorLayer {
257 - config: auth_rate_limit.clone(),
258 - });
252 + .route_layer(GovernorLayer::new(auth_rate_limit.clone()));
259 253
260 254 // Image serve — per-IP rate limited. `/uploads/{id}` is an unauthenticated
261 255 // S3-egress proxy (it streams bytes to any viewer who passes the community
@@ -275,9 +269,7 @@ pub fn forum_routes(state: AppState) -> Router {
275 269 let image_routes = Router::new()
276 270 .route("/uploads/{id}", get(uploads::serve_image_handler))
277 271 .route("/img-proxy", get(uploads::image_proxy_handler))
278 - .route_layer(GovernorLayer {
279 - config: image_rate_limit.clone(),
280 - });
272 + .route_layer(GovernorLayer::new(image_rate_limit.clone()));
281 273
282 274 // Periodically evict idle per-IP buckets from every rate limiter so the
283 275 // keyspace can't grow unbounded over the process lifetime (M-Pf3).