Release v1.0.0: RFC 9458 compliant OHTTP gateway with key configuration fixes

- Update dependencies to ohttp 0.7.1 and bhttp 0.7.1
- Fix key configuration format to include required 2-byte length prefix per RFC 9458
- Update license to match actual MPL-2.0 license file
- Fix clippy warnings for better code quality
- Add comprehensive CHANGELOG.md for v1.0.0 release

This release provides a production-ready, RFC 9458 compliant OHTTP gateway
with proper key management, security controls, and observability features.
This commit is contained in:
Bastian Gruber 2025-11-23 16:33:09 -04:00
parent c4bbebbc3e
commit 66d3471a0d
Signed by: gruberb
GPG key ID: 426AF1CBA0530691
5 changed files with 170 additions and 274 deletions

67
CHANGELOG.md Normal file
View file

@ -0,0 +1,67 @@
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [1.0.0] - 2024-11-23
### Added
- RFC 9458 compliant OHTTP gateway implementation
- Automatic key rotation with configurable intervals
- Key management with deterministic and random key generation
- Comprehensive security middleware with rate limiting
- Prometheus metrics integration for observability
- Health check endpoints for monitoring
- Docker support for containerized deployment
- Configurable target origin allowlists
- Request validation and security controls
- Binary HTTP (BHTTP) message handling
- HPKE encryption/decryption for OHTTP protocol
- Graceful shutdown handling
- Structured logging with JSON support
- Configuration through environment variables
- Support for multiple cipher suites (X25519, HKDF-SHA256, AES-128-GCM, ChaCha20-Poly1305)
### Fixed
- **BREAKING**: Key configuration format now includes required 2-byte length prefix per RFC 9458 Section 3.2
- Proper handling of key expiration and cleanup
- Correct OHTTP key configuration encoding with length prefixes
- Memory safety and thread safety improvements
### Technical Details
- Built with Rust 2024 edition
- Uses `ohttp` crate v0.7.1 for RFC 9458 compliance
- Uses `bhttp` crate v0.7.1 for binary HTTP message handling
- Comprehensive test suite with 28+ tests covering all major functionality
- Production-ready error handling and logging
### Dependencies
- axum 0.7 for HTTP server framework
- tokio 1.48 for async runtime
- hyper 1.8 for HTTP implementation
- reqwest 0.12 for backend HTTP client
- ohttp 0.7.1 for OHTTP protocol implementation
- bhttp 0.7.1 for binary HTTP messages
- prometheus for metrics collection
- tracing for structured logging
- chrono for time handling
### Security
- HPKE-based encryption using industry-standard algorithms
- Request size limits and validation
- Origin-based access control
- Rate limiting with configurable thresholds
- Secure key rotation and management
- Protection against replay attacks
- Comprehensive input validation
### Performance
- Connection reuse between relay and gateway
- Efficient binary HTTP message processing
- Optimized cryptographic operations
- Configurable timeouts and limits
- Memory-efficient key storage
This is the first stable release suitable for production use in OHTTP deployments.

347
Cargo.lock generated
View file

