I can't figure out how to make a simple HTTP request from AWS Lambda using rust without getting a segmentation fault. I get this error regardless of whether I use tokio-0.2 or tokio-0.3 with a compatibility layer. It looks like lambda_http
was compiled with tokio-0.2 so it should work.
Cargo.toml
:
[package]
name = "req"
version = "0.1.0"
authors = ["X"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
lambda_http = { version = "0.2.0-beta.1", git = "https://github.com/awslabs/aws-lambda-rust-runtime" }
tokio = { version = "0.3.4", features = ["full"] }
tokio-compat-02 = "0.1.2"
reqwest = { version = "0.10.9", features = ["json"] }
main.rs
use lambda_http::{
handler,
lambda::{self, Context},
IntoResponse, Request,
};
// NOTE:
// when using tokio-0.2 alone, you get a segmentation fault
// when tokio-0.2 compatibility is enabled with tokio-0.3, you get a segmentation fault
// when tokio-0.2 compatibility is not enabled with tokio-0.3, 'main' panics because 'there is
// no reactor running, must be called from the context of Tokio runtime'
// use tokio_compat_02::FutureExt;
pub type Error = Box<dyn std::error::Error + Send + Sync + 'static>;
#[tokio::main]
async fn main() -> Result<(), Error> {
lambda::run(handler(func)).await?;
// NOTE: [tokio-0.2 compat] - this doesn't help
// lambda::run(handler(func)).compat().await?;
Ok(())
}
async fn func(_: Request, _: Context) -> Result<impl IntoResponse, Error> {
let _res = reqwest::get("https://www.google.com").await?;
// NOTE: [tokio-0.2 compat] - this doesn't help
// let _res = reqwest::get("https://www.google.com").compat().await?;
Ok("success")
}
deploy.sh
:
PKG_CONFIG_ALLOW_CROSS=1 cargo build --release --target x86_64-unknown-linux-musl
cp target/x86_64-unknown-linux-musl/release/req target/x86_64-unknown-linux-musl/release/bootstrap
zip -j target/x86_64-unknown-linux-musl/release/bootstrap.zip target/x86_64-unknown-linux-musl/release/bootstrap
# aws lambda create-function \
# --function-name reqwest-test \
# --handler doesnt.matter \
# --zip-file fileb://target/x86_64-unknown-linux-musl/release/bootstrap.zip \
# --runtime provided \
# --role [REMOVED] \
# --environment Variables={RUST_BACKTRACE=1} \
# --tracing-config Mode=Active
aws lambda update-function-code \
--function-name reqwest-test \
--zip-file fileb://target/x86_64-unknown-linux-musl/release/bootstrap.zip
event.json
{
"headers": {
"accept": "*/*",
"content-length": "0",
"host": "xxx.execute-api.us-east-1.amazonaws.com",
"user-agent": "curl/7.64.1",
"x-amzn-trace-id": "Root=1-5eb33c07-de25b420912dee103a5db434",
"x-forwarded-for": "65.78.31.245",
"x-forwarded-port": "443",
"x-forwarded-proto": "https"
},
"isBase64Encoded": false,
"rawPath": "/",
"rawQueryString": "",
"requestContext": {
"accountId": "123456789012",
"apiId": "xxx",
"domainName": "xxx.execute-api.us-east-1.amazonaws.com",
"domainPrefix": "xxx",
"http": {
"method": "GET",
"path": "/",
"protocol": "HTTP/1.1",
"sourceIp": "65.78.31.245",
"userAgent": "curl/7.64.1"
},
"requestId": "MIZRNhJtIAMEMDw=",
"routeKey": "$default",
"stage": "$default",
"time": "06/May/2020:22:36:55 +0000",
"timeEpoch": 1588804615616
},
"routeKey": "$default",
"version": "2.0"
}
This is solved by not cross-compiling with openssl, which is dynamically linked in glibc. You can change this to
reqwest = { version = "0.45.0", default-features = false, features = ["rustls-tls"] }
. And if you are usingrusoto
crates, the same thing exceptfeatures = ["rustls"]
.