hyperapi 0.2.2

An easy to use API Gateway
Documentation
use hyper::http::HeaderValue;
use std::{pin::Pin, time::SystemTime};
use std::future::Future;
use crate::middleware::{MwPostRequest, MwPreRequest, MwPostResponse, Middleware};
use crate::config::ConfigUpdate;


lazy_static::lazy_static! {
    static ref HTTP_COUNTER: prometheus::IntCounterVec = prometheus::register_int_counter_vec!(
        "gateway_requests_total",
        "Number of HTTP requests.",
        &["service", "app", "upstream", "version", "status_code", "path"]
    ).unwrap();

    static ref HTTP_REQ_DURATION_HIST: prometheus::HistogramVec = prometheus::register_histogram_vec!(
        "gateway_request_duration_seconds",
        "Request latency histgram",
        &["service", "app", "upstream", "version"],
        vec![0.01, 0.02, 0.05, 0.1, 0.25, 0.5, 1.0, 3.0]
    ).unwrap();
}


#[derive(Debug)]
pub struct LoggerMiddleware {}

impl Default for LoggerMiddleware {
    fn default() -> Self {
        LoggerMiddleware {}
    }
}


impl Middleware for LoggerMiddleware {
    fn name() -> String {
        "Logger".into()
    }

    fn pre() -> bool {
        false
    }

    fn require_setting() -> bool {
        false
    }

    fn request(&mut self, _task: MwPreRequest) -> Pin<Box<dyn Future<Output=()> + Send>> {
        panic!("never got here");
    }

    fn response(&mut self, task: MwPostRequest) -> Pin<Box<dyn Future<Output=()> + Send>> {
        let MwPostRequest {context, response, service_filters: _, client_filters: _, result} = task;
        let status = response.status().as_u16().to_string();
        let empty_value = HeaderValue::from_static("");
        let upstream = response.headers().get("X-UPSTREAM-ID").unwrap_or(&empty_value).to_str().unwrap();
        let version = response.headers().get("X-UPSTREAM-VERSION").unwrap_or(&empty_value).to_str().unwrap();
        
        let elapsed = SystemTime::now().duration_since(context.start_time).unwrap();
        HTTP_REQ_DURATION_HIST.with_label_values(&[
            &context.service_id,
            &context.client_id,
            upstream,
            version,
        ]).observe(elapsed.as_secs_f64());

        let path = context.api_path.clone();
        HTTP_COUNTER.with_label_values(&[
            &context.service_id, 
            &context.client_id, 
            upstream, 
            version,
            &status, 
            &path,
        ]).inc_by(1);

        let response = MwPostResponse {context: context, response: response };
        let _ = result.send(Ok(response));
        Box::pin(async {})
    }

    fn config_update(&mut self, _update: ConfigUpdate) {}

}