-
Notifications
You must be signed in to change notification settings - Fork 379
Closed
Description
Hi,
I'm running into an issue where URLs with spaces are causing my Lambda function to return server errors on API Gateway.
I'm no expert in URL encoding but I do realise that spaces are unsafe characters and should be avoided at all costs. Unfortunately the product I am building is acting as a sort of redirecting proxy and I am not in full control of the URL structure.
Here is the information needed to reproduce this error:
~ rustc --version
rustc 1.61.0 (fe5b13d68 2022-05-18)Place the following files in the same directory:
# Cargo.toml
[package]
name = "http-basic-bug"
version = "0.1.0"
edition = "2021"
[[bin]]
name = "example"
path = "main.rs"
[dependencies]
lambda_http = "0.6.0"
lambda_runtime = "0.6.0"
tokio = { version = "1", features = ["macros"] }
tracing = { version = "0.1", features = ["log"] }
tracing-subscriber = { version = "0.3", default-features = false, features = ["fmt"] }// main.rs
use lambda_http::{run, service_fn, Body, Error, Request, Response};
async fn function_handler(_event: Request) -> Result<Response<Body>, Error> {
// Extract some useful information from the request
// Return something that implements IntoResponse.
// It will be serialized to the right response event automatically by the runtime
let resp = Response::builder()
.status(200)
.header("content-type", "text/html")
.body("Hello AWS Lambda HTTP request".into())
.map_err(Box::new)?;
Ok(resp)
}
#[tokio::main]
async fn main() -> Result<(), Error> {
tracing_subscriber::fmt()
.with_max_level(tracing::Level::INFO)
// disabling time is handy because CloudWatch will add the ingestion time.
.without_time()
.init();
run(service_fn(function_handler)).await
}
#[cfg(test)]
mod tests {
use super::*;
#[tokio::test]
async fn test_no_space() {
let input = include_str!("good-request.json");
let request = lambda_http::request::from_str(input).expect("failed to create request");
let response = function_handler(request)
.await
.expect("failed to handle request");
assert_eq!(response.status().as_u16(), 200);
}
#[tokio::test]
async fn test_with_space() {
let input = include_str!("bad-request.json");
let request = lambda_http::request::from_str(input).expect("failed to create request");
let response = function_handler(request)
.await
.expect("failed to handle request");
assert_eq!(response.status().as_u16(), 200);
}
}good-request.json
{
"version": "2.0",
"routeKey": "$default",
"rawPath": "/my/path",
"rawQueryString": "parameter1=value1¶meter1=value2¶meter2=value",
"cookies": [ "cookie1=value1", "cookie2=value2" ],
"headers": {
"Header1": "value1",
"Header2": "value2"
},
"queryStringParameters": { "parameter1": "value1,value2", "parameter2": "value" },
"requestContext": {
"accountId": "123456789012",
"apiId": "api-id",
"authorizer": { "jwt": {
"claims": {"claim1": "value1", "claim2": "value2"},
"scopes": ["scope1", "scope2"]
}
},
"domainName": "id.execute-api.us-east-1.amazonaws.com",
"domainPrefix": "id",
"http": {
"method": "POST",
"path": "/my/path",
"protocol": "HTTP/1.1",
"sourceIp": "IP",
"userAgent": "agent"
},
"requestId": "id",
"routeKey": "$default",
"stage": "$default",
"time": "12/Mar/2020:19:03:58 +0000",
"timeEpoch": 1583348638390
},
"body": "Hello from Lambda",
"pathParameters": {"parameter1": "value1"},
"isBase64Encoded": false,
"stageVariables": {"stageVariable1": "value1", "stageVariable2": "value2"}
}bad-request.json
{
"version": "2.0",
"routeKey": "$default",
"rawPath": "/my/path-with space",
"rawQueryString": "parameter1=value1¶meter1=value2¶meter2=value",
"cookies": [ "cookie1=value1", "cookie2=value2" ],
"headers": {
"Header1": "value1",
"Header2": "value2"
},
"queryStringParameters": { "parameter1": "value1,value2", "parameter2": "value" },
"requestContext": {
"accountId": "123456789012",
"apiId": "api-id",
"authorizer": { "jwt": {
"claims": {"claim1": "value1", "claim2": "value2"},
"scopes": ["scope1", "scope2"]
}
},
"domainName": "id.execute-api.us-east-1.amazonaws.com",
"domainPrefix": "id",
"http": {
"method": "POST",
"path": "/my/path-with space",
"protocol": "HTTP/1.1",
"sourceIp": "IP",
"userAgent": "agent"
},
"requestId": "id",
"routeKey": "$default",
"stage": "$default",
"time": "12/Mar/2020:19:03:58 +0000",
"timeEpoch": 1583348638390
},
"body": "Hello from Lambda",
"pathParameters": {"parameter1": "value1"},
"isBase64Encoded": false,
"stageVariables": {"stageVariable1": "value1", "stageVariable2": "value2"}
}Run the tests
~ cargo test
Compiling http-basic-bug v0.1.0 (/private/tmp/lambda_http_bug)
Finished test [unoptimized + debuginfo] target(s) in 0.74s
Running unittests main.rs (target/debug/deps/example-4220d3d5bc4bf2cb)
running 2 tests
test tests::test_no_space ... ok
test tests::test_with_space ... FAILED
failures:
---- tests::test_with_space stdout ----
thread 'tests::test_with_space' panicked at 'failed to build request: http::Error(InvalidUri(InvalidUriChar))', /Users/<REDACTED>/.cargo/registry/src/github.com-1ecc6299db9ec823/lambda_http-0.6.0/src/request.rs:145:10
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
failures:
tests::test_with_space
test result: FAILED. 1 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
error: test failed, to rerun pass '--bin example'If this is a case of using unsafe characters or you don't feel like this is an issue of lambda_http then please close this issue.
Metadata
Metadata
Assignees
Labels
No labels