a9e62889c3
* 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
77 lines
2.2 KiB
Rust
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)
|
|
}
|
|
}
|