Use Axum and LambdaRequest (and context) at the same time #634
-
Hi! I am new to Rust. I've been writing Lambda in Python for a long time now, but I'm interested in writing this in Rust. I used to output the whole log first every time Lambda was started. like this:.
I first wrote the following code to achieve something similar to this and it worked. main.rs async fn lambda_handler(request: Request) -> Result<Response<Body>, Error> {
let context = request.lambda_context();
lambda::log_incoming_event(&request, context);
// do something...
}
#[tokio::main]
async fn main() -> Result<(), Error> {
run(lambda::init_app(lambda_handler)).await
} utils/lambda.rs pub fn init_app<H, F>(lambda_handler: H) -> Cors<ServiceFn<H>>
where
H: Fn(Request) -> F,
F: Future<Output = Result<Response<Body>, LambdaError>>,
{
let level = env::var("LOG_LEVEL").unwrap_or_else(|_| "debug".to_string());
let level = Level::from_str(&level).unwrap();
tracing_subscriber::fmt()
.with_max_level(level)
.with_file(true)
.with_line_number(true)
.json()
.init();
let cors_layer = CorsLayer::new()
.allow_origin(
env::var("API_ALLOW_ORIGIN")
.expect("\"API_ALLOW_ORIGIN\" env var is not set.")
.parse::<HeaderValue>()
.unwrap(),
)
.allow_headers(vec![
header::AUTHORIZATION,
"Cognito-Auth-Header".parse::<HeaderName>().unwrap(),
header::CONTENT_TYPE,
"X-Amz-Date".parse::<HeaderName>().unwrap(),
"X-Amz-Security-Token".parse::<HeaderName>().unwrap(),
"X-Api-Key".parse::<HeaderName>().unwrap(),
])
.allow_methods(vec![
Method::POST,
Method::GET,
Method::PUT,
Method::PATCH,
Method::DELETE,
Method::OPTIONS,
]);
lambda_http::tower::ServiceBuilder::new()
.layer(cors_layer)
.service(service_fn(lambda_handler))
}
pub fn log_incoming_event(request: &Request, context: Context) {
if let RequestContext::ApiGatewayV1(request_context) = request.request_context() {
info!(
request_id = %context.request_id,
request_time = %request_context.request_time.unwrap_or_else(|| "No request time".to_string()),
http_version = ?request.version(),
method = ?request.method(),
resource_path = %request_context.resource_path.unwrap_or_else(|| "No resource path".to_string()),
fullpath = %request.uri(),
// Omitted...
authorizer = ?request_context.authorizer, // Structuring?
log_stream = %context.env_config.log_stream,
log_group = %context.env_config.log_group,
xray_trace_id = %context.xray_trace_id.unwrap_or_else(|| "None".to_string()),
client_context = ?context.client_context,
invoked_function_arn = %context.invoked_function_arn,
function_name = %context.env_config.function_name,
version = %context.env_config.version,
memory = ?context.env_config.memory,
deadline = ?context.deadline,
"Lambda incoming event:",
);
}
}
} However, after this, I wanted to use Axum for API routing, but I couldn't figure out how to use Axum's route object together with the How can I create an API routing for Axum while running a function to log all Lambda requests? |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment
-
the http variant of the runtime hides the lambda event from the developer, that's kind of what it's intended to do. instead of receiving a lambda request, you receive an does that help? does one of those options sound like it'll work for you? |
Beta Was this translation helpful? Give feedback.
the http variant of the runtime hides the lambda event from the developer, that's kind of what it's intended to do. instead of receiving a lambda request, you receive an
http::Request
, which is normally what code written with a more traditional web server framework expects. so you've got two choices here - either you log what you need out of the passed-inhttp::Request
, or you dip down into the lower level (non-http) runtime and do the translation to anhttp::Request
yourself after logging, if that's the type you ultimately need.does that help? does one of those options sound like it'll work for you?