Files
nym/explorer-api/src/guards/location.rs
T
dynco-nym a9e62889c3 Remove explorer dependency (#5190)
* Move monitor code to a struct
- to store state in a struct

* explorer deprecation wip

* Replace explorer with ipinfo calls

* PR feedback

* Fix clippy

* Bump package version

* Remove ipinfo crate due to openssl dep

* Add remaining bandwidth log
2024-11-29 16:45:55 +01:00

77 lines
2.2 KiB
Rust

// Copyright 2022 - Nym Technologies SA <contact@nymtech.net>
// SPDX-License-Identifier: Apache-2.0
use crate::geo_ip::location::{GeoIpError, Location};
use crate::state::ExplorerApiStateContext;
use rocket::http::Status;
use rocket::request::FromRequest;
use rocket::request::Outcome;
use rocket::Request;
use rocket_okapi::gen::OpenApiGenerator;
use rocket_okapi::request::{OpenApiFromRequest, RequestHeaderInput};
const IP_HEADER: &str = "X-Real-IP";
#[derive(Debug)]
pub enum LocationError {
NoIP,
LocationNotFound,
InternalError,
}
fn find_location(request: &Request<'_>) -> Result<Location, (Status, LocationError)> {
let ip = request
.headers()
.get_one(IP_HEADER)
.map(|f| f.to_string())
.ok_or_else(|| {
error!("Header not found, {}", IP_HEADER);
(Status::Forbidden, LocationError::NoIP)
})?;
let geo_ip = &request
.rocket()
.state::<ExplorerApiStateContext>()
.ok_or((Status::InternalServerError, LocationError::InternalError))? // should never fail
.inner
.geo_ip;
let location = geo_ip
.0
.clone()
.query(&ip, None)
.map_err(|e| match e {
GeoIpError::NoValidIP => (Status::Forbidden, LocationError::NoIP),
GeoIpError::InternalError => {
(Status::InternalServerError, LocationError::InternalError)
}
})?
.ok_or_else(|| {
warn!("Fail to find a matching location for {}", ip);
(Status::Forbidden, LocationError::LocationNotFound)
})?;
Ok(location)
}
#[rocket::async_trait]
impl<'r> FromRequest<'r> for Location {
type Error = LocationError;
async fn from_request(request: &'r Request<'_>) -> Outcome<Self, Self::Error> {
match find_location(request) {
Ok(loc) => Outcome::Success(loc),
Err(e) => Outcome::Error(e),
}
}
}
impl OpenApiFromRequest<'_> for Location {
fn from_request_input(
_gen: &mut OpenApiGenerator,
_name: String,
_required: bool,
) -> rocket_okapi::Result<RequestHeaderInput> {
Ok(RequestHeaderInput::None)
}
}