1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97
mod client;
mod server;
pub use client::*;
pub use server::*;
use tokio::process::{Child, Command};
/// Use [`Proxy::spawn`] to create a new proxy server and handler process.
#[derive(Default)]
pub struct Proxy {
/// See [`Self::port`].
pub port: Option<u16>,
/// See [`Self::command`].
pub command: Option<Command>,
}
impl Proxy {
/// Create the handler command from the `argv[1..]`.
/// For example if the command of the current process is `proxy node --help`
/// then the handler command will be `node --help`.
/// You can modify the handler command and pass it to [`Self::command`].
/// # Examples
/// ```
/// use lambda_runtime_proxy::Proxy;
/// use std::process::Stdio;
///
/// #[tokio::main]
/// async fn main {
/// // retrieve the default handler command
/// let mut command = Proxy::default_command();
///
/// // enhance the handler command
/// command
/// // override environment variables for the handler process
/// .env("KEY", "VALUE")
/// // pipe the stdout and stderr of the handler process
/// .stdout(Stdio::piped())
/// .stderr(Stdio::piped());
///
/// Proxy::default()
/// .command(command)
/// .spawn().await;
/// }
/// ```
pub fn default_command() -> Command {
let mut cmd = Command::new(std::env::args().nth(1).expect("Missing handler command"));
cmd.args(std::env::args().skip(2));
cmd
}
/// Set the port of the proxy server.
/// If not set, the port will be read from the environment variable `AWS_LAMBDA_RUNTIME_PROXY_PORT`,
/// or default to `3000`.
pub fn port(mut self, port: u16) -> Self {
self.port = Some(port);
self
}
/// Set the command of the handler process.
/// If not set, the command will be created using [`Self::default_command`].
pub fn command(mut self, cmd: Command) -> Self {
self.command = Some(cmd);
self
}
/// Spawn the proxy server and the handler process.
/// The handler process will be spawned with the environment variable `AWS_LAMBDA_RUNTIME_API`
/// set to the address of the proxy server.
pub async fn spawn(self) -> RunningProxy {
let port = self
.port
.or_else(|| {
std::env::var("AWS_LAMBDA_RUNTIME_PROXY_PORT")
.ok()
.and_then(|s| s.parse().ok())
})
.unwrap_or(3000);
let mut command = self.command.unwrap_or_else(|| Self::default_command());
command.env("AWS_LAMBDA_RUNTIME_API", format!("127.0.0.1:{}", port));
let server = MockLambdaRuntimeApiServer::bind(port).await;
// server is ready, spawn the real handler process
let handler = command.spawn().expect("Failed to spawn handler process");
RunningProxy { server, handler }
}
}
/// Created by [`Proxy::spawn`].
pub struct RunningProxy {
pub server: MockLambdaRuntimeApiServer,
/// The lambda handler process.
pub handler: Child,
}