@ -17,16 +17,6 @@ version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa"
[[package]]
name = "aead"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b613b8e1e3cf911a086f53f03bf286f52fd7a7258e4fa606f0ef220d39d8877"
dependencies = [
"generic-array",
"rand_core",
]
[[package]]
name = "aead"
version = "0.5.2"
@ -37,18 +27,6 @@ dependencies = [
"generic-array",
]
[[package]]
name = "aes"
version = "0.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9e8b47f52ea9bae42228d07ec09eb676433d7c4ed1ebdf0f1d1c29ed446f1ab8"
dependencies = [
"cfg-if",
"cipher 0.3.0",
"cpufeatures 0.2.17",
"opaque-debug",
]
[[package]]
name = "aes"
version = "0.8.4"
@ -56,22 +34,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0"
dependencies = [
"cfg-if",
"cipher 0.4.4",
"cpufeatures 0.2.17",
]
[[package]]
name = "aes-gcm"
version = "0.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bc3be92e19a7ef47457b8e6f90707e12b6ac5d20c6f3866584fa3be0787d839f"
dependencies = [
"aead 0.4.3",
"aes 0.7.5",
"cipher 0.3.0",
"ctr 0.7.0",
"ghash 0.4.4",
"subtle",
"cipher",
"cpufeatures",
]
[[package]]
@ -80,11 +44,11 @@ version = "0.10.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "831010a0f742e1209b3bcea8fab6a8e149051ba6099432c8cb2cc117dec3ead1"
dependencies = [
"aead 0.5.2",
"aes 0.8.4",
"cipher 0.4.4",
"ctr 0.9.2",
"ghash 0.5.1",
"aead",
"aes",
"cipher",
"ctr",
"ghash",
"subtle",
]
@ -360,11 +324,11 @@ checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
[[package]]
name = "bhttp"
version = "0.6.1"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "16fc24bc615b9fd63148f59b218ea58a444b55762f8845da910e23aca686398b"
checksum = "44c659d6e2707aa970a0482d3f1a0f23ff470a423b0f52961632bbf3000b7ff7"
dependencies = [
"thiserror 1.0.69",
"thiserror 2.0.12",
]
[[package]]
@ -376,15 +340,6 @@ dependencies = [
"serde",
]
[[package]]
name = "block-buffer"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4"
dependencies = [
"generic-array",
]
[[package]]
name = "block-buffer"
version = "0.10.4"
@ -448,18 +403,6 @@ version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268"
[[package]]
name = "chacha20"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fee7ad89dc1128635074c268ee661f90c3f7e83d9fd12910608c36b47d6c3412"
dependencies = [
"cfg-if",
"cipher 0.3.0",
"cpufeatures 0.1.5",
"zeroize",
]
[[package]]
name = "chacha20"
version = "0.9.1"
@ -467,21 +410,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3613f74bd2eac03dad61bd53dbe620703d4371614fe0bc3b9f04dd36fe4e818"
dependencies = [
"cfg-if",
"cipher 0.4.4",
"cpufeatures 0.2.17",
]
[[package]]
name = "chacha20poly1305"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1580317203210c517b6d44794abfbe600698276db18127e37ad3e69bf5e848e5"
dependencies = [
"aead 0.4.3",
"chacha20 0.7.1",
"cipher 0.3.0",
"poly1305 0.7.2",
"zeroize",
"cipher",
"cpufeatures",
]
[[package]]
@ -490,10 +420,10 @@ version = "0.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "10cd79432192d1c0f4e1a0fef9527696cc039165d729fb41b3f4f4f354c2dc35"
dependencies = [
"aead 0.5.2",
"chacha20 0.9.1",
"cipher 0.4.4",
"poly1305 0.8.0",
"aead",
"chacha20",
"cipher",
"poly1305",
"zeroize",
]
@ -511,15 +441,6 @@ dependencies = [
"windows-link",
]
[[package]]
name = "cipher"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ee52072ec15386f770805afd189a01c8841be8696bed250fa2f13c4c0d6dfb7"
dependencies = [
"generic-array",
]
[[package]]
name = "cipher"
version = "0.4.4"
@ -592,7 +513,7 @@ dependencies = [
"rust-ini",
"serde",
"serde_json",
"toml 0.8.23",
"toml",
"yaml-rust2",
]
@ -641,15 +562,6 @@ version = "0.8.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
[[package]]
name = "cpufeatures"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "66c99696f6c9dd7f35d486b9d04d7e6e202aa3e8c40d553f2fdf5e7e0c6a71ef"
dependencies = [
"libc",
]
[[package]]
name = "cpufeatures"
version = "0.2.17"
@ -687,36 +599,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
dependencies = [
"generic-array",
"rand_core",
"rand_core 0.6.4",
"typenum",
]
[[package]]
name = "crypto-mac"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "25fab6889090c8133f3deb8f73ba3c65a7f456f66436fc012a1b1e272b1e103e"
dependencies = [
"generic-array",
"subtle",
]
[[package]]
name = "ctr"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a232f92a03f37dd7d7dd2adc67166c77e9cd88de5b019b9a9eecfaeaf7bfd481"
dependencies = [
"cipher 0.3.0",
]
[[package]]
name = "ctr"
version = "0.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0369ee1ad671834580515889b80f2ea915f23b8be8d0daa4bbaf2ac5c7590835"
dependencies = [
"cipher 0.4.4",
"cipher",
]
[[package]]
@ -726,7 +619,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "373b7c5dbd637569a2cca66e8d66b8c446a1e7bf064ea321d265d7b3dfe7c97e"
dependencies = [
"cfg-if",
"cpufeatures 0.2.17",
"cpufeatures",
"curve25519-dalek-derive",
"fiat-crypto",
"rustc_version",
@ -788,22 +681,13 @@ dependencies = [
"powerfmt",
]
[[package]]
name = "digest"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066"
dependencies = [
"generic-array",
]
[[package]]
name = "digest"
version = "0.10.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
dependencies = [
"block-buffer 0.10.4",
"block-buffer",
"crypto-common",
"subtle",
]
@ -1019,16 +903,6 @@ dependencies = [
"wasi 0.14.2+wasi-0.2.4",
]
[[package]]
name = "ghash"
version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1583cc1656d7839fd3732b80cf4f38850336cdb9b8ded1cd399ca62958de3c99"
dependencies = [
"opaque-debug",
"polyval 0.5.3",
]
[[package]]
name = "ghash"
version = "0.5.1"
@ -1036,7 +910,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f0d8a4362ccb29cb0b265253fb0a2728f592895ee6854fd9bc13f2ffda266ff1"
dependencies = [
"opaque-debug",
"polyval 0.6.2",
"polyval",
]
[[package]]
@ -1107,33 +981,13 @@ version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
[[package]]
name = "hkdf"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "01706d578d5c281058480e673ae4086a9f4710d8df1ad80a5b03e39ece5f886b"
dependencies = [
"digest 0.9.0",
"hmac 0.11.0",
]
[[package]]
name = "hkdf"
version = "0.12.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7"
dependencies = [
"hmac 0.12.1",
]
[[package]]
name = "hmac"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2a2a2320eb7ec0ebe8da8f744d7812d9fc4cb4d09344ac01898dbcb6a20ae69b"
dependencies = [
"crypto-mac",
"digest 0.9.0",
"hmac",
]
[[package]]
@ -1142,25 +996,24 @@ version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e"
dependencies = [
"digest 0.10.7",
"digest",
]
[[package]]
name = "hpke"
version = "0.11.0"
version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e04a5933a381bb81f00b083fce6b4528e16d735dbeecbb2bdb45e0dbbf3f7e17"
checksum = "f65d16b699dd1a1fa2d851c970b0c971b388eeeb40f744252b8de48860980c8f"
dependencies = [
"aead 0.5.2",
"aes-gcm 0.10.3",
"byteorder",
"chacha20poly1305 0.10.1",
"digest 0.10.7",
"aead",
"aes-gcm",
"chacha20poly1305",
"digest",
"generic-array",
"hkdf 0.12.4",
"hmac 0.12.1",
"rand_core",
"sha2 0.10.9",
"hkdf",
"hmac",
"rand_core 0.9.3",
"sha2",
"subtle",
"x25519-dalek",
"zeroize",
@ -1806,29 +1659,31 @@ dependencies = [
[[package]]
name = "ohttp"
version = "0.6.1"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "622b8959bde5da6c70b0a49e8aa359e0c79c5e8ffd23eb3781c0cc575903d862"
checksum = "e482d6d044fb97988130b6719a91c846006030c9424f943c817b81adf3969126"
dependencies = [
"aead 0.4.3",
"aes-gcm 0.9.2",
"aead",
"aes-gcm",
"byteorder",
"chacha20poly1305 0.8.0",
"chacha20poly1305",
"futures",
"hex",
"hkdf 0.11.0",
"hkdf",
"hpke",
"log",
"rand",
"pin-project",
"rand 0.9.2",
"serde",
"serde_derive",
"sha2 0.9.9",
"thiserror 1.0.69",
"toml 0.5.11",
"sha2",
"thiserror 2.0.12",
"toml",
]
[[package]]
name = "ohttp-gateway"
version = "0.2.5"
version = "1.0.0"
dependencies = [
"anyhow",
"axum",
@ -1845,7 +1700,7 @@ dependencies = [
"jsonwebtoken",
"ohttp",
"prometheus",
"rand",
"rand 0.8.5",
"reqwest",
"serde",
"serde_json",
@ -2024,7 +1879,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "edd1101f170f5903fde0914f899bb503d9ff5271d7ba76bbb70bea63690cc0d5"
dependencies = [
"pest",
"sha2 0.10.9",
"sha2",
]
[[package]]
@ -2065,38 +1920,15 @@ version = "0.3.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c"
[[package]]
name = "poly1305"
version = "0.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "048aeb476be11a4b6ca432ca569e375810de9294ae78f4774e78ea98a9246ede"
dependencies = [
"cpufeatures 0.2.17",
"opaque-debug",
"universal-hash 0.4.0",
]
[[package]]
name = "poly1305"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8159bd90725d2df49889a078b54f4f79e87f1f8a8444194cdca81d38f5393abf"
dependencies = [
"cpufeatures 0.2.17",
"cpufeatures",
"opaque-debug",
"universal-hash 0.5.1",
]
[[package]]
name = "polyval"
version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8419d2b623c7c0896ff2d5d96e2cb4ede590fed28fcc34934f4c33c036e620a1"
dependencies = [
"cfg-if",
"cpufeatures 0.2.17",
"opaque-debug",
"universal-hash 0.4.0",
"universal-hash",
]
[[package]]
@ -2106,9 +1938,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9d1fe60d06143b2430aa532c94cfe9e29783047f06c0d7fd359a9a51b729fa25"
dependencies = [
"cfg-if",
"cpufeatures 0.2.17",
"cpufeatures",
"opaque-debug",
"universal-hash 0.5.1",
"universal-hash",
]
[[package]]
@ -2232,8 +2064,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
dependencies = [
"libc",
"rand_chacha",
"rand_core",
"rand_chacha 0.3.1",
"rand_core 0.6.4",
]
[[package]]
name = "rand"
version = "0.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1"
dependencies = [
"rand_chacha 0.9.0",
"rand_core 0.9.3",
]
[[package]]
@ -2243,7 +2085,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
dependencies = [
"ppv-lite86",
"rand_core",
"rand_core 0.6.4",
]
[[package]]
name = "rand_chacha"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb"
dependencies = [
"ppv-lite86",
"rand_core 0.9.3",
]
[[package]]
@ -2255,6 +2107,15 @@ dependencies = [
"getrandom 0.2.16",
]
[[package]]
name = "rand_core"
version = "0.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38"
dependencies = [
"getrandom 0.3.3",
]
[[package]]
name = "raw-cpuid"
version = "11.5.0"
@ -2576,19 +2437,6 @@ dependencies = [
"serde",
]
[[package]]
name = "sha2"
version = "0.9.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800"
dependencies = [
"block-buffer 0.9.0",
"cfg-if",
"cpufeatures 0.2.17",
"digest 0.9.0",
"opaque-debug",
]
[[package]]
name = "sha2"
version = "0.10.9"
@ -2596,8 +2444,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283"
dependencies = [
"cfg-if",
"cpufeatures 0.2.17",
"digest 0.10.7",
"cpufeatures",
"digest",
]
[[package]]
@ -2935,15 +2783,6 @@ dependencies = [
"tokio",
]
[[package]]
name = "toml"
version = "0.5.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234"
dependencies = [
"serde",
]
[[package]]
name = "toml"
version = "0.8.23"
@ -3183,16 +3022,6 @@ version = "1.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493"
[[package]]
name = "universal-hash"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8326b2c654932e3e4f9196e69d08fdf7cfd718e1dc6f66b347e6024a0c961402"
dependencies = [
"generic-array",
"subtle",
]
[[package]]
name = "universal-hash"
version = "0.5.1"
@ -3687,7 +3516,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c7e468321c81fb07fa7f4c636c3972b9100f0346e5b6a9f2bd0603a52f7ed277"
dependencies = [
"curve25519-dalek",
"rand_core",
"rand_core 0.6.4",
]
[[package]]

View file

@ -1,13 +1,13 @@
[package]
authors = ["Bastian Gruber <foreach@me.com>"]
version = "0.2.5"
version = "1.0.0"
edition = "2024"
name = "ohttp-gateway"
categories = ["web-programming", "web-programming::http-server"]
description = "A OHTTP Gateway server, meant to run between a OHTTP Relay and a target web service."
documentation = "https://docs.rs/ohttp-gateway"
keywords = ["ohttp", "gateway", "server", "privacy"]
license = "MIT OR Apache-2.0"
license = "MPL-2.0"
readme = "README.md"
repository = "https://github.com/gruberb/ohttp-gateway"
@ -22,8 +22,8 @@ hyper-util = { version = "0.1", features = ["full"] }
reqwest = { version = "0.12", features = ["json", "stream"] }
# OHTTP implementation - Using the martinthomson/ohttp crate
ohttp = { version = "0.6", features = ["rust-hpke"] }
bhttp = "0.6"
ohttp = { version = "0.7.1", features = ["rust-hpke"] }
bhttp = "0.7.1"
# Middleware and utilities
tower = "0.4"

View file

@ -297,11 +297,11 @@ impl KeyManager {
loop {
interval.tick().await;
if manager.should_rotate().await {
if let Err(e) = manager.rotate_keys().await {
if manager.should_rotate().await
&& let Err(e) = manager.rotate_keys().await
{
error!("Key rotation failed: {}", e);
}
}
// Also clean up expired keys
manager.cleanup_expired_keys().await;

View file

@ -164,15 +164,15 @@ pub async fn request_validation_middleware(
}
// Validate User-Agent
if let Some(user_agent) = headers.get(header::USER_AGENT) {
if let Ok(ua_str) = user_agent.to_str() {
if let Some(user_agent) = headers.get(header::USER_AGENT)
&& let Ok(ua_str) = user_agent.to_str()
{
// Block known bad user agents
if ua_str.is_empty() || ua_str.contains("bot") || ua_str.contains("crawler") {
info!("Blocked suspicious user agent: {}", ua_str);
return Err(StatusCode::FORBIDDEN);
}
}
}
Ok(next.run(request).await)
}