datatrash/src/rate_limit.rs

53 lines
1.7 KiB
Rust
Raw Normal View History

2022-08-21 16:44:12 +00:00
use actix_governor::KeyExtractor;
use actix_governor::PeerIpKeyExtractor;
2023-01-27 19:56:44 +00:00
use actix_governor::SimpleKeyExtractionError;
use actix_web::HttpResponse;
use actix_web::HttpResponseBuilder;
2022-08-21 16:44:12 +00:00
use actix_web::{dev::ServiceRequest, http::header::ContentType};
use governor::clock::{Clock, DefaultClock, QuantaInstant};
use governor::NotUntil;
use std::net::IpAddr;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct ForwardedPeerIpKeyExtractor {
pub proxied: bool,
}
impl KeyExtractor for ForwardedPeerIpKeyExtractor {
type Key = IpAddr;
2023-01-27 19:56:44 +00:00
type KeyExtractionError = SimpleKeyExtractionError<&'static str>;
2022-08-21 16:44:12 +00:00
fn extract(&self, req: &ServiceRequest) -> Result<Self::Key, Self::KeyExtractionError> {
let forwarded_for = req.headers().get("x-forwarded-for");
if self.proxied && forwarded_for.is_some() {
2023-01-27 19:56:44 +00:00
read_forwareded_for(forwarded_for).map_err(SimpleKeyExtractionError::new)
2022-08-21 16:44:12 +00:00
} else {
PeerIpKeyExtractor.extract(req)
}
}
2023-01-27 19:56:44 +00:00
fn exceed_rate_limit_response(
&self,
negative: &NotUntil<QuantaInstant>,
mut response: HttpResponseBuilder,
) -> HttpResponse {
2022-08-21 16:44:12 +00:00
let wait_time = negative
.wait_time_from(DefaultClock::default().now())
.as_secs();
2023-01-27 19:56:44 +00:00
response
.content_type(ContentType::plaintext())
.body(format!("too many requests, retry in {wait_time}s"))
2022-08-21 16:44:12 +00:00
}
2023-01-27 19:56:44 +00:00
}
2022-08-21 16:44:12 +00:00
2023-01-27 19:56:44 +00:00
fn read_forwareded_for(
forwarded_for: Option<&actix_web::http::header::HeaderValue>,
) -> Result<IpAddr, &'static str> {
forwarded_for
.unwrap()
.to_str()
.map_err(|_| "x-forwarded-for contains invalid header value")?
.parse::<IpAddr>()
.map_err(|_| "x-forwarded-for contains invalid ip adress")
2022-08-21 16:44:12 +00:00
}