I'm trying to write a lambda function for AWS in Rust using cargo-lambda. The example function generated by cargo lambda new
builds fine when I call cargo lambda build --release --arm64
. However, when I try to build code I write by following the instructions and examples on https://github.com/awslabs/aws-lambda-rust-runtime & https://www.cargo-lambda.info/guide/getting-started.html, the build fails to find the headers for OpenSSL. I already installed OpenSSL with pacman -S openssl
and ran pacman -S linux-headers
for good measure, and tried running export OPENSSL_LIB_DIR=/usr/lib/
and export OPENSSL_INCLUDE_DIR=/usr/include/openssl/
as well as setting them in my Fish config file, but neither has worked. I can't get past:
cargo:warning=build/expando.c:1:10: fatal error: 'openssl/opensslv.h' file not found
cargo:warning=#include <openssl/opensslv.h>
I have visually verified the file exists in the directory but for some reason openssl-sys-0.9.87
fails to find it and panics. Has anyone else encountered this, or does anyone have any ideas I can try? I'm not sure if the problem is with my cargo-lambda setup, my OpenSSL setup, my code, or something else entirely.
This code was generated with cargo lambda new project_name
and builds fine:
use lambda_runtime::{run, service_fn, Error, LambdaEvent};
use serde::{Deserialize, Serialize};
/// Main function generated by cargo-lambda
#[tokio::main]
async fn main() -> Result<(), Error> {
tracing_subscriber::fmt()
.with_max_level(tracing::Level::INFO)
// disable printing the name of the module in every log line.
.with_target(false)
// disabling time is handy because CloudWatch will add the ingestion time.
.without_time()
.init();
lambda_runtime::run(service_fn(function_handler)).await
}
/// This is a made-up example.
#[derive(Deserialize)]
struct Request {
command: String,
}
/// This is a made-up example of what a response structure may look like.
#[derive(Serialize)]
struct Response {
req_id: String,
msg: String,
}
/// This is the main body for the function.
/// Write your code inside it.
async fn function_handler(event: LambdaEvent<Request>) -> Result<Response, Error> {
// Extract some useful info from the request
let command = event.payload.command;
// Prepare the response
let resp = Response {
req_id: event.context.request_id,
msg: format!("Command {}.", command),
};
// Return `Response` (it will be serialized to JSON automatically by the runtime)
Ok(resp)
}
This is the code I'm trying to build but getting an error from openssl-sys-0.9.87
even though it was written in the same project and follows the examples from the online documentation:
use lambda_runtime::{run, service_fn, Error, LambdaEvent};
use reqwest::blocking::Client;
use serde::{Deserialize, Serialize};
use serde_json::{Value, json};
#[tokio::main]
async fn main() -> Result<(), lambda_runtime::Error> {
tracing_subscriber::fmt()
.with_max_level(tracing::Level::INFO)
// disable printing the name of the module in every log line.
.with_target(false)
// disabling time is handy because CloudWatch will add the ingestion time.
.without_time()
.init();
let query = service_fn(query_handler);
run(query).await
}
async fn query_handler(event: LambdaEvent<Value>) -> Result<Value, Error> {
let (event, _context) = event.into_parts();
let symbol = event["symbol"].to_string();
let message = query_price(symbol)?;
Ok(json!({ "message": format!("{}", message) }))
}
#[derive(Deserialize, Debug)]
#[allow(non_snake_case)]
struct PriceQuote {
pub s: String,
pub symbol: Vec<String>,
pub ask: Vec<f32>,
pub askSize: Vec<u32>,
pub bid: Vec<f32>,
pub bidSize: Vec<u32>,
pub mid: Vec<f32>,
pub last: Vec<f32>,
pub volume: Vec<u32>,
pub updated: Vec<u32>,
}
fn query_price(symbol: String) -> Result<String, reqwest::Error> {
//let symbol = "AAPL";
let url = format!("https://api.marketdata.app/v1/stocks/quotes/{}", symbol);
let client = Client::new();
let response = client.get(url).send()?;
let price_quote: PriceQuote = response.json()?;
let symbol: &String = &price_quote.symbol[0];
let last_price: &f32 = &price_quote.last[0];
Ok(format!("Last price for {} is {}", symbol, last_price).to_string())
}
Why would one build but not the other? Are the dependencies I added messing with it? Do I have the wrong OpenSSL version? Did I make a mistake? What am I missing? Sorry if these are dumb questions, I'm new to AWS and my head is spinning.