mod build_the_gateway_response;
mod check_method_permission;
mod check_security_group;
mod check_source_reliability;
mod initialize_downstream_request;
mod inject_downstream_secret;
mod match_downstream_route_from_request;
mod stream_request_to_downstream;
use build_the_gateway_response::*;
use check_method_permission::*;
use check_security_group::*;
use check_source_reliability::*;
use initialize_downstream_request::*;
use inject_downstream_secret::*;
use match_downstream_route_from_request::*;
use stream_request_to_downstream::*;
use crate::models::api_config::ApiConfig;
use actix_web::{web, HttpRequest, HttpResponse};
use awc::Client;
use myc_http_tools::{
responses::GatewayError, settings::DEFAULT_REQUEST_ID_KEY,
};
use myc_mem_db::repositories::MemDbAppModule;
use tracing::Instrument;
#[tracing::instrument(
name = "route_request",
skip_all,
fields(
//
// Request information
//
myc.router.req_id = tracing::field::Empty,
myc.router.req_method = tracing::field::Empty,
myc.router.req_protocol = tracing::field::Empty,
//
// Response information
//
myc.router.res_status = tracing::field::Empty,
myc.router.res_duration = tracing::field::Empty,
)
)]
pub(crate) async fn route_request(
upstream_request: HttpRequest,
payload: web::Payload,
client: web::Data<Client>,
api_config: web::Data<ApiConfig>,
app_module: web::Data<MemDbAppModule>,
) -> Result<HttpResponse, GatewayError> {
let span = tracing::Span::current();
span.record(
"myc.router.req_method",
&Some(upstream_request.method().to_string()),
)
.record(
"myc.router.req_protocol",
&Some(upstream_request.full_url().scheme()),
);
let request_id = if let Some(request_id) =
upstream_request.headers().get(DEFAULT_REQUEST_ID_KEY)
{
span.record("myc.router.req_id", &Some(request_id.to_str().unwrap()));
Some(request_id.to_owned())
} else {
None
};
let route = match_downstream_route_from_request(
upstream_request.clone(),
app_module.clone(),
)
.instrument(span.to_owned())
.await?;
check_source_reliability(upstream_request.clone(), &route.service)
.instrument(span.to_owned())
.await?;
check_method_permission(upstream_request.clone(), &route)
.instrument(span.to_owned())
.await?;
let downstream_request = initialize_downstream_request(
upstream_request.clone(),
&route,
client.clone(),
api_config.clone(),
)
.instrument(span.to_owned())
.await?;
let (downstream_request, security_group, user_info) = check_security_group(
upstream_request.clone(),
downstream_request,
route.clone(),
)
.instrument(span.to_owned())
.await?;
let (downstream_request, route_key) = inject_downstream_secret(
downstream_request,
route.clone(),
None,
api_config.clone(),
)
.instrument(span.to_owned())
.await?;
let downstream_response = stream_request_to_downstream(
downstream_request,
&upstream_request,
payload,
route.callbacks.to_owned(),
&app_module,
user_info,
security_group,
)
.instrument(span.to_owned())
.await?;
let mut gateway_response =
build_the_gateway_response(request_id, route_key, &downstream_response)
.instrument(span.to_owned())
.await?;
tracing::trace!("Streaming response to the client");
Ok(gateway_response.streaming(downstream_response))
}