diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 9f146c58..82b4cea2 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -12,7 +12,7 @@ jobs: - ubuntu-latest - macOS-latest rust: - - 1.31.0 + - 1.40.0 - stable - beta - nightly @@ -26,7 +26,7 @@ jobs: - os: macOS-latest target: x86_64-unknown-linux-musl - os: ubuntu-latest - rust: 1.31.0 + rust: 1.40.0 target: x86_64-unknown-linux-musl - os: ubuntu-latest rust: beta @@ -35,7 +35,7 @@ jobs: rust: nightly target: x86_64-unknown-linux-musl - os: macOS-latest - rust: 1.31.0 + rust: 1.40.0 - os: macOS-latest rust: beta - os: macOS-latest @@ -68,4 +68,4 @@ jobs: components: rustfmt override: true - name: Run fmt check - run: cargo fmt --all -- --check + run: cargo fmt --all -- --check \ No newline at end of file diff --git a/.rustfmt.toml b/.rustfmt.toml index 4df947e3..02f25178 100644 --- a/.rustfmt.toml +++ b/.rustfmt.toml @@ -1,3 +1,4 @@ +edition = "2018" # https://github.com/rust-lang/rustfmt/blob/master/Configurations.md#merge_imports merge_imports = true # https://github.com/rust-lang/rustfmt/blob/master/Configurations.md#max_width diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index e3373475..00000000 --- a/.travis.yml +++ /dev/null @@ -1,32 +0,0 @@ -language: rust - -cache: - directories: - - /home/travis/.cargo - -before_cache: - - rm -rf /home/travis/.cargo/registry - -install: | - # this project's rustfmt style requires nightly features - if [[ "$TRAVIS_RUST_VERSION" == nightly ]]; then - rustup component add rustfmt - fi - -matrix: - include: - - rust: 1.31.0 - - rust: stable - - rust: beta - - rust: nightly - env: ALLOW_FAILURES=true - - os: osx - - env: TARGET=x86_64-unknown-linux-musl - - env: TARGET=x86_64-unknown-linux-gnu -script: - - | - if [[ "$TRAVIS_RUST_VERSION" == nightly ]]; then - cargo fmt --all -- --check - fi - - cargo build --verbose --all - - cargo test --verbose --all diff --git a/Cargo.lock b/Cargo.lock index d5e54134..5fc8b329 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,298 +1,223 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. [[package]] -name = "arrayvec" -version = "0.4.10" +name = "arc-swap" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] name = "autocfg" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "backtrace" -version = "0.3.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-demangle 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "backtrace-sys" -version = "0.1.28" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "base64" -version = "0.10.1" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] name = "bitflags" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "byteorder" -version = "1.3.1" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "bytes" -version = "0.4.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "cc" -version = "1.0.29" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "cfg-if" -version = "0.1.6" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "chrono" -version = "0.4.6" +name = "fnv" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] -name = "cloudabi" -version = "0.0.3" +name = "fuchsia-zircon" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "crossbeam" -version = "0.6.0" +name = "fuchsia-zircon-sys" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-channel 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-deque 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-epoch 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] -name = "crossbeam-channel" -version = "0.3.8" +name = "futures" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-channel 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-executor 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-io 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-sink 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-task 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-util 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "crossbeam-deque" -version = "0.6.3" +name = "futures-channel" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-epoch 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-sink 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "crossbeam-epoch" -version = "0.7.1" +name = "futures-core" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] -name = "crossbeam-utils" -version = "0.6.5" +name = "futures-executor" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-task 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-util 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "dtoa" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "failure" -version = "0.1.5" +name = "futures-io" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "backtrace 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", - "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] -name = "failure_derive" -version = "0.1.5" +name = "futures-macro" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", - "synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "fnv" -version = "1.0.6" +name = "futures-sink" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "fuchsia-cprng" -version = "0.1.1" +name = "futures-task" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "fuchsia-zircon" -version = "0.3.3" +name = "futures-util" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-channel 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-io 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-macro 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-sink 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-task 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "pin-utils 0.1.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-nested 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "fuchsia-zircon-sys" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "futures" -version = "0.1.25" +name = "h2" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", + "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-sink 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-util 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "indexmap 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-util 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] -name = "futures-cpupool" -version = "0.1.8" +name = "hermit-abi" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "h2" -version = "0.1.16" +name = "http" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "http 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", - "indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "string 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "itoa 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "http" -version = "0.1.15" +name = "http-body" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "httparse" -version = "1.3.3" +version = "1.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "hyper" -version = "0.12.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "h2 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", - "http 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", - "httparse 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-channel 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-util 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "h2 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "http-body 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "httparse 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "itoa 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "pin-project 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-threadpool 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", - "want 0.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tower-service 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "want 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "idna" -version = "0.1.5" +name = "indexmap" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-normalization 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "indexmap" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "iovec" -version = "0.1.2" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "itoa" -version = "0.4.3" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -305,167 +230,89 @@ dependencies = [ ] [[package]] -name = "lambda_http" -version = "0.1.1" -dependencies = [ - "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", - "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "http 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", - "lambda_runtime 0.2.1", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "maplit 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_urlencoded 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", - "simple_logger 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "lambda_runtime" -version = "0.2.1" -dependencies = [ - "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "lambda_runtime_core 0.1.2", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", - "simple-error 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", - "simple_logger 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "lambda_runtime_client" -version = "0.2.3" -dependencies = [ - "chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "http 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.12.24 (registry+https://github.com/rust-lang/crates.io-index)", - "lambda_runtime_errors 0.1.1", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "lambda_runtime_core" -version = "0.1.2" -dependencies = [ - "backtrace 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", - "chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.12.24 (registry+https://github.com/rust-lang/crates.io-index)", - "lambda_runtime_client 0.2.3", - "lambda_runtime_errors 0.1.1", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "simple_logger 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "lambda_runtime_errors" -version = "0.1.1" +name = "lambda" +version = "0.1.0" dependencies = [ - "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "lambda_runtime_core 0.1.2", - "lambda_runtime_errors_derive 0.1.1", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", + "lambda-attributes 0.1.0", + "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tower-service 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "lambda_runtime_errors_derive" -version = "0.1.1" +name = "lambda-attributes" +version = "0.1.0" dependencies = [ - "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "lambda_runtime_errors 0.1.1", - "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", - "synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "lazy_static" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "lazycell" -version = "1.2.1" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "libc" -version = "0.2.48" +version = "0.2.66" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "lock_api" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "log" -version = "0.4.6" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "maplit" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "matches" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "memoffset" -version = "0.2.1" +name = "memchr" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "mio" -version = "0.6.16" +version = "0.6.21" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "mio-named-pipes" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", + "miow 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "mio-uds" version = "0.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", + "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -480,284 +327,145 @@ dependencies = [ ] [[package]] -name = "net2" -version = "0.2.33" +name = "miow" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "socket2 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "nodrop" -version = "0.1.13" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "num-integer" -version = "0.1.39" +name = "net2" +version = "0.2.33" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "num-traits" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "num_cpus" -version = "1.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "owning_ref" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "parking_lot" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "parking_lot_core" -version = "0.4.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "hermit-abi 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "percent-encoding" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "proc-macro2" -version = "0.4.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "quote" -version = "0.6.11" +name = "pin-project" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "pin-project-internal 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "rand" -version = "0.6.5" +name = "pin-project-internal" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_jitter 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_os 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_pcg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "rand_chacha" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rand_core" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rand_core" -version = "0.4.0" +name = "pin-project-lite" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "rand_hc" -version = "0.1.0" +name = "pin-utils" +version = "0.1.0-alpha.4" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] -name = "rand_isaac" -version = "0.1.1" +name = "proc-macro-hack" +version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "rand_jitter" +name = "proc-macro-nested" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] -name = "rand_os" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rand_pcg" -version = "0.1.1" +name = "proc-macro2" +version = "0.4.30" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "rand_xorshift" -version = "0.1.1" +name = "proc-macro2" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "rdrand" -version = "0.4.0" +name = "quote" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "redox_syscall" -version = "0.1.51" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "rustc-demangle" -version = "0.1.13" +version = "0.1.56" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "rustc_version" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "ryu" -version = "0.2.7" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "scopeguard" -version = "0.3.3" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "semver" -version = "0.9.0" +name = "serde" +version = "1.0.104" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "semver-parser" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "serde" -version = "1.0.87" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "serde_derive" -version = "1.0.87" +version = "1.0.104" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde_json" -version = "1.0.38" +version = "1.0.45" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", + "itoa 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", + "ryu 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "serde_urlencoded" -version = "0.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "dtoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "simple-error" -version = "0.1.13" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "simple_logger" -version = "1.0.1" +name = "signal-hook-registry" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "arc-swap 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -766,42 +474,24 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "smallvec" -version = "0.6.8" +name = "socket2" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "stable_deref_trait" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "string" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "syn" -version = "0.15.26" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "synstructure" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -809,235 +499,83 @@ name = "time" version = "0.1.42" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio" -version = "0.1.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-current-thread 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-fs 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-sync 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-threadpool 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-udp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-uds 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tokio-codec" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tokio-current-thread" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tokio-executor" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tokio-fs" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-threadpool 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tokio-io" -version = "0.1.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tokio-reactor" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tokio-sync" -version = "0.1.1" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tokio-tcp" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tokio-threadpool" -version = "0.1.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "crossbeam 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-channel 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-deque 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", + "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", + "mio-named-pipes 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "pin-project-lite 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "signal-hook-registry 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-macros 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "tokio-timer" -version = "0.2.10" +name = "tokio-macros" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "tokio-udp" -version = "0.1.3" +name = "tokio-util" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-sink 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "pin-project-lite 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "tokio-uds" -version = "0.2.5" +name = "tower-service" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", - "mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] name = "try-lock" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "unicode-bidi" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "unicode-normalization" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "unicode-xid" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "unreachable" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "url" -version = "1.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "void" -version = "1.0.2" +name = "unicode-xid" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "want" -version = "0.0.6" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "try-lock 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1048,7 +586,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "winapi" -version = "0.3.6" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1080,117 +618,73 @@ dependencies = [ ] [metadata] -"checksum arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "92c7fb76bc8826a8b33b4ee5bb07a247a81e76764ab4d55e8f73e3a4d8808c71" -"checksum autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a6d640bee2da49f60a4068a7fae53acde8982514ab7bae8b8cea9e88cbcfd799" -"checksum backtrace 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)" = "b5b493b66e03090ebc4343eb02f94ff944e0cbc9ac6571491d170ba026741eb5" -"checksum backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)" = "797c830ac25ccc92a7f8a7b9862bde440715531514594a6154e3d4a54dd769b6" -"checksum base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e" -"checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" -"checksum byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a019b10a2a7cdeb292db131fc8113e57ea2a908f6e7894b0c3c671893b65dbeb" -"checksum bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "40ade3d27603c2cb345eb0912aec461a6dec7e06a4ae48589904e808335c7afa" -"checksum cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)" = "4390a3b5f4f6bce9c1d0c00128379df433e53777fdd30e92f16a529332baec4e" -"checksum cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "082bb9b28e00d3c9d39cc03e64ce4cea0f1bb9b3fde493f0cbc008472d22bdf4" -"checksum chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "45912881121cb26fad7c38c17ba7daa18764771836b34fab7d3fbd93ed633878" -"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" -"checksum crossbeam 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ad4c7ea749d9fb09e23c5cb17e3b70650860553a0e2744e38446b1803bf7db94" -"checksum crossbeam-channel 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "0f0ed1a4de2235cabda8558ff5840bffb97fcb64c97827f354a451307df5f72b" -"checksum crossbeam-deque 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "05e44b8cf3e1a625844d1750e1f7820da46044ff6d28f4d43e455ba3e5bb2c13" -"checksum crossbeam-epoch 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "04c9e3102cc2d69cd681412141b390abd55a362afc1540965dad0ad4d34280b4" -"checksum crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f8306fcef4a7b563b76b7dd949ca48f52bc1141aa067d2ea09565f3e2652aa5c" -"checksum dtoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6d301140eb411af13d3115f9a562c85cc6b541ade9dfa314132244aaee7489dd" -"checksum failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "795bd83d3abeb9220f257e597aa0080a508b27533824adf336529648f6abf7e2" -"checksum failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea1063915fd7ef4309e222a5a07cf9c319fb9c7836b1f89b85458672dbb127e1" +"checksum arc-swap 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d7b8a9123b8027467bce0099fe556c628a53c8d83df0507084c31e9ba2e39aff" +"checksum autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d" +"checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" +"checksum bytes 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "130aac562c0dd69c56b3b1cc8ffd2e17be31d0b6c25b61c96b76231aa23e39e1" +"checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" "checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" -"checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" "checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" "checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" -"checksum futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)" = "49e7653e374fe0d0c12de4250f0bdb60680b8c80eed558c5c7538eec9c89e21b" -"checksum futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "ab90cde24b3319636588d0c35fe03b1333857621051837ed769faefb4c2162e4" -"checksum h2 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "ddb2b25a33e231484694267af28fec74ac63b5ccf51ee2065a5e313b834d836e" -"checksum http 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "1a10e5b573b9a0146545010f50772b9e8b1dd0a256564cc4307694c68832a2f5" -"checksum httparse 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e8734b0cfd3bc3e101ec59100e101c2eecd19282202e87808b3037b442777a83" -"checksum hyper 0.12.24 (registry+https://github.com/rust-lang/crates.io-index)" = "fdfa9b401ef6c4229745bb6e9b2529192d07b920eed624cdee2a82348cd550af" -"checksum idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" -"checksum indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7e81a7c05f79578dbc15793d8b619db9ba32b4577003ef3af1a91c416798c58d" -"checksum iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dbe6e417e7d0975db6512b90796e8ce223145ac4e33c377e4a42882a0e88bb08" -"checksum itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b" +"checksum futures 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b6f16056ecbb57525ff698bb955162d0cd03bee84e6241c27ff75c08d8ca5987" +"checksum futures-channel 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fcae98ca17d102fd8a3603727b9259fcf7fa4239b603d2142926189bc8999b86" +"checksum futures-core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "79564c427afefab1dfb3298535b21eda083ef7935b4f0ecbfcb121f0aec10866" +"checksum futures-executor 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1e274736563f686a837a0568b478bdabfeaec2dca794b5649b04e2fe1627c231" +"checksum futures-io 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e676577d229e70952ab25f3945795ba5b16d63ca794ca9d2c860e5595d20b5ff" +"checksum futures-macro 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "52e7c56c15537adb4f76d0b7a76ad131cb4d2f4f32d3b0bcabcbe1c7c5e87764" +"checksum futures-sink 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "171be33efae63c2d59e6dbba34186fe0d6394fb378069a76dfd80fdcffd43c16" +"checksum futures-task 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0bae52d6b29cf440e298856fec3965ee6fa71b06aa7495178615953fd669e5f9" +"checksum futures-util 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c0d66274fb76985d3c62c886d1da7ac4c0903a8c9f754e8fe0f35a6a6cc39e76" +"checksum h2 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b9433d71e471c1736fd5a61b671fc0b148d7a2992f666c958d03cd8feb3b88d1" +"checksum hermit-abi 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "eff2656d88f158ce120947499e971d743c05dbcbed62e5bd2f38f1698bbc3772" +"checksum http 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b708cc7f06493459026f53b9a61a7a121a5d1ec6238dee58ea4941132b30156b" +"checksum http-body 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "13d5ff830006f7646652e057693569bfe0d51760c0085a071769d142a205111b" +"checksum httparse 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "cd179ae861f0c2e53da70d892f5f3029f9594be0c41dc5269cd371691b1dc2f9" +"checksum hyper 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8bf49cfb32edee45d890537d9057d1b02ed55f53b7b6a30bae83a38c9231749e" +"checksum indexmap 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b54058f0a6ff80b6803da8faf8997cde53872b38f4023728f6830b06cd3c0dc" +"checksum iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e" +"checksum itoa 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "b8b7a7c0c47db5545ed3fef7468ee7bb5b74691498139e4b3f6a20685dc6dd8e" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" -"checksum lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a374c89b9db55895453a74c1e38861d9deec0b01b405a82516e9d5de4820dea1" -"checksum lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f" -"checksum libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)" = "e962c7641008ac010fa60a7dfdc1712449f29c44ef2d4702394aea943ee75047" -"checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c" -"checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6" -"checksum maplit 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "08cbb6b4fef96b6d77bfc40ec491b1690c779e77b05cd9f07f787ed376fd4c43" -"checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" -"checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3" -"checksum mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)" = "71646331f2619b1026cc302f87a2b8b648d5c6dd6937846a16cc8ce0f347f432" +"checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +"checksum libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)" = "d515b1f41455adea1313a4a2ac8a8a477634fbae63cc6100e3aebb207ce61558" +"checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" +"checksum memchr 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3197e20c7edb283f87c071ddfc7a2cca8f8e0b888c242959846a6fce03c72223" +"checksum mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)" = "302dec22bcf6bae6dfb69c647187f4b4d0fb6f535521f7bc022430ce8e12008f" +"checksum mio-named-pipes 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "f5e374eff525ce1c5b7687c4cef63943e7686524a387933ad27ca7ec43779cb3" "checksum mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "966257a94e196b11bb43aca423754d87429960a768de9414f3691d6957abf125" "checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" +"checksum miow 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "396aa0f2003d7df8395cb93e09871561ccc3e785f0acb369170e8cc74ddf9226" "checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88" -"checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945" -"checksum num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "e83d528d2677f0518c570baf2b7abdcf0cd2d248860b68507bdcb3e91d4c0cea" -"checksum num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1" -"checksum num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1a23f0ed30a54abaa0c7e83b1d2d87ada7c3c23078d1d87815af3e3b6385fbba" -"checksum owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49a4b8ea2179e6a2e27411d3bca09ca6dd630821cf6894c6c7c8467a8ee7ef13" -"checksum parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ab41b4aed082705d1056416ae4468b6ea99d52599ecf3169b00088d43113e337" -"checksum parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94c8c7923936b28d546dfd14d4472eaf34c99b14e1c973a32b3e6d4eb04298c9" -"checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" -"checksum proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)" = "4d317f9caece796be1980837fd5cb3dfec5613ebdb04ad0956deea83ce168915" -"checksum quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)" = "cdd8e04bd9c52e0342b406469d494fcb033be4bdbe5c606016defbb1681411e1" -"checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" -"checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" -"checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" -"checksum rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d0e7a549d590831370895ab7ba4ea0c1b6b011d106b5ff2da6eee112615e6dc0" -"checksum rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4" -"checksum rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" -"checksum rand_jitter 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b9ea758282efe12823e0d952ddb269d2e1897227e464919a554f2a03ef1b832" -"checksum rand_os 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b7c690732391ae0abafced5015ffb53656abfaec61b342290e5eb56b286a679d" -"checksum rand_pcg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "086bd09a33c7044e56bb44d5bdde5a60e7f119a9e95b0775f545de759a32fe05" -"checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" -"checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" -"checksum redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)" = "423e376fffca3dfa06c9e9790a9ccd282fafb3cc6e6397d01dbf64f9bacc6b85" -"checksum rustc-demangle 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "adacaae16d02b6ec37fdc7acfcddf365978de76d1983d3ee22afc260e1ca9619" -"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" -"checksum ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "eb9e9b8cde282a9fe6a42dd4681319bfb63f121b8a8ee9439c6f4107e58a46f7" -"checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" -"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" -"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" -"checksum serde 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)" = "2e20fde37801e83c891a2dc4ebd3b81f0da4d1fb67a9e0a2a3b921e2536a58ee" -"checksum serde_derive 1.0.87 (registry+https://github.com/rust-lang/crates.io-index)" = "633e97856567e518b59ffb2ad7c7a4fd4c5d91d9c7f32dd38a27b2bf7e8114ea" -"checksum serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)" = "27dce848e7467aa0e2fcaf0a413641499c0b745452aaca1194d24dedde9e13c9" -"checksum serde_urlencoded 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d48f9f99cd749a2de71d29da5f948de7f2764cc5a9d7f3c97e3514d4ee6eabf2" -"checksum simple-error 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "c00e871264295428089fb278c4b225be3ca92c227c918857f2e562bac973257b" -"checksum simple_logger 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "25111f1d77db1ac3ee11b62ba4b7a162e6bb3be43e28273f0d3935cc8d3ff7fb" +"checksum num_cpus 1.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "46203554f085ff89c235cd12f7075f3233af9b11ed7c9e16dfe2560d03313ce6" +"checksum pin-project 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7804a463a8d9572f13453c516a5faea534a2403d7ced2f0c7e100eeff072772c" +"checksum pin-project-internal 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "385322a45f2ecf3410c68d2a549a4a2685e8051d0f278e39743ff4e451cb9b3f" +"checksum pin-project-lite 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "237844750cfbb86f67afe27eee600dfbbcb6188d734139b534cbfbf4f96792ae" +"checksum pin-utils 0.1.0-alpha.4 (registry+https://github.com/rust-lang/crates.io-index)" = "5894c618ce612a3fa23881b152b608bafb8c56cfc22f434a3ba3120b40f7b587" +"checksum proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)" = "ecd45702f76d6d3c75a80564378ae228a85f0b59d2f3ed43c91b4a69eb2ebfc5" +"checksum proc-macro-nested 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "369a6ed065f249a159e06c45752c780bda2fb53c995718f9e484d08daa9eb42e" +"checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" +"checksum proc-macro2 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3acb317c6ff86a4e579dfa00fc5e6cca91ecbb4e7eb2df0468805b674eb88548" +"checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe" +"checksum redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)" = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84" +"checksum ryu 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bfa8506c1de11c9c4e4c38863ccbe02a305c8188e85a05a784c9e11e1c3910c8" +"checksum serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)" = "414115f25f818d7dfccec8ee535d76949ae78584fc4f79a6f45a904bf8ab4449" +"checksum serde_derive 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)" = "128f9e303a5a29922045a830221b8f78ec74a5f544944f3d5984f8ec3895ef64" +"checksum serde_json 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)" = "eab8f15f15d6c41a154c1b128a22f2dfabe350ef53c40953d84e36155c91192b" +"checksum signal-hook-registry 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94f478ede9f64724c5d173d7bb56099ec3e2d9fc2774aac65d34b8b890405f41" "checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" -"checksum smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)" = "88aea073965ab29f6edb5493faf96ad662fb18aa9eeb186a3b7057951605ed15" -"checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" -"checksum string 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b639411d0b9c738748b5397d5ceba08e648f4f1992231aa859af1a017f31f60b" -"checksum syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)" = "f92e629aa1d9c827b2bb8297046c1ccffc57c99b947a680d3ccff1f136a3bee9" -"checksum synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "73687139bf99285483c96ac0add482c3776528beac1d97d444f6e91f203a2015" +"checksum socket2 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)" = "e8b74de517221a2cb01a53349cf54182acdc31a074727d3079068448c0676d85" +"checksum syn 1.0.14 (registry+https://github.com/rust-lang/crates.io-index)" = "af6f3550d8dff9ef7dc34d384ac6f107e5d31c8f57d9f28e0081503f547ac8f5" "checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f" -"checksum tokio 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "e0500b88064f08bebddd0c0bed39e19f5c567a5f30975bee52b0c0d3e2eeb38c" -"checksum tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5c501eceaf96f0e1793cf26beb63da3d11c738c4a943fdf3746d81d64684c39f" -"checksum tokio-current-thread 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "331c8acc267855ec06eb0c94618dcbbfea45bed2d20b77252940095273fb58f6" -"checksum tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "30c6dbf2d1ad1de300b393910e8a3aa272b724a400b6531da03eed99e329fbf0" -"checksum tokio-fs 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0e9cbbc8a3698b7ab652340f46633364f9eaa928ddaaee79d8b8f356dd79a09d" -"checksum tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "b53aeb9d3f5ccf2ebb29e19788f96987fa1355f8fe45ea193928eaaaf3ae820f" -"checksum tokio-reactor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "afbcdb0f0d2a1e4c440af82d7bbf0bf91a8a8c0575bcd20c05d15be7e9d3a02f" -"checksum tokio-sync 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3742b64166c1ee9121f1921aea5a726098458926a6b732d906ef23b1f3ef6f4f" -"checksum tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1d14b10654be682ac43efee27401d792507e30fd8d26389e1da3b185de2e4119" -"checksum tokio-threadpool 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "c3fd86cb15547d02daa2b21aadaf4e37dee3368df38a526178a5afa3c034d2fb" -"checksum tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "2910970404ba6fa78c5539126a9ae2045d62e3713041e447f695f41405a120c6" -"checksum tokio-udp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "66268575b80f4a4a710ef83d087fdfeeabdce9b74c797535fbac18a2cb906e92" -"checksum tokio-uds 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "037ffc3ba0e12a0ab4aca92e5234e0dedeb48fddf6ccd260f1f150a36a9f2445" +"checksum tokio 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8fdd17989496f49cdc57978c96f0c9fe5e4a58a8bddc6813c449a4624f6a030b" +"checksum tokio-macros 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "f4b1e7ed7d5d4c2af3d999904b0eebe76544897cdbfb2b9684bed2174ab20f7c" +"checksum tokio-util 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "571da51182ec208780505a32528fc5512a8fe1443ab960b3f2f3ef093cd16930" +"checksum tower-service 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e987b6bf443f4b5b3b6f38704195592cca41c5bb7aedd3c3693c7081f8289860" "checksum try-lock 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e604eb7b43c06650e854be16a2a03155743d3752dd1c943f6829e26b7a36e382" -"checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" -"checksum unicode-normalization 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "141339a08b982d942be2ca06ff8b076563cbe223d1befd5450716790d44e2426" "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" -"checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" -"checksum url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a" -"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" -"checksum want 0.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "797464475f30ddb8830cc529aaaae648d581f99e2036a928877dfde027ddf6b3" +"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" +"checksum want 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" -"checksum winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "92c1eb33641e276cfa214a0522acad57be5c56b10cb348b3c5117db75f3ac4b0" +"checksum winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6" "checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/Cargo.toml b/Cargo.toml index 255cc695..da7fefce 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,9 +1,5 @@ [workspace] members = [ - "lambda-runtime-client", - "lambda-runtime-core", - "lambda-runtime", - "lambda-http", - "lambda-runtime-errors", - "lambda-runtime-errors-derive" + "lambda", + "lambda-attributes" ] \ No newline at end of file diff --git a/NOTICE b/NOTICE index 24db4754..00537da3 100644 --- a/NOTICE +++ b/NOTICE @@ -1,2 +1,2 @@ AWS Lambda Rust Runtime -Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. +Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. diff --git a/lambda-attributes/Cargo.toml b/lambda-attributes/Cargo.toml new file mode 100644 index 00000000..d0c0e6e7 --- /dev/null +++ b/lambda-attributes/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "lambda-attributes" +version = "0.1.0" +authors = ["David Barsky "] +edition = "2018" + +[lib] +proc-macro = true + +[dependencies] +proc-macro2 = { version = "0.4.30" } +syn = { version = "1.0.5", features = ["full"] } +quote = "1" diff --git a/lambda-attributes/src/lib.rs b/lambda-attributes/src/lib.rs new file mode 100644 index 00000000..d9a518af --- /dev/null +++ b/lambda-attributes/src/lib.rs @@ -0,0 +1,68 @@ +extern crate proc_macro; + +use proc_macro::TokenStream; +use quote::quote_spanned; +use syn::{spanned::Spanned, FnArg, ItemFn}; + +#[proc_macro_attribute] +pub fn lambda(_attr: TokenStream, item: TokenStream) -> TokenStream { + let input = syn::parse_macro_input!(item as ItemFn); + + let ret = &input.sig.output; + let name = &input.sig.ident; + let body = &input.block; + let attrs = &input.attrs; + let asyncness = &input.sig.asyncness; + let inputs = &input.sig.inputs; + + if name != "main" { + let tokens = quote_spanned! { name.span() => + compile_error!("only the main function can be tagged with #[lambda::main]"); + }; + return TokenStream::from(tokens); + } + + if asyncness.is_none() { + let tokens = quote_spanned! { input.span() => + compile_error!("the async keyword is missing from the function declaration"); + }; + return TokenStream::from(tokens); + } + + let result = match inputs.len() { + 1 => { + let event = match inputs.first().unwrap() { + FnArg::Typed(arg) => arg, + _ => { + let tokens = quote_spanned! { inputs.span() => + compile_error!("fn main must take a fully formed argument"); + }; + return TokenStream::from(tokens); + } + }; + let arg_name = &event.pat; + let arg_type = &event.ty; + + quote_spanned! { input.span() => + use lambda::LambdaCtx; + + #(#attrs)* + #asyncness fn main() { + async fn actual(#arg_name: #arg_type) #ret { + #body + } + let f = lambda::handler_fn(actual); + lambda::run(f).await.unwrap(); + } + } + } + _ => { + let tokens = quote_spanned! { inputs.span() => + compile_error!("The #[lambda] macro can accept only a single argument."); + }; + return TokenStream::from(tokens); + } + }; + + result.into() +} diff --git a/lambda-http/Cargo.toml b/lambda-http/Cargo.toml index 512ddaab..48a7a05b 100644 --- a/lambda-http/Cargo.toml +++ b/lambda-http/Cargo.toml @@ -20,7 +20,7 @@ http = "0.1" serde = "^1" serde_json = "^1" serde_derive = "^1" -lambda_runtime = { path = "../lambda-runtime", version = "^0.2" } +lambda = { path = "../lambda" } tokio = "^0.1" base64 = "0.10" failure = "0.1" diff --git a/lambda-runtime-client/Cargo.toml b/lambda-runtime-client/Cargo.toml deleted file mode 100644 index e4c962de..00000000 --- a/lambda-runtime-client/Cargo.toml +++ /dev/null @@ -1,30 +0,0 @@ -[package] -name = "lambda_runtime_client" -version = "0.2.3" -authors = ["Stefano Buliani", "David Barsky"] -edition = "2018" -description = "Client SDK for AWS Lambda's runtime APIs" -keywords = ["AWS", "Lambda", "Runtime", "API", "Client"] -license = "Apache-2.0" -homepage = "https://github.com/awslabs/aws-lambda-rust-runtime" -repository = "https://github.com/awslabs/aws-lambda-rust-runtime" -documentation = "https://docs.rs/lambda_runtime_client" -readme = "../README.md" - -[badges] -travis-ci = { repository = "awslabs/aws-lambda-rust-runtime" } -maintenance = { status = "actively-developed" } - -[dependencies] -hyper = "0.12" -tokio = "0.1" -http = "0.1" -serde = "^1" -serde_json = "^1" -serde_derive = "^1" -log = "0.4" -lambda_runtime_errors = { path = "../lambda-runtime-errors", version = "^0.1" } -failure = "^0.1" - -[dev-dependencies] -chrono = "^0.4" diff --git a/lambda-runtime-client/src/client.rs b/lambda-runtime-client/src/client.rs deleted file mode 100644 index 02ffca08..00000000 --- a/lambda-runtime-client/src/client.rs +++ /dev/null @@ -1,526 +0,0 @@ -use crate::error::{ApiError, ApiErrorKind, ErrorResponse}; -use failure::ResultExt; -use hyper::{ - client::HttpConnector, - header::{self, HeaderMap, HeaderValue}, - rt::{Future, Stream}, - Body, Client, Method, Request, Uri, -}; -use log::*; -use serde_derive::*; -use serde_json; -use std::{collections::HashMap, fmt}; -use tokio::runtime::Runtime; - -const RUNTIME_API_VERSION: &str = "2018-06-01"; -const API_CONTENT_TYPE: &str = "application/json"; -const API_ERROR_CONTENT_TYPE: &str = "application/vnd.aws.lambda.error+json"; -const RUNTIME_ERROR_HEADER: &str = "Lambda-Runtime-Function-Error-Type"; -// TODO: Perhaps use a macro to generate this -const DEFAULT_AGENT: &str = "AWS_Lambda_Rust"; - -/// Enum of the headers returned by Lambda's `/next` API call. -pub enum LambdaHeaders { - /// The AWS request ID - RequestId, - /// The ARN of the Lambda function being invoked - FunctionArn, - /// The X-Ray trace ID generated for this invocation - TraceId, - /// The deadline for the function execution in milliseconds - Deadline, - /// The client context header. This field is populated when the function - /// is invoked from a mobile client. - ClientContext, - /// The Cognito Identity context for the invocation. This field is populated - /// when the function is invoked with AWS credentials obtained from Cognito - /// Identity. - CognitoIdentity, -} - -impl LambdaHeaders { - /// Returns the `str` representation of the header. - fn as_str(&self) -> &'static str { - match self { - LambdaHeaders::RequestId => "Lambda-Runtime-Aws-Request-Id", - LambdaHeaders::FunctionArn => "Lambda-Runtime-Invoked-Function-Arn", - LambdaHeaders::TraceId => "Lambda-Runtime-Trace-Id", - LambdaHeaders::Deadline => "Lambda-Runtime-Deadline-Ms", - LambdaHeaders::ClientContext => "Lambda-Runtime-Client-Context", - LambdaHeaders::CognitoIdentity => "Lambda-Runtime-Cognito-Identity", - } - } -} - -impl fmt::Display for LambdaHeaders { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_str(self.as_str()) - } -} - -/// AWS Moble SDK client properties -#[derive(Deserialize, Clone)] -pub struct ClientApplication { - /// The mobile app installation id - #[serde(rename = "installationId")] - pub installation_id: String, - /// The app title for the mobile app as registered with AWS' mobile services. - #[serde(rename = "appTitle")] - pub app_title: String, - /// The version name of the application as registered with AWS' mobile services. - #[serde(rename = "appVersionName")] - pub app_version_name: String, - /// The app version code. - #[serde(rename = "appVersionCode")] - pub app_version_code: String, - /// The package name for the mobile application invoking the function - #[serde(rename = "appPackageName")] - pub app_package_name: String, -} - -/// Client context sent by the AWS Mobile SDK. -#[derive(Deserialize, Clone)] -pub struct ClientContext { - /// Information about the mobile application invoking the function. - pub client: ClientApplication, - /// Custom properties attached to the mobile event context. - pub custom: HashMap, - /// Environment settings from the mobile client. - pub environment: HashMap, -} - -#[derive(Deserialize, Clone)] -/// Cognito identity information sent with the event -pub struct CognitoIdentity { - /// The unique identity id for the Cognito credentials invoking the function. - pub identity_id: String, - /// The identity pool id the caller is "registered" with. - pub identity_pool_id: String, -} - -/// The Lambda function execution context. The values in this struct -/// are populated using the [Lambda environment variables](https://docs.aws.amazon.com/lambda/latest/dg/current-supported-versions.html) -/// and the headers returned by the poll request to the Runtime APIs. -/// A new instance of the `Context` object is passed to each handler invocation. -#[derive(Clone)] -pub struct EventContext { - /// The ARN of the Lambda function being invoked. - pub invoked_function_arn: String, - /// The AWS request ID generated by the Lambda service. - pub aws_request_id: String, - /// The X-Ray trace ID for the current invocation. - pub xray_trace_id: Option, - /// The execution deadline for the current invocation in milliseconds. - pub deadline: i64, - /// The client context object sent by the AWS mobile SDK. This field is - /// empty unless the function is invoked using an AWS mobile SDK. - pub client_context: Option, - /// The Cognito identity that invoked the function. This field is empty - /// unless the invocation request to the Lambda APIs was made using AWS - /// credentials issues by Amazon Cognito Identity Pools. - pub identity: Option, -} - -/// Used by the Runtime to communicate with the internal endpoint. -pub struct RuntimeClient { - _runtime: Runtime, - http_client: Client, - next_endpoint: Uri, - runtime_agent: String, - host: String, -} - -impl<'ev> RuntimeClient { - /// Creates a new instance of the Runtime APIclient SDK. The http client has timeouts disabled and - /// will always send a `Connection: keep-alive` header. Optionally, the runtime client can receive - /// a user agent string. This string is used to make requests to the runtime APIs and is used to - /// identify the runtime being used by the function. For example, the `lambda_runtime_core` crate - /// uses `AWS_Lambda_Rust/0.1.0 (rustc/1.31.1-stable)`. The runtime client can also receive an - /// instance of Tokio Runtime to use. - pub fn new(host: &str, agent: Option, runtime: Option) -> Result { - debug!("Starting new HttpRuntimeClient for {}", host); - let runtime_agent = match agent { - Some(a) => a, - None => DEFAULT_AGENT.to_owned(), - }; - - // start a tokio core main event loop for hyper - let runtime = match runtime { - Some(r) => r, - None => Runtime::new().context(ApiErrorKind::Unrecoverable("Could not initialize runtime".to_string()))?, - }; - - let http_client = Client::builder().executor(runtime.executor()).build_http(); - // we cached the parsed Uri since this never changes. - let next_endpoint = format!("http://{}/{}/runtime/invocation/next", host, RUNTIME_API_VERSION) - .parse::() - .context(ApiErrorKind::Unrecoverable("Could not parse API uri".to_string()))?; - - Ok(RuntimeClient { - _runtime: runtime, - http_client, - next_endpoint, - runtime_agent, - host: host.to_owned(), - }) - } -} - -impl<'ev> RuntimeClient { - /// Polls for new events to the Runtime APIs. - pub fn next_event(&self) -> Result<(Vec, EventContext), ApiError> { - trace!("Polling for next event"); - - let req = Request::builder() - .method(Method::GET) - .uri(self.next_endpoint.clone()) - .header(header::USER_AGENT, self.runtime_agent.clone()) - .body(Body::from("")) - .unwrap(); - - // We wait instead of processing the future asynchronously because AWS Lambda - // itself enforces only one event per container at a time. No point in taking on - // the additional complexity. - let resp = self - .http_client - .request(req) - .wait() - .context(ApiErrorKind::Unrecoverable("Could not fetch next event".to_string()))?; - - if resp.status().is_client_error() { - error!( - "Runtime API returned client error when polling for new events: {}", - resp.status() - ); - Err(ApiErrorKind::Recoverable(format!( - "Error {} when polling for events", - resp.status() - )))?; - } - if resp.status().is_server_error() { - error!( - "Runtime API returned server error when polling for new events: {}", - resp.status() - ); - Err(ApiErrorKind::Unrecoverable( - "Server error when polling for new events".to_string(), - ))?; - } - let ctx = self.get_event_context(&resp.headers())?; - let out = resp - .into_body() - .concat2() - .wait() - .context(ApiErrorKind::Recoverable("Could not read event boxy".to_string()))?; - let buf = out.into_bytes().to_vec(); - - trace!( - "Received new event for request id {}. Event length {} bytes", - ctx.aws_request_id, - buf.len() - ); - Ok((buf, ctx)) - } - - /// Calls the Lambda Runtime APIs to submit a response to an event. In this function we treat - /// all errors from the API as an unrecoverable error. This is because the API returns - /// 4xx errors for responses that are too long. In that case, we simply log the output and fail. - /// - /// # Arguments - /// - /// * `request_id` The request id associated with the event we are serving the response for. - /// This is returned as a header from the poll (`/next`) API. - /// * `output` The object be sent back to the Runtime APIs as a response. - /// - /// # Returns - /// A `Result` object containing a bool return value for the call or an `error::ApiError` instance. - pub fn event_response(&self, request_id: &str, output: &[u8]) -> Result<(), ApiError> { - trace!( - "Posting response for request {} to Runtime API. Response length {} bytes", - request_id, - output.len() - ); - let uri = format!( - "http://{}/{}/runtime/invocation/{}/response", - self.host, RUNTIME_API_VERSION, request_id - ) - .parse::() - .context(ApiErrorKind::Unrecoverable( - "Could not generate response uri".to_owned(), - ))?; - let req = self.get_runtime_post_request(&uri, output); - - let resp = self - .http_client - .request(req) - .wait() - .context(ApiErrorKind::Recoverable("Could not post event response".to_string()))?; - if !resp.status().is_success() { - error!( - "Error from Runtime API when posting response for request {}: {}", - request_id, - resp.status() - ); - Err(ApiErrorKind::Recoverable(format!( - "Error {} while sending response", - resp.status() - )))?; - } - trace!("Posted response to Runtime API for request {}", request_id); - Ok(()) - } - - /// Calls Lambda's Runtime APIs to send an error generated by the `Handler`. Because it's rust, - /// the error type for lambda is always `handled`. - /// - /// # Arguments - /// - /// * `request_id` The request id associated with the event we are serving the error for. - /// * `e` An instance of `errors::HandlerError` generated by the handler function. - /// - /// # Returns - /// A `Result` object containing a bool return value for the call or an `error::ApiError` instance. - pub fn event_error(&self, request_id: &str, e: &ErrorResponse) -> Result<(), ApiError> { - trace!( - "Posting error to runtime API for request {}: {}", - request_id, - e.error_message - ); - let uri = format!( - "http://{}/{}/runtime/invocation/{}/error", - self.host, RUNTIME_API_VERSION, request_id - ) - .parse::() - .context(ApiErrorKind::Unrecoverable( - "Could not generate response uri".to_owned(), - ))?; - let req = self.get_runtime_error_request(&uri, &e); - - let resp = self.http_client.request(req).wait().context(ApiErrorKind::Recoverable( - "Could not post event error response".to_string(), - ))?; - if !resp.status().is_success() { - error!( - "Error from Runtime API when posting error response for request {}: {}", - request_id, - resp.status() - ); - Err(ApiErrorKind::Recoverable(format!( - "Error {} while sending response", - resp.status() - )))?; - } - trace!("Posted error response for request id {}", request_id); - Ok(()) - } - - /// Calls the Runtime APIs to report a failure during the init process. - /// The contents of the error (`e`) parmeter are passed to the Runtime APIs - /// using the private `to_response()` method. - /// - /// # Arguments - /// - /// * `e` An instance of `errors::RuntimeError`. - /// - /// # Panics - /// If it cannot send the init error. In this case we panic to force the runtime - /// to restart. - pub fn fail_init(&self, e: &ErrorResponse) { - error!("Calling fail_init Runtime API: {}", e.error_message); - let uri = format!("http://{}/{}/runtime/init/error", self.host, RUNTIME_API_VERSION) - .parse::() - .map_err(|e| { - error!("Could not parse fail init URI: {}", e); - panic!("Killing runtime"); - }); - let req = self.get_runtime_error_request(&uri.unwrap(), &e); - - self.http_client - .request(req) - .wait() - .map_err(|e| { - error!("Error while sending init failed message: {}", e); - panic!("Error while sending init failed message: {}", e); - }) - .map(|resp| { - info!("Successfully sent error response to the runtime API: {:?}", resp); - }) - .expect("Could not complete init_fail request"); - } - - /// Returns the endpoint configured for this HTTP Runtime client. - pub fn get_endpoint(&self) -> &str { - &self.host - } - - /// Creates a Hyper `Request` object for the given `Uri` and `Body`. Sets the - /// HTTP method to `POST` and the `Content-Type` header value to `application/json`. - /// - /// # Arguments - /// - /// * `uri` A `Uri` reference target for the request - /// * `body` The content of the post request. This parameter must not be null - /// - /// # Returns - /// A Populated Hyper `Request` object. - fn get_runtime_post_request(&self, uri: &Uri, body: &[u8]) -> Request { - Request::builder() - .method(Method::POST) - .uri(uri.clone()) - .header(header::CONTENT_TYPE, header::HeaderValue::from_static(API_CONTENT_TYPE)) - .header(header::USER_AGENT, self.runtime_agent.clone()) - .body(Body::from(body.to_owned())) - .unwrap() - } - - fn get_runtime_error_request(&self, uri: &Uri, e: &ErrorResponse) -> Request { - let body = serde_json::to_vec(&e).expect("Could not turn error object into response JSON"); - Request::builder() - .method(Method::POST) - .uri(uri.clone()) - .header( - header::CONTENT_TYPE, - header::HeaderValue::from_static(API_ERROR_CONTENT_TYPE), - ) - .header(header::USER_AGENT, self.runtime_agent.clone()) - // this header is static for the runtime APIs and it's likely to go away in the future. - .header(RUNTIME_ERROR_HEADER, HeaderValue::from_static("Unhandled")) - .body(Body::from(body)) - .unwrap() - } - - /// Creates an `EventContext` object based on the response returned by the Runtime - /// API `/next` endpoint. - /// - /// # Arguments - /// - /// * `resp` The response returned by the Runtime APIs endpoint. - /// - /// # Returns - /// A `Result` containing the populated `EventContext` or an `ApiError` if the required headers - /// were not present or the client context and cognito identity could not be parsed from the - /// JSON string. - fn get_event_context(&self, headers: &HeaderMap) -> Result { - // let headers = resp.headers(); - - let aws_request_id = header_string( - headers.get(LambdaHeaders::RequestId.as_str()), - &LambdaHeaders::RequestId, - )?; - let invoked_function_arn = header_string( - headers.get(LambdaHeaders::FunctionArn.as_str()), - &LambdaHeaders::FunctionArn, - )?; - let xray_trace_id = match headers.get(LambdaHeaders::TraceId.as_str()) { - Some(trace_id) => match trace_id.to_str() { - Ok(trace_str) => Some(trace_str.to_owned()), - Err(e) => { - // we do not fail on this error. - error!("Could not parse X-Ray trace id as string: {}", e); - None - } - }, - None => None, - }; - let deadline = header_string(headers.get(LambdaHeaders::Deadline.as_str()), &LambdaHeaders::Deadline)? - .parse::() - .context(ApiErrorKind::Recoverable( - "Could not parse deadline header value to int".to_string(), - ))?; - - let mut ctx = EventContext { - aws_request_id, - invoked_function_arn, - xray_trace_id, - deadline, - client_context: Option::default(), - identity: Option::default(), - }; - - if let Some(ctx_json) = headers.get(LambdaHeaders::ClientContext.as_str()) { - let ctx_json = ctx_json.to_str().context(ApiErrorKind::Recoverable( - "Could not convert context header content to string".to_string(), - ))?; - trace!("Found Client Context in response headers: {}", ctx_json); - let ctx_value: ClientContext = serde_json::from_str(&ctx_json).context(ApiErrorKind::Recoverable( - "Could not parse client context value as json object".to_string(), - ))?; - ctx.client_context = Option::from(ctx_value); - }; - - if let Some(cognito_json) = headers.get(LambdaHeaders::CognitoIdentity.as_str()) { - let cognito_json = cognito_json.to_str().context(ApiErrorKind::Recoverable( - "Could not convert congnito context header content to string".to_string(), - ))?; - trace!("Found Cognito Identity in response headers: {}", cognito_json); - let identity_value: CognitoIdentity = serde_json::from_str(&cognito_json).context( - ApiErrorKind::Recoverable("Could not parse cognito context value as json object".to_string()), - )?; - ctx.identity = Option::from(identity_value); - }; - - Ok(ctx) - } -} - -fn header_string(value: Option<&HeaderValue>, header_type: &LambdaHeaders) -> Result { - match value { - Some(value_str) => Ok(value_str - .to_str() - .context(ApiErrorKind::Recoverable(format!( - "Could not parse {} header", - header_type - )))? - .to_owned()), - None => { - error!("Response headers do not contain {} header", header_type); - Err(ApiErrorKind::Recoverable(format!("Missing {} header", header_type)))? - } - } -} - -#[cfg(test)] -pub(crate) mod tests { - use super::*; - use chrono::{Duration, Utc}; - - fn get_headers() -> HeaderMap { - let mut headers: HeaderMap = HeaderMap::new(); - headers.insert( - LambdaHeaders::RequestId.as_str(), - HeaderValue::from_str("req_id").unwrap(), - ); - headers.insert( - LambdaHeaders::FunctionArn.as_str(), - HeaderValue::from_str("func_arn").unwrap(), - ); - headers.insert(LambdaHeaders::TraceId.as_str(), HeaderValue::from_str("trace").unwrap()); - let deadline = Utc::now() + Duration::seconds(10); - headers.insert( - LambdaHeaders::Deadline.as_str(), - HeaderValue::from_str(&deadline.timestamp_millis().to_string()).unwrap(), - ); - headers - } - - #[test] - fn get_event_context_with_empty_trace_id() { - let client = RuntimeClient::new("localhost:8081", None, None).expect("Could not initialize runtime client"); - let mut headers = get_headers(); - headers.remove(LambdaHeaders::TraceId.as_str()); - let headers_result = client.get_event_context(&headers); - assert_eq!(false, headers_result.is_err()); - let ok_result = headers_result.unwrap(); - assert_eq!(None, ok_result.xray_trace_id); - assert_eq!("req_id", ok_result.aws_request_id); - } - - #[test] - fn get_event_context_populates_trace_id_when_present() { - let client = RuntimeClient::new("localhost:8081", None, None).expect("Could not initialize runtime client"); - let headers = get_headers(); - let headers_result = client.get_event_context(&headers); - assert_eq!(false, headers_result.is_err()); - assert_eq!(Some("trace".to_owned()), headers_result.unwrap().xray_trace_id); - } -} diff --git a/lambda-runtime-client/src/error.rs b/lambda-runtime-client/src/error.rs deleted file mode 100644 index 0235773a..00000000 --- a/lambda-runtime-client/src/error.rs +++ /dev/null @@ -1,165 +0,0 @@ -//! This module defines the `RuntimeApiError` trait that developers should implement -//! to send their custom errors to the AWS Lambda Runtime Client SDK. The module also -//! defines the `ApiError` type returned by the `RuntimeClient` implementations. -use failure::{AsFail, Backtrace, Context, Fail}; -use lambda_runtime_errors::LambdaErrorExt; -use log::*; -use serde_derive::*; -use std::{ - fmt::{self, Display}, - option::Option, -}; - -/// Error type for the error responses to the Runtime APIs. In the future, this library -/// should use a customer-generated error code -pub const RUNTIME_ERROR_TYPE: &str = "RustRuntimeError"; - -/// This object is used to generate requests to the Lambda Runtime APIs. -/// It is used for both the error response APIs and fail init calls. -/// custom error types should implement the `RuntimeError` trait and return -/// this object to be compatible with the APIs. -#[derive(Serialize)] -pub struct ErrorResponse { - /// The error message generated by the application. - #[serde(rename = "errorMessage")] - pub error_message: String, - /// The error type for Lambda. Normally, this value is populated using the - /// `error_type()` method from the `LambdaErrorExt` trait. - #[serde(rename = "errorType")] - pub error_type: String, - /// The stack trace for the exception as vector of strings. In the framework, - /// this value is automatically populated using the `backtrace` crate. - #[serde(rename = "stackTrace")] - pub stack_trace: Option>, -} - -impl ErrorResponse { - /// Creates a new instance of the `ErrorResponse` object with the given parameters. If the - /// `RUST_BACKTRACE` env variable is `1` the `ErrorResponse` is populated with the backtrace - /// collected through the [`backtrace` craete](https://crates.io/crates/backtrace). - /// - /// # Arguments - /// - /// * `message` The error message to be returned to the APIs. Normally the error description() - /// * `err_type` An error type that identifies the root cause. Normally populated by the - /// `error_type()` method in the `LambdaErrorExt` trait. - /// * `backtrace` The stack trace for the error - /// - /// # Return - /// A new instance of the `ErrorResponse` object. - fn new(message: String, err_type: String, backtrace: Option<&Backtrace>) -> Self { - let mut err = ErrorResponse { - error_message: message, - error_type: err_type, - stack_trace: Option::default(), - }; - // assume that failure is smart enough to only collect a backtrace - // if the env variable is enabled - if let Some(stack) = backtrace { - trace!("Begin backtrace collection"); - err.stack_trace = Some( - format!("{:?}", stack) - .lines() - .map(std::string::ToString::to_string) - .collect::>(), - ); - trace!("Completed backtrace collection"); - } - - err - } -} - -impl From for ErrorResponse { - fn from(e: T) -> Self { - ErrorResponse::new(format!("{}", e), e.error_type().to_owned(), e.as_fail().backtrace()) - } -} - -/// Represents an error generated by the Lambda Runtime API client. -#[derive(Debug)] -pub struct ApiError { - inner: Context, -} - -impl ApiError { - /// Returns `true` if the API error is recoverable and should be retried - pub fn is_recoverable(&self) -> bool { - match *self.inner.get_context() { - ApiErrorKind::Recoverable(_) => true, - _ => false, - } - } -} -/// Failure context for the `ApiError` type. The kind is used to indicate whether the -/// error is recoverable and should be retried or not. -#[derive(Clone, PartialEq, Debug, Fail)] -pub enum ApiErrorKind { - /// Runtime implementations that receive recoverable errors should automatically - /// retry requests - #[fail(display = "Recoverable API error: {}", _0)] - Recoverable(String), - /// Unrecoverable error should cause the runtime implementation to call the `fail_init` - /// method of the Runtime APIs if it is appropriate and then shutdown gracefully - #[fail(display = "Unrecoverable API error: {}", _0)] - Unrecoverable(String), -} - -impl Fail for ApiError { - fn cause(&self) -> Option<&dyn Fail> { - self.inner.cause() - } - - fn backtrace(&self) -> Option<&Backtrace> { - self.inner.backtrace() - } -} - -impl Display for ApiError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - Display::fmt(&self.inner, f) - } -} - -impl LambdaErrorExt for ApiError { - fn error_type(&self) -> &str { - "RuntimeApiError" - } -} - -impl From for ApiError { - fn from(kind: ApiErrorKind) -> Self { - Self { - inner: Context::new(kind), - } - } -} - -impl From> for ApiError { - fn from(inner: Context) -> Self { - Self { inner } - } -} - -#[cfg(test)] -pub(crate) mod tests { - use super::*; - use failure::format_err; - use std::env; - - #[test] - fn does_not_produce_stack_trace() { - env::remove_var("RUST_BACKTRACE"); - let err = format_err!("Test error").compat(); - let resp_err = ErrorResponse::from(err); - assert_eq!(resp_err.stack_trace, None); - } - - #[test] - fn is_recoverable_eq_correctly() { - let rec_err = ApiError::from(ApiErrorKind::Recoverable("Some recoverable kind".to_owned())); - assert_eq!(true, rec_err.is_recoverable()); - let unrec_err = ApiError::from(ApiErrorKind::Unrecoverable("Some unrecovrable kind".to_owned())); - assert_eq!(false, unrec_err.is_recoverable()); - } -} diff --git a/lambda-runtime-client/src/lib.rs b/lambda-runtime-client/src/lib.rs deleted file mode 100644 index 85089ecc..00000000 --- a/lambda-runtime-client/src/lib.rs +++ /dev/null @@ -1,62 +0,0 @@ -#![warn(missing_docs)] -#![deny(warnings)] -#![allow(clippy::new_ret_no_self)] -//! Rust client SDK for the AWS Lambda Runtime APIs. This crate defines -//! a `RuntimeClient` that encapsulates interactions with AWS Lambda's Runtime -//! APIs. -//! -//! To return errors to the Runtime APIs through the `event_error()` or -//! `fail_init()` methods the `Error` objects must implement the `error::RuntimeApiError` -//! trait from this crate. The RuntimeApiError trait defines a single method -//! called `to_response()`. The method must return an `error::RuntimeError` object. -//! See the `error::ApiError` object in this crate for an example. -//! -//! # Examples -//! -//! ```rust,no_run -//! extern crate lambda_runtime_client; -//! #[macro_use] -//! extern crate serde_derive; -//! extern crate serde_json; -//! -//! use lambda_runtime_client::{RuntimeClient, EventContext}; -//! -//! #[derive(Serialize, Deserialize, Debug)] -//! struct CustomEvent { -//! name: String, -//! } -//! -//! #[derive(Serialize, Deserialize, Debug)] -//! struct CustomResponse { -//! surname: String, -//! } -//! -//! fn main() { -//! let client = RuntimeClient::new("http://localhost:8080", None, None) -//! .expect("Could not initialize client"); -//! -//! let (event_data, event_context) = client.next_event() -//! .expect("Could not retrieve next event"); -//! let custom_event: CustomEvent = serde_json::from_slice(&event_data) -//! .expect("Could not turn Vec into CustomEvent object"); -//! -//! println!("Event for {}", custom_event.name); -//! if custom_event.name == "John" { -//! let resp_object = CustomResponse{ surname: String::from("Doe")}; -//! let resp_vec = serde_json::to_vec(&resp_object) -//! .expect("Could not serialize CustomResponse to Vec"); -//! client.event_response(&event_context.aws_request_id, &resp_vec) -//! .expect("Response sent successfully"); -//! } else { -//! // return a custom error by implementing the RuntimeApiError trait. -//! // See the error module for examples. -//! //client.event_error(&event_context.aws_request_id, CustomErrorType::new("Invalid first name")) -//! // .expect("Could not send error response"); -//! } -//! } -//! ``` - -mod client; -pub mod error; - -pub use crate::client::*; diff --git a/lambda-runtime-core/Cargo.toml b/lambda-runtime-core/Cargo.toml deleted file mode 100644 index cf57ad41..00000000 --- a/lambda-runtime-core/Cargo.toml +++ /dev/null @@ -1,27 +0,0 @@ -[package] -name = "lambda_runtime_core" -version = "0.1.2" -authors = ["Stefano Buliani", "David Barsky"] -description = "Rust runtime for AWS Lambda" -keywords = ["AWS", "Lambda", "Runtime", "Rust"] -license = "Apache-2.0" -homepage = "https://github.com/awslabs/aws-lambda-rust-runtime" -repository = "https://github.com/awslabs/aws-lambda-rust-runtime" -documentation = "https://docs.rs/lambda_runtime_core" -edition = "2018" - -[dependencies] -log = "^0.4" -hyper = "^0.12" -tokio = "^0.1" -backtrace = "^0.3" -chrono = "^0.4" -failure = "^0.1" -lambda_runtime_client = { path = "../lambda-runtime-client", version = "^0.2" } -lambda_runtime_errors = { path = "../lambda-runtime-errors", version = "^0.1" } - -[dev-dependencies] -simple_logger = "^1.0" - -[build-dependencies] -rustc_version = "^0.2" \ No newline at end of file diff --git a/lambda-runtime-core/build.rs b/lambda-runtime-core/build.rs deleted file mode 100644 index b5eb4bc9..00000000 --- a/lambda-runtime-core/build.rs +++ /dev/null @@ -1,56 +0,0 @@ -use rustc_version::{Channel, VersionMeta}; -use std::{env, fs, io::Write, path::Path, process::Command}; - -const RUNTIME_METADATA_FILE: &str = "runtime_release"; - -fn main() { - println!("Generating AWS Lambda metadata file"); - let out_dir = env::var("OUT_DIR").unwrap(); - let compiler = env::var("RUSTC").unwrap(); - let cargo_version = env::var("CARGO_PKG_VERSION").unwrap(); - let compiler_version = - VersionMeta::for_command(Command::new(compiler.clone())).expect("Could not load compiler metdata"); - let chn: &str; - match compiler_version.channel { - Channel::Dev => chn = "dev", - Channel::Nightly => chn = "nightly", - Channel::Beta => chn = "beta", - Channel::Stable => chn = "stable", - } - let compiler_str = format!("{}/{}-{}", compiler, compiler_version.semver, chn); - - let agent = format!("AWS_Lambda_Rust/{} ({})", cargo_version, compiler_str); - // we expect this library to be built as a dependency and the output directory - // to be something like: my-lambda-function/target/release/build/lambda_runtime_core-c1abe336a4420096/out. - // we want the metadata file to be generated alongside the executable of the function - // so we travel 3 directories up to my-lambda-function/target/release. - let metadata_path = Path::new(&out_dir) - .parent() - .unwrap() - .parent() - .unwrap() - .parent() - .unwrap() - .join(RUNTIME_METADATA_FILE); - println!("Writing runtime metadata to: {}", metadata_path.to_str().unwrap()); - println!("Runtime metadata: {}", agent); - fs::write(metadata_path, agent.clone()).expect("Could not write runtime metdata file"); - - // next generate the metadata function for the runtime - let dest_path = Path::new(&out_dir).join("metadata.rs"); - let mut f = fs::File::create(&dest_path).unwrap(); - - f.write_all( - format!( - " -/// returns metdata information about the Lambda runtime -pub fn runtime_release() -> &'static str {{ - \"{}\" -}} -", - agent - ) - .as_bytes(), - ) - .unwrap(); -} diff --git a/lambda-runtime-core/examples/simple.rs b/lambda-runtime-core/examples/simple.rs deleted file mode 100644 index f83f3f34..00000000 --- a/lambda-runtime-core/examples/simple.rs +++ /dev/null @@ -1,21 +0,0 @@ -use failure::format_err; -use lambda_runtime_core::{lambda, Context, HandlerError}; -use simple_logger; -use std::error::Error; - -fn main() -> Result<(), Box> { - simple_logger::init_with_level(log::Level::Debug)?; - lambda!(my_handler); - - Ok(()) -} - -fn my_handler(data: Vec, _c: Context) -> Result, HandlerError> { - let first_name = String::from_utf8(data)?; - - if first_name == "" { - return Err(format_err!("First name must be valid").into()); - } - - Ok(format!("Hello, {}!", first_name).as_bytes().to_vec()) -} diff --git a/lambda-runtime-core/src/context.rs b/lambda-runtime-core/src/context.rs deleted file mode 100644 index 658a29f6..00000000 --- a/lambda-runtime-core/src/context.rs +++ /dev/null @@ -1,134 +0,0 @@ -use chrono::Utc; - -use crate::env as lambda_env; -use lambda_runtime_client; - -/// The Lambda function execution context. The values in this struct -/// are populated using the [Lambda environment variables](https://docs.aws.amazon.com/lambda/latest/dg/current-supported-versions.html) -/// and the headers returned by the poll request to the Runtime APIs. -/// A new instance of the `Context` object is passed to each handler invocation. -#[derive(Default, Clone)] -pub struct Context { - /// The amount of memory allocated to the Lambda function in Mb. - /// This value is extracted from the `AWS_LAMBDA_FUNCTION_MEMORY_SIZE` - /// environment variable set by the Lambda service. - pub memory_limit_in_mb: i32, - /// The name of the Lambda function as registered with the Lambda - /// service. The value is extracted from the `AWS_LAMBDA_FUNCTION_NAME` - /// environment variable set by the Lambda service. - pub function_name: String, - /// The version of the function being invoked. This value is extracted - /// from the `AWS_LAMBDA_FUNCTION_VERSION` environment variable set - /// by the Lambda service. - pub function_version: String, - /// The fully qualified ARN (Amazon Resource Name) for the function - /// invocation event. This value is returned by the Lambda Runtime APIs - /// as a header. - pub invoked_function_arn: String, - /// The AWS request ID for the current invocation event. This value - /// is returned by the Lambda Runtime APIs as a header. - pub aws_request_id: String, - /// The X-Ray trace ID for the current invocation. This value is returned - /// by the Lambda Runtime APIs as a header. Developers can use this value - /// with the AWS SDK to create new, custom sub-segments to the current - /// invocation. - pub xray_trace_id: Option, - /// The name of the CloudWatch log stream for the current execution - /// environment. This value is extracted from the `AWS_LAMBDA_LOG_STREAM_NAME` - /// environment variable set by the Lambda service. - pub log_stream_name: String, - /// The name of the CloudWatch log group for the current execution - /// environment. This value is extracted from the `AWS_LAMBDA_LOG_GROUP_NAME` - /// environment variable set by the Lambda service. - pub log_group_name: String, - - /// The client context sent by the AWS Mobile SDK with the invocation - /// request. This value is returned by the Lambda Runtime APIs as a - /// header. This value is populated only if the invocation request - /// originated from an AWS Mobile SDK or an SDK that attached the client - /// context information to the request. - pub client_context: Option, - /// The information of the Cognito identity that sent the invocation - /// request to the Lambda service. This value is returned by the Lambda - /// Runtime APIs in a header and it's only populated if the invocation - /// request was performed with AWS credentials federated through the Cognito - /// identity service. - pub identity: Option, - - /// The deadline for the current handler execution in milliseconds, based - /// on a unix `MONOTONIC` clock. - pub deadline: i64, -} - -impl Context { - /// Generates a new `Context` object for an event. Uses the responses headers alongside the - /// environment variable values from the `FunctionSettings` object to populate the data. - /// - /// # Arguments - /// - /// * `local_settings` A populated environment settings object - /// - /// # Return - /// A new, populated `Context` object. - pub(super) fn new(local_settings: lambda_env::FunctionSettings) -> Context { - Context { - xray_trace_id: None, - memory_limit_in_mb: local_settings.memory_size, - function_name: local_settings.function_name, - function_version: local_settings.version, - log_stream_name: local_settings.log_stream, - log_group_name: local_settings.log_group, - ..Default::default() - } - } - - /// Returns the remaining time in the execution in milliseconds. This is based on the - /// deadline header passed by Lambda's Runtime APIs. - pub fn get_time_remaining_millis(&self) -> i64 { - self.deadline - Utc::now().timestamp_millis() - } -} - -#[cfg(test)] -pub(crate) mod tests { - use super::*; - use crate::env::{self, ConfigProvider}; - use std::{thread::sleep, time}; - - fn get_deadline(timeout_secs: i64) -> i64 { - let deadline = Utc::now() + chrono::Duration::seconds(timeout_secs); - deadline.timestamp_millis() - } - - pub(crate) fn test_context(timeout_secs: i64) -> Context { - Context { - memory_limit_in_mb: 128, - function_name: "test_func".to_string(), - function_version: "$LATEST".to_string(), - invoked_function_arn: "arn:aws:lambda".to_string(), - aws_request_id: "123".to_string(), - xray_trace_id: Some("123".to_string()), - log_stream_name: "logStream".to_string(), - log_group_name: "logGroup".to_string(), - client_context: Option::default(), - identity: Option::default(), - deadline: get_deadline(timeout_secs), - } - } - - #[test] - fn verify_time_remaining() { - let config = env::tests::MockConfigProvider { error: false }; - let mut ctx = Context::new(config.get_function_settings().unwrap()); - ctx.deadline = get_deadline(10); - println!("Set deadline to: {}", ctx.deadline); - sleep(time::Duration::new(2, 0)); - - let remaining = ctx.get_time_remaining_millis(); - assert!( - remaining > 7800 && remaining < 8200, - "Remaining time in millis outside the expected range: {}", - remaining - ); - } -} diff --git a/lambda-runtime-core/src/env.rs b/lambda-runtime-core/src/env.rs deleted file mode 100644 index 94cde577..00000000 --- a/lambda-runtime-core/src/env.rs +++ /dev/null @@ -1,183 +0,0 @@ -use std::env; - -use crate::error::RuntimeError; -use log::*; - -/// The name of the environment variable in the Lambda execution -/// environment for the Runtime APIs endpoint. The value of this -/// variable is read once as the runtime starts. -pub const RUNTIME_ENDPOINT_VAR: &str = "AWS_LAMBDA_RUNTIME_API"; - -/// Clone-able generic function settings object. The data is loaded -/// from environment variables during the init process. The data -/// for the object is cloned in the `Context` for each invocation. -#[derive(Clone)] -pub struct FunctionSettings { - pub function_name: String, - pub memory_size: i32, - pub version: String, - pub log_stream: String, - pub log_group: String, -} - -/// Trait used by the `RustRuntime` module to retrieve configuration information -/// about the environement. This is implemented by the `EnvConfigProvider` using -/// the environment variables. We also have a mock implementation for the unit tests -pub trait ConfigProvider { - /// Loads the function settings such as name, arn, memory amount, version, etc. - /// - /// # Return - /// A `Result` of `FunctionSettings` or a `RuntimeError`. The runtime - /// fails the init process if this function returns an error. - fn get_function_settings(&self) -> Result; - - /// Returns the endpoint (hostname:port) for the Runtime API endpoint - fn get_runtime_api_endpoint(&self) -> Result; -} - -/// Implementation of the `ConfigProvider` trait that reads the settings from -/// environment variables in the Lambda execution environment. This is the config -/// used by the `start()` method of this module. -pub struct EnvConfigProvider; - -impl std::default::Default for EnvConfigProvider { - fn default() -> Self { - EnvConfigProvider - } -} - -impl ConfigProvider for EnvConfigProvider { - /// Loads the function settings from the Lambda environment variables: - /// https://docs.aws.amazon.com/lambda/latest/dg/current-supported-versions.html - fn get_function_settings(&self) -> Result { - let function_name = env::var("AWS_LAMBDA_FUNCTION_NAME")?; - let version = env::var("AWS_LAMBDA_FUNCTION_VERSION")?; - let log_stream = env::var("AWS_LAMBDA_LOG_STREAM_NAME")?; - let log_group = env::var("AWS_LAMBDA_LOG_GROUP_NAME")?; - let memory_str = env::var("AWS_LAMBDA_FUNCTION_MEMORY_SIZE")?; - let parsed_memory_str = memory_str.parse::(); - let memory_size: i32; - match parsed_memory_str { - Ok(int_value) => memory_size = int_value, - Err(_parse_err) => { - error!( - "Memory value from environment is not i32: {}", - env::var("AWS_LAMBDA_FUNCTION_MEMORY_SIZE").unwrap() - ); - return Err(RuntimeError::unrecoverable(&format!( - "Could not parse memory value: {}", - memory_str - ))); - } - }; - - Ok(FunctionSettings { - function_name, - memory_size, - version, - log_stream, - log_group, - }) - } - - /// Loads the endpoint from Lambda's default environment variable: AWS_LAMBDA_RUNTIME_API - fn get_runtime_api_endpoint(&self) -> Result { - let endpoint = env::var(RUNTIME_ENDPOINT_VAR)?; - Ok(endpoint) - } -} - -#[cfg(test)] -pub(crate) mod tests { - use crate::{env::*, error}; - use std::{env, error::Error}; - - pub(crate) struct MockConfigProvider { - pub(crate) error: bool, - } - - impl ConfigProvider for MockConfigProvider { - fn get_function_settings(&self) -> Result { - if self.error { - return Err(error::RuntimeError::unrecoverable("Mock error")); - } - - Ok(FunctionSettings { - function_name: String::from("MockFunction"), - memory_size: 128, - version: String::from("$LATEST"), - log_stream: String::from("LogStream"), - log_group: String::from("LogGroup"), - }) - } - - fn get_runtime_api_endpoint(&self) -> Result { - if self.error { - return Err(error::RuntimeError::unrecoverable("Mock error")); - } - - Ok(String::from("http://localhost:8080")) - } - } - - fn set_endpoint_env_var() { - env::set_var(RUNTIME_ENDPOINT_VAR, "localhost:8080"); - } - - fn set_lambda_env_vars() { - env::set_var("AWS_LAMBDA_FUNCTION_NAME", "test_func"); - env::set_var("AWS_LAMBDA_FUNCTION_VERSION", "$LATEST"); - env::set_var("AWS_LAMBDA_LOG_STREAM_NAME", "LogStreamName"); - env::set_var("AWS_LAMBDA_LOG_GROUP_NAME", "LogGroup2"); - env::set_var("AWS_LAMBDA_FUNCTION_MEMORY_SIZE", "128"); - } - - fn unset_env_vars() { - env::remove_var(RUNTIME_ENDPOINT_VAR); - env::remove_var("AWS_LAMBDA_FUNCTION_NAME"); - env::remove_var("AWS_LAMBDA_FUNCTION_VERSION"); - env::remove_var("AWS_LAMBDA_LOG_STREAM_NAME"); - env::remove_var("AWS_LAMBDA_LOG_GROUP_NAME"); - env::remove_var("AWS_LAMBDA_FUNCTION_MEMORY_SIZE"); - } - - #[test] - fn function_config_from_env_vars() { - unset_env_vars(); - set_endpoint_env_var(); - set_lambda_env_vars(); - let config_provider: &dyn ConfigProvider = &EnvConfigProvider {}; - let env_settings = config_provider.get_function_settings(); - assert_eq!( - env_settings.is_err(), - false, - "Env settings returned an error: {}", - env_settings.err().unwrap().description() - ); - let settings = env_settings.unwrap(); - assert_eq!( - settings.memory_size, 128, - "Invalid memory size: {}", - settings.memory_size - ); - let endpoint = config_provider.get_runtime_api_endpoint(); - assert_eq!( - endpoint.is_err(), - false, - "Env endpoint returned an error: {}", - endpoint.err().unwrap().description() - ); - - unset_env_vars(); - let err_env_settings = config_provider.get_function_settings(); - assert!( - err_env_settings.is_err(), - "Env config did not return error without variables" - ); - let err_endpoint = config_provider.get_runtime_api_endpoint(); - assert!( - err_endpoint.is_err(), - "Env endpoint did not return error without variables" - ); - } -} diff --git a/lambda-runtime-core/src/error.rs b/lambda-runtime-core/src/error.rs deleted file mode 100644 index 152e1a41..00000000 --- a/lambda-runtime-core/src/error.rs +++ /dev/null @@ -1,98 +0,0 @@ -//! The error module defines the error types that can be returned -//! by custom handlers as well as the runtime itself. -use std::{env, error::Error, fmt}; - -use lambda_runtime_client::error::ApiError; -use lambda_runtime_errors::LambdaErrorExt; - -/// The `RuntimeError` object is returned by the custom runtime as it polls -/// for new events and tries to execute the handler function. The error -/// is primarily used by other methods within this crate and should not be relevant -/// to developers building Lambda functions. Handlers are expected to return -/// the `HandlerError` defined in this module. -#[derive(Debug, Clone)] -pub struct RuntimeError { - msg: String, - /// The request id that generated this error - pub(crate) request_id: Option, - /// Whether the error is recoverable or not. - pub(crate) recoverable: bool, -} - -impl RuntimeError { - /// Creates a new `RuntimeError` that is unrecoverable and it will cause the - /// runtime to panic in order to force a restart of the execution environment. - /// When a new `RuntimeError` is created the stack trace for the error is collected - /// automatically using the `backtrace` crate. - /// - /// # Arguments - /// - /// * `msg` The error message to be attached to the error. - /// - /// # Returns - /// A new `RuntimeError` instance with the `recoverable` property set to `false`. - pub(crate) fn unrecoverable(msg: &str) -> RuntimeError { - let mut new_error = RuntimeError::new(msg); - new_error.recoverable = false; - new_error - } - - /// Creates a new `RuntimeError` with the given properties. The stack trace for the - /// error is collected automatically using the `backtrace` crate. - /// - /// # Arguments - /// - /// * `msg` The error message - /// - /// # Returns - /// A new `RuntimeError` instance. - pub(crate) fn new(msg: &str) -> RuntimeError { - RuntimeError { - msg: String::from(msg), - recoverable: true, - request_id: None, - } - } -} - -impl LambdaErrorExt for RuntimeError { - fn error_type(&self) -> &str { - if self.recoverable { - "RecoverableRuntimeError" - } else { - "UnrecoverableRuntimeError" - } - } -} - -impl fmt::Display for RuntimeError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", self.msg) - } -} - -// This is important for other errors to wrap this one. -impl Error for RuntimeError { - fn description(&self) -> &str { - &self.msg - } - - fn cause(&self) -> Option<&dyn Error> { - // Generic error, underlying cause isn't tracked. - None - } -} - -impl From for RuntimeError { - fn from(e: env::VarError) -> Self { - RuntimeError::unrecoverable(e.description()) - } -} - -impl From for RuntimeError { - fn from(e: ApiError) -> Self { - let mut err = RuntimeError::new(&format!("{}", e)); - err.recoverable = e.is_recoverable(); - err - } -} diff --git a/lambda-runtime-core/src/handler.rs b/lambda-runtime-core/src/handler.rs deleted file mode 100644 index 41d2eff5..00000000 --- a/lambda-runtime-core/src/handler.rs +++ /dev/null @@ -1,20 +0,0 @@ -use crate::context::Context; -use failure::Fail; -use lambda_runtime_errors::LambdaErrorExt; -use std::fmt::Display; - -/// Functions acting as a handler must conform to this type. -pub trait Handler { - /// Run the handler. - fn run(&mut self, event: Vec, ctx: Context) -> Result, EventError>; -} - -impl<'ev, Function, EventError> Handler for Function -where - Function: FnMut(Vec, Context) -> Result, EventError>, - EventError: Fail + LambdaErrorExt + Display + Send + Sync, -{ - fn run(&mut self, event: Vec, ctx: Context) -> Result, EventError> { - (*self)(event, ctx) - } -} diff --git a/lambda-runtime-core/src/lib.rs b/lambda-runtime-core/src/lib.rs deleted file mode 100644 index 7a52c1d1..00000000 --- a/lambda-runtime-core/src/lib.rs +++ /dev/null @@ -1,25 +0,0 @@ -#![warn(missing_docs)] -#![deny(warnings)] -//! The Lambda runtime core crate implements [Lambda's custom runtime main loop](https://docs.aws.amazon.com/lambda/latest/dg/runtimes-custom.html#runtimes-custom-build). -//! The crate receives a `Handler` type that consumed events in the form of `Vec` and -//! outputs a `Result` with a `Vec` successful output. -//! -//! **Unless you have specific requirements to consume/produce raw bytes, you should look at the -//! [`lambda_runtime` crate](https://crates.io/crates/lambda_runtime)**. -//! -//! TODO: Add example - -mod context; -mod env; -mod error; -mod handler; -mod runtime; - -pub use crate::{ - context::Context, - env::{ConfigProvider, EnvConfigProvider}, - handler::Handler, - runtime::*, -}; - -pub use lambda_runtime_errors::{HandlerError, LambdaErrorExt, LambdaResultExt}; diff --git a/lambda-runtime-core/src/runtime.rs b/lambda-runtime-core/src/runtime.rs deleted file mode 100644 index 35357322..00000000 --- a/lambda-runtime-core/src/runtime.rs +++ /dev/null @@ -1,326 +0,0 @@ -use crate::{ - context::Context, - env::{ConfigProvider, EnvConfigProvider, FunctionSettings}, - error::RuntimeError, - handler::Handler, -}; -use failure::Fail; -use lambda_runtime_client::{error::ErrorResponse, RuntimeClient}; -use lambda_runtime_errors::LambdaErrorExt; -use log::*; -use std::{fmt::Display, marker::PhantomData}; -use tokio::runtime::Runtime as TokioRuntime; - -// include file generated during the build process -include!(concat!(env!("OUT_DIR"), "/metadata.rs")); - -const MAX_RETRIES: i8 = 3; - -/// Creates a new runtime and begins polling for events using Lambda's Runtime APIs. -/// -/// # Arguments -/// -/// * `f` A function pointer that conforms to the `Handler` type. -/// -/// # Panics -/// The function panics if the Lambda environment variables are not set. -pub fn start(f: impl Handler, runtime: Option) -where - EventError: Fail + LambdaErrorExt + Display + Send + Sync, -{ - start_with_config(f, &EnvConfigProvider::default(), runtime) -} - -#[macro_export] -/// Starts an event listener which will parse incoming events into the even type requested by -/// `handler` and will invoke `handler` on each incoming event. Can optionally be passed a Tokio -/// `runtime` to build the listener on. If none is provided, it creates its own. -macro_rules! lambda { - ($handler:ident) => { - $crate::start($handler, None) - }; - ($handler:ident, $runtime:expr) => { - $crate::start($handler, Some($runtime)) - }; - ($handler:expr) => { - $crate::start($handler, None) - }; - ($handler:expr, $runtime:expr) => { - $crate::start($handler, Some($runtime)) - }; -} - -/// Internal implementation of the start method that receives a config provider. This method -/// is used for unit tests with a mock provider. The provider data is used to construct the -/// `HttpRuntimeClient` which is then passed to the `start_with_runtime_client()` function. -/// -/// # Arguments -/// -/// * `f` A function pointer that conforms to the `Handler` type. -/// * `config` An implementation of the `ConfigProvider` trait with static lifetime. -/// -/// # Panics -/// The function panics if the `ConfigProvider` returns an error from the `get_runtime_api_endpoint()` -/// or `get_function_settings()` methods. The panic forces AWS Lambda to terminate the environment -/// and spin up a new one for the next invocation. -pub fn start_with_config( - f: impl Handler, - config: &Config, - runtime: Option, -) where - Config: ConfigProvider, - EventError: Fail + LambdaErrorExt + Display + Send + Sync, -{ - // if we cannot find the endpoint we panic, nothing else we can do. - let endpoint: String; - match config.get_runtime_api_endpoint() { - Ok(value) => endpoint = value, - Err(e) => { - panic!("Could not find runtime API env var: {}", e); - } - } - - // if we can't get the settings from the environment variable - // we also panic. - let function_config: FunctionSettings; - let settings = config.get_function_settings(); - match settings { - Ok(env_settings) => function_config = env_settings, - Err(e) => { - panic!("Could not find runtime API env var: {}", e); - } - } - - let info = Option::from(runtime_release().to_owned()); - - match RuntimeClient::new(&endpoint, info, runtime) { - Ok(client) => { - start_with_runtime_client(f, function_config, client); - } - Err(e) => { - panic!("Could not create runtime client SDK: {}", e); - } - } -} - -/// Starts the rust runtime with the given Runtime API client. -/// -/// # Arguments -/// -/// * `f` A function pointer that conforms to the `Handler` type. -/// * `client` An implementation of the `lambda_runtime_client::RuntimeClient` -/// trait with a lifetime that matches that of the environment, -/// in this case expressed as `'env`. -/// -/// # Panics -/// The function panics if we cannot instantiate a new `RustRuntime` object. -pub(crate) fn start_with_runtime_client( - f: impl Handler, - func_settings: FunctionSettings, - client: RuntimeClient, -) where - EventError: Fail + LambdaErrorExt + Display + Send + Sync, -{ - let mut lambda_runtime: Runtime<_, EventError> = Runtime::new(f, func_settings, MAX_RETRIES, client); - - // start the infinite loop - lambda_runtime.start(); -} - -/// Internal representation of the runtime object that polls for events and communicates -/// with the Runtime APIs -pub(super) struct Runtime { - runtime_client: RuntimeClient, - handler: Function, - max_retries: i8, - settings: FunctionSettings, - _phantom: PhantomData, -} - -// generic methods implementation -impl Runtime -where - Function: Handler, - EventError: Fail + LambdaErrorExt + Display + Send + Sync, -{ - /// Creates a new instance of the `Runtime` object populated with the environment - /// settings. - /// - /// # Arguments - /// - /// * `f` A function pointer that conforms to the `Handler` type. - /// * `retries` The maximum number of times we should retry calling the Runtime APIs - /// for recoverable errors while polling for new events. - /// - /// # Return - /// A `Result` for the `Runtime` object or a `errors::RuntimeSerror`. The runtime - /// fails the init if this function returns an error. If we cannot find the - /// `AWS_LAMBDA_RUNTIME_API` variable in the environment the function panics. - pub(super) fn new(f: Function, config: FunctionSettings, retries: i8, client: RuntimeClient) -> Self { - debug!( - "Creating new runtime with {} max retries for endpoint {}", - retries, - client.get_endpoint() - ); - - Runtime { - runtime_client: client, - settings: config, - handler: f, - max_retries: retries, - _phantom: PhantomData, - } - } -} - -// implementation of methods that require the Event and Output types -// to be compatible with `serde`'s Deserialize/Serialize. -impl Runtime -where - Function: Handler, - EventError: Fail + LambdaErrorExt + Display + Send + Sync, -{ - /// Starts the main event loop and begin polling or new events. If one of the - /// Runtime APIs returns an unrecoverable error this method calls the init failed - /// API and then panics. - fn start(&mut self) { - debug!("Beginning main event loop"); - loop { - let (event, ctx) = self.get_next_event(0, None); - let request_id = ctx.aws_request_id.clone(); - info!("Received new event with AWS request id: {}", request_id); - let function_outcome = self.invoke(event, ctx); - match function_outcome { - Ok(response) => { - debug!( - "Function executed succesfully for {}, pushing response to Runtime API", - request_id - ); - match self.runtime_client.event_response(&request_id, &response) { - Ok(_) => info!("Response for {} accepted by Runtime API", request_id), - // unrecoverable error while trying to communicate with the endpoint. - // we let the Lambda Runtime API know that we have died - Err(e) => { - error!("Could not send response for {} to Runtime API: {}", request_id, e); - if !e.is_recoverable() { - error!( - "Error for {} is not recoverable, sending fail_init signal and panicking.", - request_id - ); - self.runtime_client.fail_init(&ErrorResponse::from(e)); - panic!("Could not send response"); - } - } - } - } - Err(e) => { - error!("Handler returned an error for {}: {}", request_id, e); - debug!("Attempting to send error response to Runtime API for {}", request_id); - match self.runtime_client.event_error(&request_id, &ErrorResponse::from(e)) { - Ok(_) => info!("Error response for {} accepted by Runtime API", request_id), - Err(e) => { - error!("Unable to send error response for {} to Runtime API: {}", request_id, e); - if !e.is_recoverable() { - error!( - "Error for {} is not recoverable, sending fail_init signal and panicking", - request_id - ); - self.runtime_client.fail_init(&ErrorResponse::from(e)); - panic!("Could not send error response"); - } - } - } - } - } - } - } - - /// Invoke the handler function. This method is split out of the main loop to - /// make it testable. - pub(super) fn invoke(&mut self, e: Vec, ctx: Context) -> Result, EventError> { - (self.handler).run(e, ctx) - } - - /// Attempts to get the next event from the Runtime APIs and keeps retrying - /// unless the error throws is not recoverable. - /// - /// # Return - /// The next `Event` object to be processed. - pub(super) fn get_next_event(&self, retries: i8, e: Option) -> (Vec, Context) { - if let Some(err) = e { - if retries > self.max_retries { - error!("Unrecoverable error while fetching next event: {}", err); - match err.request_id.clone() { - Some(req_id) => { - self.runtime_client - .event_error(&req_id, &ErrorResponse::from(err)) - .expect("Could not send event error response"); - } - None => { - self.runtime_client.fail_init(&ErrorResponse::from(err)); - } - } - - // these errors are not recoverable. Either we can't communicate with the runtie APIs - // or we cannot parse the event. panic to restart the environment. - panic!("Could not retrieve next event"); - } - } - - match self.runtime_client.next_event() { - Ok((ev_data, invocation_ctx)) => { - let mut handler_ctx = Context::new(self.settings.clone()); - handler_ctx.invoked_function_arn = invocation_ctx.invoked_function_arn; - handler_ctx.aws_request_id = invocation_ctx.aws_request_id; - handler_ctx.xray_trace_id = invocation_ctx.xray_trace_id; - handler_ctx.client_context = invocation_ctx.client_context; - handler_ctx.identity = invocation_ctx.identity; - handler_ctx.deadline = invocation_ctx.deadline; - - (ev_data, handler_ctx) - } - Err(e) => self.get_next_event(retries + 1, Option::from(RuntimeError::from(e))), - } - } -} - -#[cfg(test)] -pub(crate) mod tests { - use super::*; - use crate::{context, env}; - use lambda_runtime_client::RuntimeClient; - use lambda_runtime_errors::HandlerError; - - #[test] - fn runtime_invokes_handler() { - let config: &dyn env::ConfigProvider = &env::tests::MockConfigProvider { error: false }; - let client = RuntimeClient::new( - &config - .get_runtime_api_endpoint() - .expect("Could not get runtime endpoint"), - None, - None, - ) - .expect("Could not initialize client"); - let handler = |_e: Vec, _c: context::Context| -> Result, HandlerError> { Ok(b"hello".to_vec()) }; - let retries: i8 = 3; - let mut runtime = Runtime::new( - handler, - config - .get_function_settings() - .expect("Could not load environment config"), - retries, - client, - ); - let output = runtime.invoke(b"test".to_vec(), context::tests::test_context(10)); - assert_eq!( - output.is_err(), - false, - "Handler threw an unexpected error: {}", - output.err().unwrap() - ); - let output_bytes = output.ok().unwrap(); - let output_string = String::from_utf8(output_bytes).unwrap(); - assert_eq!(output_string, "hello", "Unexpected output message: {}", output_string); - } -} diff --git a/lambda-runtime-errors-derive/Cargo.toml b/lambda-runtime-errors-derive/Cargo.toml deleted file mode 100644 index f7fe0e84..00000000 --- a/lambda-runtime-errors-derive/Cargo.toml +++ /dev/null @@ -1,24 +0,0 @@ -[package] -name = "lambda_runtime_errors_derive" -version = "0.1.1" -authors = ["Stefano Buliani", "David Barsky"] -edition = "2018" -description = "Rust runtime errors derive for AWS Lambda" -keywords = ["AWS", "Lambda", "Runtime", "Rust"] -license = "Apache-2.0" -homepage = "https://github.com/awslabs/aws-lambda-rust-runtime" -repository = "https://github.com/awslabs/aws-lambda-rust-runtime" -documentation = "https://docs.rs/lambda_runtime_errors_derive" - -[dependencies] -syn = "^0.15" -synstructure = "^0.10" -proc-macro2 = "^0.4" -quote = "^0.6" - -[dev-dependencies] -lambda_runtime_errors = { path = "../lambda-runtime-errors", version = "^0.1" } -failure = "^0.1.5" - -[lib] -proc-macro = true \ No newline at end of file diff --git a/lambda-runtime-errors-derive/src/lib.rs b/lambda-runtime-errors-derive/src/lib.rs deleted file mode 100644 index 4018ccb6..00000000 --- a/lambda-runtime-errors-derive/src/lib.rs +++ /dev/null @@ -1,23 +0,0 @@ -use proc_macro2::TokenStream; -use quote::quote; -use synstructure::decl_derive; - -decl_derive!([LambdaErrorExt, attributes()] => lambda_error_derive); - -fn lambda_error_derive(s: synstructure::Structure) -> TokenStream { - let name = format!("{}", s.ast().ident); - - let err_impl = s.gen_impl(quote! { - use lambda_runtime_errors::LambdaErrorExt; - - gen impl LambdaErrorExt for @Self { - fn error_type(&self) -> &str { - #name - } - } - }); - - (quote! { - #err_impl - }) -} diff --git a/lambda-runtime-errors-derive/tests/tests.rs b/lambda-runtime-errors-derive/tests/tests.rs deleted file mode 100644 index 2e4294a9..00000000 --- a/lambda-runtime-errors-derive/tests/tests.rs +++ /dev/null @@ -1,75 +0,0 @@ -use failure::{Backtrace, Context, Fail}; -use lambda_runtime_errors::LambdaErrorExt; -use std::fmt; - -#[derive(LambdaErrorExt)] -struct BasicCustomError; - -#[derive(Fail, LambdaErrorExt, Debug)] -#[fail(display = "Input was invalid UTF-8")] -struct FailureCustomError; - -#[derive(Debug, LambdaErrorExt)] -struct FailureCustomWithKind { - inner: Context, -} - -#[derive(Clone, Eq, PartialEq, Debug, Fail, LambdaErrorExt)] -enum FailureErrorKind { - #[fail(display = "First contextual error message.")] - FirstVariant, - #[fail(display = "Second contextual error message: {}.", _0)] - SecondVariant(String), -} - -impl Fail for FailureCustomWithKind { - fn cause(&self) -> Option<&dyn Fail> { - self.inner.cause() - } - - fn backtrace(&self) -> Option<&Backtrace> { - self.inner.backtrace() - } -} - -impl fmt::Display for FailureCustomWithKind { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::Display::fmt(&self.inner, f) - } -} - -impl FailureCustomWithKind { - pub fn kind(&self) -> FailureErrorKind { - self.inner.get_context().clone() - } -} - -impl From for FailureCustomWithKind { - fn from(kind: FailureErrorKind) -> Self { - FailureCustomWithKind { - inner: Context::new(kind), - } - } -} - -#[test] -fn simple_error_type() { - let err = BasicCustomError {}; - assert_eq!( - err.error_type(), - "BasicCustomError", - "Custom error not implemented correctly" - ); -} - -#[test] -fn fail_custom_error() { - let err = FailureCustomError {}; - assert_eq!(err.error_type(), "FailureCustomError", "Error type wrong") -} - -#[test] -fn fail_variant_first() { - let err = FailureCustomWithKind::from(FailureErrorKind::FirstVariant); - //assert_eq!(err.error_type(), "FailureCustomError", "Error type wrong") -} diff --git a/lambda-runtime-errors/Cargo.toml b/lambda-runtime-errors/Cargo.toml deleted file mode 100644 index a141187f..00000000 --- a/lambda-runtime-errors/Cargo.toml +++ /dev/null @@ -1,20 +0,0 @@ -[package] -name = "lambda_runtime_errors" -version = "0.1.1" -authors = ["Stefano Buliani", "David Barsky"] -edition = "2018" -description = "Rust runtime errors for AWS Lambda" -keywords = ["AWS", "Lambda", "Runtime", "Rust"] -license = "Apache-2.0" -homepage = "https://github.com/awslabs/aws-lambda-rust-runtime" -repository = "https://github.com/awslabs/aws-lambda-rust-runtime" -documentation = "https://docs.rs/lambda_runtime_errors" - -[dependencies] -log = "^0.4" -failure = "^0.1.5" -serde_json = "^1" -lambda_runtime_errors_derive = { path = "../lambda-runtime-errors-derive", version = "^0.1" } - -[dev-dependencies] -lambda_runtime_core = { path = "../lambda-runtime-core", version = "^0.1"} diff --git a/lambda-runtime-errors/errorgen.py b/lambda-runtime-errors/errorgen.py deleted file mode 100755 index 04538651..00000000 --- a/lambda-runtime-errors/errorgen.py +++ /dev/null @@ -1,142 +0,0 @@ -#!/usr/bin/env python3 - -# Generates the LambdaErrorExt implementation for all of the Errors -# in the standard library, excluding unstable APIs and errors that -# require generics. -# -# !! Please note this script is a hacky, short term solution !! -import os -from urllib.request import urlopen -from html.parser import HTMLParser - -RUST_ERROR_DOCS = "https://doc.rust-lang.org/std/error/trait.Error.html" -GENERATED_FILE_NAME = "./src/error_ext_impl.rs" -UNSTABLE_APIS = ["std::alloc::AllocErr", - "std::alloc::CannotReallocInPlace", - "std::char::CharTryFromError", - "std::num::TryFromIntError"] -GENERIC_ERRORS = ["std::sync::TryLockError", - "std::sync::PoisonError", - "std::sync::mpsc::TrySendError", - "std::sync::mpsc::SendError", - "std::io::IntoInnerError"] - - -class ErrorHtmlParser(HTMLParser): - def __init__(self): - super().__init__() - self.reset() - self.errors = [] - self.parsing = False - self.cur_error = self.empty_error() - - def handle_starttag(self, tag, attrs): - if self.parsing and tag == "a": - href = "" - if len(attrs) == 1: - href = attrs[0][1] - else: - href = attrs[1][1] - parts = href.split("/") - cnt = 0 - package = "" - for part in parts: - cnt = cnt + 1 - if part == "..": - continue - if cnt == len(parts): - break - - package += part + "::" - - if package.endswith("::"): - package = package[0:len(package) - 2] - self.cur_error["package"] = package - self.cur_error["href"] = href - - def empty_error(self): - return { - "package": "", - "name": "" - } - - def handle_data(self, data): - if data == " Error for " or data == "impl Error for ": - self.start_parsing() - else: - if self.parsing: - self.cur_error["name"] = data - if self.is_valid_error(self.cur_error): - self.errors.append(self.cur_error) - self.cur_error = self.empty_error - self.parsing = False - - def is_valid_error(self, err): - if err["name"] == "Box": - return False - if ".html" in err["package"]: - return False - if err["package"] == "": - return False - if err["package"] + "::" + err["name"] in UNSTABLE_APIS: - return False - if err["package"] + "::" + err["name"] in GENERIC_ERRORS: - return False - - return True - - def start_parsing(self): - if not self.parsing: - self.parsing = True - self.cur_error = self.empty_error() - else: - if self.cur_error["package"] == "" or self.cur_error["name"] == "": - print("Starting new error with empty existing error") - - -res = urlopen(RUST_ERROR_DOCS) -assert res.getcode() == 200, "Could not retrieve Rust error docs" - -error_docs_html = res.read() -assert error_docs_html != "", "Empty Error docs" - -parser = ErrorHtmlParser() -parser.feed(error_docs_html.decode()) - -print("found {} valid errors. Beginning code generation to {}".format( - len(parser.errors), GENERATED_FILE_NAME)) - -if os.path.isfile(GENERATED_FILE_NAME): - os.remove(GENERATED_FILE_NAME) - -# code gen -with open(GENERATED_FILE_NAME, "a") as f: - f.write("""// Generated code, DO NOT MODIFY! -// This file contains the implementation of the LambdaErrorExt -// trait for most of the standard library errors as well as the -// implementation of the From trait for the HandlerError struct -// to support the same standard library errors.\n\n""") - - # use statements - for err in parser.errors: - f.write("use {}::{};\n".format(err["package"], err["name"])) - f.write( - "use crate::{LambdaErrorExt, HandlerError};\n\n") - - # impl for LambdaErrorExt for the standard library errors - for err in parser.errors: - f.write("""impl LambdaErrorExt for {} {{ - fn error_type(&self) -> &str {{ - "{}::{}" - }} -}}\n""".format(err["name"], err["package"], err["name"])) - - # impl From trait for standard library errors to HandlerError - for err in parser.errors: - f.write("""impl From<{}> for HandlerError {{ - fn from(e: {}) -> Self {{ - HandlerError::new(e) - }} -}}\n""".format(err["name"], err["name"])) - - f.close() diff --git a/lambda-runtime-errors/src/error_ext_impl.rs b/lambda-runtime-errors/src/error_ext_impl.rs deleted file mode 100644 index 04a46a6a..00000000 --- a/lambda-runtime-errors/src/error_ext_impl.rs +++ /dev/null @@ -1,252 +0,0 @@ -// Generated code, DO NOT MODIFY! -// This file contains the implementation of the LambdaErrorExt -// trait for most of the standard library errors as well as the -// implementation of the From trait for the HandlerError struct -// to support the same standard library errors. - -use crate::{HandlerError, LambdaErrorExt}; -use std::{ - alloc::LayoutErr, - cell::{BorrowError, BorrowMutError}, - char::{DecodeUtf16Error, ParseCharError}, - env::{JoinPathsError, VarError}, - ffi::{FromBytesWithNulError, IntoStringError, NulError}, - net::AddrParseError, - num::{ParseFloatError, ParseIntError}, - path::StripPrefixError, - str::{ParseBoolError, Utf8Error}, - string::{FromUtf16Error, FromUtf8Error, ParseError}, - sync::mpsc::{RecvError, RecvTimeoutError, TryRecvError}, - time::SystemTimeError, -}; - -impl LambdaErrorExt for VarError { - fn error_type(&self) -> &str { - "std::env::VarError" - } -} -impl LambdaErrorExt for ParseError { - fn error_type(&self) -> &str { - "std::string::ParseError" - } -} -impl LambdaErrorExt for RecvTimeoutError { - fn error_type(&self) -> &str { - "std::sync::mpsc::RecvTimeoutError" - } -} -impl LambdaErrorExt for TryRecvError { - fn error_type(&self) -> &str { - "std::sync::mpsc::TryRecvError" - } -} -impl LambdaErrorExt for LayoutErr { - fn error_type(&self) -> &str { - "std::alloc::LayoutErr" - } -} -impl LambdaErrorExt for BorrowError { - fn error_type(&self) -> &str { - "std::cell::BorrowError" - } -} -impl LambdaErrorExt for BorrowMutError { - fn error_type(&self) -> &str { - "std::cell::BorrowMutError" - } -} -impl LambdaErrorExt for DecodeUtf16Error { - fn error_type(&self) -> &str { - "std::char::DecodeUtf16Error" - } -} -impl LambdaErrorExt for ParseCharError { - fn error_type(&self) -> &str { - "std::char::ParseCharError" - } -} -impl LambdaErrorExt for JoinPathsError { - fn error_type(&self) -> &str { - "std::env::JoinPathsError" - } -} -impl LambdaErrorExt for FromBytesWithNulError { - fn error_type(&self) -> &str { - "std::ffi::FromBytesWithNulError" - } -} -impl LambdaErrorExt for IntoStringError { - fn error_type(&self) -> &str { - "std::ffi::IntoStringError" - } -} -impl LambdaErrorExt for NulError { - fn error_type(&self) -> &str { - "std::ffi::NulError" - } -} -impl LambdaErrorExt for AddrParseError { - fn error_type(&self) -> &str { - "std::net::AddrParseError" - } -} -impl LambdaErrorExt for ParseFloatError { - fn error_type(&self) -> &str { - "std::num::ParseFloatError" - } -} -impl LambdaErrorExt for ParseIntError { - fn error_type(&self) -> &str { - "std::num::ParseIntError" - } -} -impl LambdaErrorExt for StripPrefixError { - fn error_type(&self) -> &str { - "std::path::StripPrefixError" - } -} -impl LambdaErrorExt for ParseBoolError { - fn error_type(&self) -> &str { - "std::str::ParseBoolError" - } -} -impl LambdaErrorExt for Utf8Error { - fn error_type(&self) -> &str { - "std::str::Utf8Error" - } -} -impl LambdaErrorExt for FromUtf16Error { - fn error_type(&self) -> &str { - "std::string::FromUtf16Error" - } -} -impl LambdaErrorExt for FromUtf8Error { - fn error_type(&self) -> &str { - "std::string::FromUtf8Error" - } -} -impl LambdaErrorExt for RecvError { - fn error_type(&self) -> &str { - "std::sync::mpsc::RecvError" - } -} -impl LambdaErrorExt for SystemTimeError { - fn error_type(&self) -> &str { - "std::time::SystemTimeError" - } -} -impl From for HandlerError { - fn from(e: VarError) -> Self { - HandlerError::new(e) - } -} -impl From for HandlerError { - fn from(e: ParseError) -> Self { - HandlerError::new(e) - } -} -impl From for HandlerError { - fn from(e: RecvTimeoutError) -> Self { - HandlerError::new(e) - } -} -impl From for HandlerError { - fn from(e: TryRecvError) -> Self { - HandlerError::new(e) - } -} -impl From for HandlerError { - fn from(e: LayoutErr) -> Self { - HandlerError::new(e) - } -} -impl From for HandlerError { - fn from(e: BorrowError) -> Self { - HandlerError::new(e) - } -} -impl From for HandlerError { - fn from(e: BorrowMutError) -> Self { - HandlerError::new(e) - } -} -impl From for HandlerError { - fn from(e: DecodeUtf16Error) -> Self { - HandlerError::new(e) - } -} -impl From for HandlerError { - fn from(e: ParseCharError) -> Self { - HandlerError::new(e) - } -} -impl From for HandlerError { - fn from(e: JoinPathsError) -> Self { - HandlerError::new(e) - } -} -impl From for HandlerError { - fn from(e: FromBytesWithNulError) -> Self { - HandlerError::new(e) - } -} -impl From for HandlerError { - fn from(e: IntoStringError) -> Self { - HandlerError::new(e) - } -} -impl From for HandlerError { - fn from(e: NulError) -> Self { - HandlerError::new(e) - } -} -impl From for HandlerError { - fn from(e: AddrParseError) -> Self { - HandlerError::new(e) - } -} -impl From for HandlerError { - fn from(e: ParseFloatError) -> Self { - HandlerError::new(e) - } -} -impl From for HandlerError { - fn from(e: ParseIntError) -> Self { - HandlerError::new(e) - } -} -impl From for HandlerError { - fn from(e: StripPrefixError) -> Self { - HandlerError::new(e) - } -} -impl From for HandlerError { - fn from(e: ParseBoolError) -> Self { - HandlerError::new(e) - } -} -impl From for HandlerError { - fn from(e: Utf8Error) -> Self { - HandlerError::new(e) - } -} -impl From for HandlerError { - fn from(e: FromUtf16Error) -> Self { - HandlerError::new(e) - } -} -impl From for HandlerError { - fn from(e: FromUtf8Error) -> Self { - HandlerError::new(e) - } -} -impl From for HandlerError { - fn from(e: RecvError) -> Self { - HandlerError::new(e) - } -} -impl From for HandlerError { - fn from(e: SystemTimeError) -> Self { - HandlerError::new(e) - } -} diff --git a/lambda-runtime-errors/src/lib.rs b/lambda-runtime-errors/src/lib.rs deleted file mode 100644 index 13881331..00000000 --- a/lambda-runtime-errors/src/lib.rs +++ /dev/null @@ -1,199 +0,0 @@ -//! The Lambda runtime errors crate defines the `LambdaErrorExt` trait -//! that can be used by libriaries to return errors compatible with the -//! AWS Lambda Rust runtime. -//! -//! This crate also exports the `lambda_runtime_errors_derive` crate to -//! derive the `LambdaErrorExt` trait. -//! -//! ```rust,no-run -//! use lambda_runtime_errors::*; -//! -//! // the generated error_type() method returns "crate::LambdaError" -//! #[derive(LambdaErrorExt)] -//! struct LambdaError; -//! ``` -mod error_ext_impl; - -pub use crate::error_ext_impl::*; -pub use lambda_runtime_errors_derive::*; - -use failure::{format_err, Compat, Error, Fail}; -use std::fmt; - -/// The `LambdaErrorExt` trait defines the `error_type()` method used -/// by the AWS Lambda runtime client to generate `ErrorResponse` -/// objects. The value returned by the `error_type()` method is used to -/// populate the `errorType` field in the Lambda response. This crate -/// includes an implementation of this trait for most errors in the -/// standard library. By default, error return their type name. -pub trait LambdaErrorExt { - /// The value for this field should be an alphanumeric unique identifier - /// of the error type. For example `MyCustomError`. - /// - /// # Return - /// An alphanumeric identifier for the error - fn error_type(&self) -> &str; -} - -impl LambdaErrorExt for Error { - fn error_type(&self) -> &str { - self.find_root_cause().name().unwrap_or_else(|| "FailureError") - } -} - -// We implement this trait here so that we can use the Compat type -// in the lambda-runtime crate - heaps of fun between failure and std::error -impl LambdaErrorExt for Compat { - fn error_type(&self) -> &str { - "CompatFailureError" - } -} - -/// `Result` type extension for AWS that makes it easy to generate a `HandlerError` -/// object or a `Compat` from the failure crate using an existing result. -/// This trait should be imported from the `lambda_runtime_core` or `lambda_runtime` -/// crates. -pub trait LambdaResultExt { - /// Takes the incoming `Result` and maps it to a Result that returns an `HandlerError` object. - /// The `HandlerError` type already includes implementations of the `From` trait for most - /// standard library errors. This method is intended to be used when a the `From` trait is not - /// implemented. - /// - /// # Example - /// - /// ```rust,no_run - /// use lambda_runtime_core::{Context, LambdaResultExt, HandlerError, lambda}; - /// use std::error::Error as StdError; - /// - /// fn main() -> Result<(), Box> { - /// lambda!(my_handler); - /// Ok(()) - /// } - /// - /// fn my_handler(_event: Vec, _ctx: Context) -> Result, HandlerError> { - /// let age = "hello"; // this will throw an error when we try to parse it into an int - /// age.parse::().handler_error()?; - /// - /// Ok(vec!()) - /// } - /// ``` - fn handler_error(self) -> Result; - - /// Takes the incoming result and converts it into an `Error` type from the `failure` crate - /// wrapped in a `Compat` object to make it implement the `Error` trait from the standard - /// library. This method makes it easy to write handler functions that return `Compat` - /// directly. - /// - /// # Example - /// - /// ```rust,no_run - /// use lambda_runtime_core::{Context, LambdaResultExt, lambda}; - /// use failure::{Error, Compat}; - /// use std::error::Error as StdError; - /// - /// fn main() -> Result<(), Box> { - /// lambda!(my_handler); - /// Ok(()) - /// } - /// - /// fn my_handler(_event: Vec, _ctx: Context) -> Result, Compat> { - /// let age = "hello"; // this will throw an error when we try to parse it into an int - /// age.parse::().failure_compat()?; - /// Ok(vec!()) - /// } - /// ``` - fn failure_compat(self) -> Result>; -} - -impl LambdaResultExt for Result -where - ERR: Fail + LambdaErrorExt, -{ - fn handler_error(self) -> Result { - self.map_err(HandlerError::new) - } - - fn failure_compat(self) -> Result> { - self.map_err(|err| Error::from(err).compat()) - } -} - -/// The `HandlerError` struct can be use to abstract any `Err` of the handler method `Result`. -/// The `HandlerError` object can be generated `From` any object that supports `Display`, -/// `Send, `Sync`, and `Debug`. This allows handler functions to return any error using -/// the `?` syntax. For example `let _age_num: u8 = e.age.parse()?;` will return the -/// `::Err` from the handler function. -//pub type HandlerError = failure::Error; -#[derive(Debug)] -pub struct HandlerError { - err_type: String, - inner: failure::Error, -} -impl HandlerError { - pub fn new(e: T) -> Self { - let err_type = e.error_type().to_owned(); - HandlerError { - err_type, - inner: failure::Error::from(e), - } - } -} -impl std::error::Error for HandlerError {} -impl fmt::Display for HandlerError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}: {}", self.err_type, self.inner.find_root_cause()) - } -} -impl LambdaErrorExt for HandlerError { - fn error_type(&self) -> &str { - &self.err_type - } -} -impl From<&str> for HandlerError { - fn from(s: &str) -> Self { - HandlerError { - err_type: "UnknownError".to_owned(), - inner: format_err!("{}", s), - } - } -} -impl From for HandlerError { - fn from(e: failure::Error) -> Self { - let error_type = e.error_type(); - HandlerError { - err_type: error_type.to_owned(), - inner: e, - } - } -} -impl From for HandlerError { - fn from(e: serde_json::error::Error) -> Self { - HandlerError { - err_type: "JsonError".to_owned(), - inner: failure::Error::from(e), - } - } -} - -#[cfg(test)] -pub(crate) mod tests { - use super::*; - use failure::Fail; - - #[derive(Fail, Debug)] - #[fail(display = "Custom Error")] - struct CustomError; - - #[test] - fn std_error_type() { - let parsed_int = "hello".parse::(); - let err = HandlerError::from(parsed_int.err().unwrap()); - assert_eq!(err.error_type(), "std::num::ParseIntError"); - } - - #[test] - fn error_type_from_failure() { - let err = HandlerError::from(failure::Error::from(CustomError {})); - assert_eq!(err.error_type(), "lambda_runtime_errors::tests::CustomError"); - } -} diff --git a/lambda-runtime/Cargo.toml b/lambda-runtime/Cargo.toml deleted file mode 100644 index 1120c8f3..00000000 --- a/lambda-runtime/Cargo.toml +++ /dev/null @@ -1,29 +0,0 @@ -[package] -name = "lambda_runtime" -version = "0.2.1" -authors = ["Stefano Buliani", "David Barsky"] -edition = "2018" -description = "Rust runtime for AWS Lambda" -keywords = ["AWS", "Lambda", "Runtime", "Rust"] -license = "Apache-2.0" -homepage = "https://github.com/awslabs/aws-lambda-rust-runtime" -repository = "https://github.com/awslabs/aws-lambda-rust-runtime" -documentation = "https://docs.rs/lambda_runtime" -readme = "../README.md" - -[badges] -travis-ci = { repository = "awslabs/aws-lambda-rust-runtime" } -maintenance = { status = "actively-developed" } - -[dependencies] -serde = "^1" -serde_json = "^1" -serde_derive = "^1" -tokio = "0.1" -log = "^0.4" -lambda_runtime_core = { path = "../lambda-runtime-core", version = "^0.1" } -failure = "^0.1" - -[dev-dependencies] -simple_logger = "^1" -simple-error = "^0.1" diff --git a/lambda-runtime/examples/basic.rs b/lambda-runtime/examples/basic.rs deleted file mode 100644 index 1a64f628..00000000 --- a/lambda-runtime/examples/basic.rs +++ /dev/null @@ -1,36 +0,0 @@ -use std::error::Error; - -use lambda_runtime::{error::HandlerError, lambda, Context}; -use log::{self, error}; -use serde_derive::{Deserialize, Serialize}; -use simple_error::bail; -use simple_logger; - -#[derive(Deserialize)] -struct CustomEvent { - #[serde(rename = "firstName")] - first_name: String, -} - -#[derive(Serialize)] -struct CustomOutput { - message: String, -} - -fn main() -> Result<(), Box> { - simple_logger::init_with_level(log::Level::Debug)?; - lambda!(my_handler); - - Ok(()) -} - -fn my_handler(e: CustomEvent, c: Context) -> Result { - if e.first_name == "" { - error!("Empty first name in request {}", c.aws_request_id); - bail!("Empty first name"); - } - - Ok(CustomOutput { - message: format!("Hello, {}!", e.first_name), - }) -} diff --git a/lambda-runtime/examples/custom_error.rs b/lambda-runtime/examples/custom_error.rs deleted file mode 100644 index 35f0c0dd..00000000 --- a/lambda-runtime/examples/custom_error.rs +++ /dev/null @@ -1,70 +0,0 @@ -use lambda_runtime::{error::LambdaErrorExt, lambda, Context}; -use log::error; -use serde_derive::{Deserialize, Serialize}; -use std::{error::Error, fmt}; - -#[derive(Debug)] -struct CustomError { - msg: String, -} -impl CustomError { - fn new(message: &str) -> CustomError { - CustomError { - msg: message.to_owned(), - } - } -} -impl fmt::Display for CustomError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", self.msg) - } -} -impl Error for CustomError {} -impl From for CustomError { - fn from(i: std::num::ParseIntError) -> Self { - CustomError::new(&format!("{}", i)) - } -} -// the value return by the error_type function is included as the -// `errorType` in the AWS Lambda response -impl LambdaErrorExt for CustomError { - fn error_type(&self) -> &str { - "CustomError" - } -} - -#[derive(Deserialize)] -struct CustomEvent { - #[serde(rename = "firstName")] - first_name: String, - age: String, -} - -#[derive(Serialize)] -struct CustomOutput { - message: String, -} - -fn main() -> Result<(), Box> { - simple_logger::init_with_level(log::Level::Debug)?; - lambda!(my_handler); - - Ok(()) -} - -fn my_handler(e: CustomEvent, c: Context) -> Result { - if e.first_name == "" { - error!("Empty first name in request {}", c.aws_request_id); - // in this case, we explicitly initialize and box our custom error type. - // the HandlerError type is an alias to Box/ - return Err(CustomError::new("Empty first name")); - } - - // For errors simply want to return, because the HandlerError is an alias to any - // generic error type, we can propapgate with the standard "?" syntax. - let _age_num: u8 = e.age.parse()?; - - Ok(CustomOutput { - message: format!("Hello, {}!", e.first_name), - }) -} diff --git a/lambda-runtime/examples/custom_error_failure.rs b/lambda-runtime/examples/custom_error_failure.rs deleted file mode 100644 index 8e8c33e8..00000000 --- a/lambda-runtime/examples/custom_error_failure.rs +++ /dev/null @@ -1,51 +0,0 @@ -use failure::Fail; -use lambda_runtime::{error::LambdaErrorExt, lambda, Context}; -use log::error; -use serde_derive::{Deserialize, Serialize}; -use std::error::Error as StdError; - -#[derive(Fail, Debug)] -#[fail(display = "Custom Error")] -struct CustomError; -impl LambdaErrorExt for CustomError { - fn error_type(&self) -> &str { - "CustomError" - } -} -impl From for CustomError { - fn from(_i: std::num::ParseIntError) -> Self { - CustomError {} - } -} - -#[derive(Deserialize)] -struct CustomEvent { - #[serde(rename = "firstName")] - first_name: String, - age: String, -} - -#[derive(Serialize)] -struct CustomOutput { - message: String, -} - -fn main() -> Result<(), Box> { - simple_logger::init_with_level(log::Level::Debug)?; - lambda!(my_handler); - - Ok(()) -} - -fn my_handler(e: CustomEvent, c: Context) -> Result { - if e.first_name == "" { - error!("Empty first name in request {}", c.aws_request_id); - return Err(CustomError {}); - } - - let _age_num: u8 = e.age.parse()?; - - Ok(CustomOutput { - message: format!("Hello, {}!", e.first_name), - }) -} diff --git a/lambda-runtime/examples/failure_error.rs b/lambda-runtime/examples/failure_error.rs deleted file mode 100644 index b426ecb2..00000000 --- a/lambda-runtime/examples/failure_error.rs +++ /dev/null @@ -1,38 +0,0 @@ -use failure::{format_err, Compat, Error}; -use lambda_runtime::{error::LambdaResultExt, lambda, Context}; -use log::error; -use serde_derive::{Deserialize, Serialize}; -use std::error::Error as StdError; - -#[derive(Deserialize)] -struct CustomEvent { - #[serde(rename = "firstName")] - first_name: String, - age: String, -} - -#[derive(Serialize)] -struct CustomOutput { - message: String, -} - -fn main() -> Result<(), Box> { - simple_logger::init_with_level(log::Level::Debug)?; - lambda!(my_handler); - - Ok(()) -} - -fn my_handler(e: CustomEvent, c: Context) -> Result> { - if e.first_name == "" { - error!("Empty first name in request {}", c.aws_request_id); - let err = format_err!("Invalid First Name"); - return Err(err.compat()); - } - - let _age_num: u8 = e.age.parse().failure_compat()?; - - Ok(CustomOutput { - message: format!("Hello, {}!", e.first_name), - }) -} diff --git a/lambda-runtime/examples/with_custom_runtime.rs b/lambda-runtime/examples/with_custom_runtime.rs deleted file mode 100644 index d0e6a0b7..00000000 --- a/lambda-runtime/examples/with_custom_runtime.rs +++ /dev/null @@ -1,38 +0,0 @@ -use lambda_runtime::{error::HandlerError, lambda, Context}; -use log::{self, error}; -use serde_derive::{Deserialize, Serialize}; -use simple_error::bail; -use simple_logger; -use std::error::Error; -use tokio::runtime::Runtime; - -#[derive(Deserialize, Clone)] -struct CustomEvent { - #[serde(rename = "firstName")] - first_name: String, -} - -#[derive(Serialize, Clone)] -struct CustomOutput { - message: String, -} - -fn main() -> Result<(), Box> { - let rt = Runtime::new()?; - - simple_logger::init_with_level(log::Level::Debug)?; - lambda!(my_handler, rt); - - Ok(()) -} - -fn my_handler(e: CustomEvent, c: Context) -> Result { - if e.first_name == "" { - error!("Empty first name in request {}", c.aws_request_id); - bail!("Empty first name"); - } - - Ok(CustomOutput { - message: format!("Hello, {}!", e.first_name), - }) -} diff --git a/lambda-runtime/src/lib.rs b/lambda-runtime/src/lib.rs deleted file mode 100644 index 2ef78f4e..00000000 --- a/lambda-runtime/src/lib.rs +++ /dev/null @@ -1,219 +0,0 @@ -#![warn(missing_docs)] -#![deny(warnings)] -//! Lambda runtime makes it easy to run Rust code inside AWS Lambda. To create -//! Lambda function with this library simply include it as a dependency, make -//! sure that you declare a function that respects the `Handler` type, and call -//! the `start()` function from your main method. The executable in your deployment -//! package must be called `bootstrap`. -//! -//! ```rust,no_run -//! use lambda_runtime::{error::HandlerError, lambda, Context}; -//! use simple_error::bail; -//! use serde_derive::{Serialize, Deserialize}; -//! -//! #[derive(Deserialize, Clone)] -//! struct CustomEvent { -//! first_name: String, -//! last_name: String, -//! } -//! -//! #[derive(Serialize, Clone)] -//! struct CustomOutput { -//! message: String, -//! } -//! -//! fn main() { -//! lambda!(my_handler); -//! } -//! -//! fn my_handler(e: CustomEvent, ctx: Context) -> Result { -//! if e.first_name == "" { -//! bail!("Empty first name"); -//! } -//! Ok(CustomOutput{ -//! message: format!("Hello, {}!", e.first_name), -//! }) -//! } -//! ``` -use failure::Fail; -use lambda_runtime_core::{start_with_config, EnvConfigProvider, HandlerError, LambdaErrorExt}; -use serde; -use serde_json; -use std::fmt::Display; -use tokio::runtime::Runtime as TokioRuntime; - -pub use lambda_runtime_core::Context; - -/// The error module exposes the HandlerError type. -pub mod error { - pub use lambda_runtime_core::{HandlerError, LambdaErrorExt, LambdaResultExt}; -} - -/// Functions acting as a handler must conform to this type. -pub trait Handler { - /// Method to execute the handler function - fn run(&mut self, event: Event, ctx: Context) -> Result; -} - -/// Implementation of the `Handler` trait for both function pointers -/// and closures. -impl Handler for Function -where - Function: FnMut(Event, Context) -> Result, - EventError: Fail + LambdaErrorExt + Display + Send + Sync, -{ - fn run(&mut self, event: Event, ctx: Context) -> Result { - (*self)(event, ctx) - } -} - -/// Wraps a typed handler into a closure that complies with the `Handler` trait -/// defined in the `lambda_runtime_core` crate. The closure simply uses `serde_json` -/// to serialize and deserialize the incoming event from a `Vec` and the output -/// to a `Vec`. -fn wrap( - mut h: impl Handler, -) -> impl FnMut(Vec, Context) -> Result, HandlerError> -where - Event: serde::de::DeserializeOwned, - Output: serde::Serialize, - EventError: Fail + LambdaErrorExt + Display + Send + Sync, -{ - move |ev, ctx| { - let event: Event = serde_json::from_slice(&ev)?; - match h.run(event, ctx) { - Ok(out) => { - let out_bytes = serde_json::to_vec(&out)?; - Ok(out_bytes) - } - Err(e) => Err(HandlerError::new(e)), - } - } -} - -/// Creates a new runtime and begins polling for events using Lambda's Runtime APIs. -/// -/// # Arguments -/// -/// * `f` A function pointer that conforms to the `Handler` type. -/// -/// # Panics -/// The function panics if the Lambda environment variables are not set. -pub fn start(f: impl Handler, runtime: Option) -where - Event: serde::de::DeserializeOwned, - Output: serde::Serialize, - EventError: Fail + LambdaErrorExt + Display + Send + Sync, -{ - let wrapped = wrap(f); - start_with_config(wrapped, &EnvConfigProvider::default(), runtime) -} - -/// Initializes the Lambda runtime with the given handler. Optionally this macro can -/// also receive a customized instance of Tokio runtime to drive internal lambda operations -/// to completion -#[macro_export] -macro_rules! lambda { - ($handler:ident) => { - $crate::start($handler, None) - }; - ($handler:ident, $runtime:expr) => { - $crate::start($handler, Some($runtime)) - }; - ($handler:expr) => { - $crate::start($handler, None) - }; - ($handler:expr, $runtime:expr) => { - $crate::start($handler, Some($runtime)) - }; -} - -#[cfg(test)] -pub(crate) mod tests { - use super::*; - use lambda_runtime_core::Context; - use serde_derive::{Deserialize, Serialize}; - use serde_json; - - fn test_context() -> Context { - Context { - memory_limit_in_mb: 128, - function_name: "test_func".to_string(), - function_version: "$LATEST".to_string(), - invoked_function_arn: "arn:aws:lambda".to_string(), - aws_request_id: "123".to_string(), - xray_trace_id: Some("123".to_string()), - log_stream_name: "logStream".to_string(), - log_group_name: "logGroup".to_string(), - client_context: Option::default(), - identity: Option::default(), - deadline: 0, - } - } - - #[derive(Serialize, Deserialize)] - struct Input { - name: String, - } - - #[derive(Serialize, Deserialize)] - struct Output { - msg: String, - } - - #[test] - fn runtime_invokes_handler() { - let handler_ok = |_e: Input, _c: Context| -> Result { - Ok(Output { - msg: "hello".to_owned(), - }) - }; - let mut wrapped_ok = wrap(handler_ok); - let input = Input { - name: "test".to_owned(), - }; - let output = wrapped_ok.run( - serde_json::to_vec(&input).expect("Could not convert input to Vec"), - test_context(), - ); - assert_eq!( - output.is_err(), - false, - "Handler threw an unexpected error: {}", - output.err().unwrap() - ); - let output_obj: Output = serde_json::from_slice(&output.ok().unwrap()).expect("Could not serialize output"); - assert_eq!( - output_obj.msg, - "hello".to_owned(), - "Unexpected output message: {}", - output_obj.msg - ); - } - - #[test] - fn runtime_captures_error() { - let handler_ok = |e: Input, _c: Context| -> Result { - let _age = e.name.parse::()?; - Ok(Output { - msg: "hello".to_owned(), - }) - }; - let mut wrapped_ok = wrap(handler_ok); - let input = Input { - name: "test".to_owned(), - }; - let output = wrapped_ok.run( - serde_json::to_vec(&input).expect("Could not convert input to Vec"), - test_context(), - ); - assert_eq!(output.is_err(), true, "Handler did not throw an error"); - let err = output.err().unwrap(); - assert_eq!( - err.error_type(), - "std::num::ParseIntError", - "Unexpected error_type: {}", - err.error_type() - ); - } -} diff --git a/lambda/Cargo.toml b/lambda/Cargo.toml new file mode 100644 index 00000000..e7a96f1b --- /dev/null +++ b/lambda/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "lambda" +version = "0.1.0" +authors = ["David Barsky "] +edition = "2018" + +[dependencies] +tokio = { version = "0.2.4", features = ["full"] } +hyper = "0.13" +serde = { version = "1", features = ["derive"] } +serde_json = "1.0.39" +tower-service = "0.3" +bytes = "0.5" +http = "0.2" +lambda-attributes = { path = "../lambda-attributes", version = "0.1.0" } +futures = "0.3.1" diff --git a/lambda/examples/hello-with-ctx.rs b/lambda/examples/hello-with-ctx.rs new file mode 100644 index 00000000..58549494 --- /dev/null +++ b/lambda/examples/hello-with-ctx.rs @@ -0,0 +1,9 @@ +use lambda::lambda; + +type Error = Box; + +#[lambda] +#[tokio::main] +async fn main(event: String) -> Result { + Ok(event) +} diff --git a/lambda/examples/hello-without-macro.rs b/lambda/examples/hello-without-macro.rs new file mode 100644 index 00000000..e5ab866b --- /dev/null +++ b/lambda/examples/hello-without-macro.rs @@ -0,0 +1,14 @@ +use lambda::handler_fn; + +type Error = Box; + +#[tokio::main] +async fn main() -> Result<(), Error> { + let func = handler_fn(func); + lambda::run(func).await?; + Ok(()) +} + +async fn func(event: String) -> Result { + Ok(event) +} diff --git a/lambda/examples/hello.rs b/lambda/examples/hello.rs new file mode 100644 index 00000000..58549494 --- /dev/null +++ b/lambda/examples/hello.rs @@ -0,0 +1,9 @@ +use lambda::lambda; + +type Error = Box; + +#[lambda] +#[tokio::main] +async fn main(event: String) -> Result { + Ok(event) +} diff --git a/lambda/src/client.rs b/lambda/src/client.rs new file mode 100644 index 00000000..c58a4cd3 --- /dev/null +++ b/lambda/src/client.rs @@ -0,0 +1,304 @@ +use crate::{ + requests::{IntoResponse, NextEventResponse}, + types::Diagnostic, + Err, +}; +use bytes::buf::ext::BufExt; +use futures::future; +use http::{ + uri::{PathAndQuery, Scheme}, + HeaderValue, Method, Request, Response, StatusCode, Uri, +}; +use hyper::Body; +use serde_json::json; +use std::{ + convert::{TryFrom, TryInto}, + future::Future, + pin::Pin, + task::{Context, Poll}, +}; +use tower_service::Service; + +type Fut<'a, T> = Pin + 'a + Send>>; + +#[derive(Debug, Clone)] +pub(crate) struct Client { + base: Uri, + client: S, +} + +impl Client +where + S: Service, Response = Response>, + S::Error: std::error::Error + Send + Sync + 'static, +{ + pub fn with(base: T, client: S) -> Result + where + T: TryInto, + >::Error: std::error::Error + Send + Sync + 'static, + { + let base = base.try_into()?; + Ok(Self { base, client }) + } + + fn set_origin(&self, req: Request) -> Result, Err> { + let (mut parts, body) = req.into_parts(); + let (scheme, authority) = { + let scheme = self.base.scheme().unwrap_or(&Scheme::HTTP); + let authority = self.base.authority().expect("Authority not found"); + (scheme, authority) + }; + let path = parts.uri.path_and_query().expect("PathAndQuery not found"); + + let uri = Uri::builder() + .scheme(scheme.clone()) + .authority(authority.clone()) + .path_and_query(path.clone()) + .build() + .expect("Unable to build URI"); + + parts.uri = uri; + Ok(Request::from_parts(parts, body)) + } + + pub(crate) async fn call(&mut self, req: Request) -> Result, Err> { + let req = self.set_origin(req)?; + let (parts, body) = req.into_parts(); + let body = Body::from(body); + let req = Request::from_parts(parts, body); + let response = self.client.call(req).await?; + Ok(response) + } +} + +pub struct EndpointSvc; + +impl Service> for EndpointSvc { + type Response = Response; + type Error = crate::Err; + type Future = Fut<'static, Result>; + + fn poll_ready(&mut self, _: &mut Context<'_>) -> Poll> { + Poll::Ready(Ok(())) + } + + fn call(&mut self, req: Request) -> Self::Future { + let fut = async move { + let path: Vec<&str> = req + .uri() + .path_and_query() + .unwrap() + .as_str() + .split("/") + .collect::>(); + match &path[1..] { + ["2018-06-01", "runtime", "invocation", "next"] => next_event(&req).await, + ["2018-06-01", "runtime", "invocation", id, "response"] => complete_event(&req, id).await, + ["2018-06-01", "runtime", "invocation", id, "error"] => event_err(&req, id).await, + ["2018-06-01", "runtime", "init", "error"] => unimplemented!(), + _ => unimplemented!(), + } + }; + Box::pin(fut) + } +} + +async fn next_event(req: &Request) -> Result, Err> { + let path = "/2018-06-01/runtime/invocation/next"; + assert_eq!(req.method(), Method::GET); + assert_eq!(req.uri().path_and_query().unwrap(), &PathAndQuery::from_static(path)); + let body = json!({"message": "hello"}); + + let rsp = NextEventResponse { + request_id: "8476a536-e9f4-11e8-9739-2dfe598c3fcd", + deadline: 1542409706888, + arn: "arn:aws:lambda:us-east-2:123456789012:function:custom-runtime", + trace_id: "Root=1-5bef4de7-ad49b0e87f6ef6c87fc2e700;Parent=9a9197af755a6419", + body: serde_json::to_vec(&body)?, + }; + rsp.into_rsp() +} + +async fn complete_event(req: &Request, id: &str) -> Result, Err> { + assert_eq!(Method::POST, req.method()); + let rsp = Response::builder() + .status(StatusCode::ACCEPTED) + .body(Body::empty()) + .expect("Unable to construct response"); + + let expected = format!("/2018-06-01/runtime/invocation/{}/response", id); + assert_eq!(expected, req.uri().path()); + + Ok(rsp) +} + +async fn event_err(req: &Request, id: &str) -> Result, Err> { + let expected = format!("/2018-06-01/runtime/invocation/{}/error", id); + assert_eq!(expected, req.uri().path()); + + assert_eq!(req.method(), Method::POST); + let header = "lambda-runtime-function-error-type"; + let expected = "unhandled"; + assert_eq!(req.headers()[header], HeaderValue::try_from(expected)?); + + let rsp = Response::builder().status(StatusCode::ACCEPTED).body(Body::empty())?; + Ok(rsp) +} + +pub struct MakeSvc; + +impl Service for MakeSvc { + type Response = EndpointSvc; + type Error = std::io::Error; + type Future = future::Ready>; + + fn poll_ready(&mut self, _cx: &mut Context<'_>) -> Poll> { + Ok(()).into() + } + + fn call(&mut self, _: T) -> Self::Future { + future::ok(EndpointSvc) + } +} + +#[cfg(test)] +mod endpoint_tests { + use super::{Client, MakeSvc}; + use crate::{ + handler_fn, + requests::{EventCompletionRequest, EventErrorRequest, IntoRequest, NextEventRequest}, + run_simulated, + types::Diagnostic, + Err, INVOCATION_CTX, + }; + use http::{HeaderValue, StatusCode}; + use std::{ + convert::TryFrom, + net::{SocketAddr, TcpListener}, + }; + use tokio::select; + + /// `race` selects over two tasks. + /// + /// The first task to complete is joined and checked for errors. + /// In this test suite, we don't expect that the "server" task + /// will ever complete because it is continuously listening for + /// incoming events. + macro_rules! race { + ($left:ident, $right:ident) => { + select! { + $left = $left => { $left?? }, + $right = $right => { $right?? } + }; + }; + } + + fn setup() -> Result<(TcpListener, SocketAddr), Err> { + let listener = TcpListener::bind("127.0.0.1:0")?; + let addr = listener.local_addr()?; + Ok((listener, addr)) + } + + #[tokio::test] + async fn next_event() -> Result<(), Err> { + let (listener, addr) = setup()?; + let url = format!("http://{}/", addr); + + let server = tokio::spawn(async move { + let svc = hyper::Server::from_tcp(listener)?.serve(MakeSvc); + svc.await + }); + + let client = tokio::spawn(async { + let mut client = Client::with(url, hyper::Client::new())?; + let req = NextEventRequest.into_req()?; + let rsp = client.call(req).await?; + + assert_eq!(rsp.status(), StatusCode::OK); + let header = "lambda-runtime-deadline-ms"; + assert_eq!(rsp.headers()[header], &HeaderValue::try_from("1542409706888")?); + Ok::<(), Err>(()) + }); + race!(client, server); + Ok(()) + } + + #[tokio::test] + async fn ok_response() -> Result<(), Err> { + let (listener, addr) = setup()?; + let url = format!("http://{}/", addr); + + let server = tokio::spawn(async move { + let svc = hyper::Server::from_tcp(listener)?.serve(MakeSvc); + svc.await + }); + + let client = tokio::spawn(async { + let mut client = Client::with(url, hyper::Client::new())?; + let req = EventCompletionRequest { + request_id: "156cb537-e2d4-11e8-9b34-d36013741fb9", + body: "done", + }; + let req = req.into_req()?; + let rsp = client.call(req).await?; + assert_eq!(rsp.status(), StatusCode::ACCEPTED); + Ok::<(), Err>(()) + }); + race!(client, server); + Ok(()) + } + + #[tokio::test] + async fn error_response() -> Result<(), Err> { + let (listener, addr) = setup()?; + let url = format!("http://{}/", addr); + + let server = tokio::spawn(async move { + let svc = hyper::Server::from_tcp(listener)?.serve(MakeSvc); + svc.await + }); + + let client = tokio::spawn(async { + let mut client = Client::with(url, hyper::Client::new())?; + let req = EventErrorRequest { + request_id: "156cb537-e2d4-11e8-9b34-d36013741fb9", + diagnostic: Diagnostic { + error_type: "InvalidEventDataError".to_string(), + error_message: "Error parsing event data".to_string(), + }, + }; + let req = req.into_req()?; + let rsp = client.call(req).await?; + assert_eq!(rsp.status(), StatusCode::ACCEPTED); + Ok::<(), Err>(()) + }); + race!(client, server); + Ok(()) + } + + #[tokio::test] + async fn run_end_to_end() -> Result<(), Err> { + use serde_json::Value; + let (listener, addr) = setup()?; + let url = format!("http://{}/", addr); + + let server = tokio::spawn(async move { + let svc = hyper::Server::from_tcp(listener)?.serve(MakeSvc); + svc.await + }); + + async fn handler(s: Value) -> Result { + INVOCATION_CTX.with(|ctx| { + assert!(ctx.xray_trace_id.is_some()); + }); + Ok(s) + } + let handler = handler_fn(handler); + let client = tokio::spawn(async move { + run_simulated(handler, &url).await?; + Ok::<(), Err>(()) + }); + race!(client, server); + Ok(()) + } +} diff --git a/lambda/src/lib.rs b/lambda/src/lib.rs new file mode 100644 index 00000000..c5696736 --- /dev/null +++ b/lambda/src/lib.rs @@ -0,0 +1,255 @@ +#![deny(clippy::all, clippy::pedantic, clippy::nursery, clippy::cargo)] +#![warn(missing_docs, nonstandard_style, rust_2018_idioms)] + +//! The official Rust runtime for AWS Lambda. +//! +//! There are two mechanisms of defining a Lambda function: +//! 1. The `#[lambda]` attribute, which generates the boilerplate needed to +//! to launch and run a Lambda function. The `#[lambda]` attribute _must_ +//! be placed on an asynchronous main funtion. However, asynchronous main +//! funtions are not legal valid Rust, which means that a crate like +//! [Runtime](https://github.com/rustasync/runtime) must be used. A main function +//! decorated using `#[lamdba]` +//! 2. A type that conforms to the [`Handler`] trait. This type can then be passed +//! to the the `lambda::run` function, which launches and runs the Lambda runtime. +//! +//! An asynchronous function annotated with the `#[lambda]` attribute must +//! accept an argument of type `A` which implements [`serde::Deserialize`] and +//! return a `Result`, where `B` implements [`serde::Serializable`]. `E` is +//! any type that implements `Into>`. +//! +//! Optionally, the `#[lambda]` annotated function can accept an argument +//! of [`lambda::LambdaCtx`]. +//! +//! ```no_run +//! use lambda::lambda; +//! +//! type Error = Box; +//! +//! #[lambda] +//! #[tokio::main] +//! async fn main(event: String) -> Result { +//! Ok(event) +//! } +//! ``` +pub use crate::types::LambdaCtx; +use client::Client; +use http::{Request, Response}; +use hyper::Body; +pub use lambda_attributes::lambda; +use serde::{Deserialize, Serialize}; +use std::{ + convert::TryFrom, + env, + error::Error, + fmt, + future::Future, + pin::Pin, + task::{Context, Poll}, +}; +use tower_service::Service; + +mod client; +mod requests; +/// Types availible to a Lambda function. +mod types; + +use requests::{EventCompletionRequest, EventErrorRequest, IntoRequest, NextEventRequest}; +use types::Diagnostic; + +type Err = Box; + +/// Configuration derived from environment variables. +#[derive(Debug, Default, Clone, PartialEq)] +pub struct Config { + /// The host and port of the [runtime API](https://docs.aws.amazon.com/lambda/latest/dg/runtimes-api.html). + pub endpoint: String, + /// The name of the function. + pub function_name: String, + /// The amount of memory available to the function in MB. + pub memory: i32, + /// The version of the function being executed. + pub version: String, + /// The name of the Amazon CloudWatch Logs stream for the function. + pub log_stream: String, + /// The name of the Amazon CloudWatch Logs group for the function. + pub log_group: String, +} + +impl Config { + /// Attempts to read configuration from environment variables. + pub fn from_env() -> Result { + let conf = Config { + endpoint: env::var("AWS_LAMBDA_RUNTIME_API")?, + function_name: env::var("AWS_LAMBDA_FUNCTION_NAME")?, + memory: env::var("AWS_LAMBDA_FUNCTION_MEMORY_SIZE")?.parse::()?, + version: env::var("AWS_LAMBDA_FUNCTION_VERSION")?, + log_stream: env::var("AWS_LAMBDA_LOG_STREAM_NAME")?, + log_group: env::var("AWS_LAMBDA_LOG_GROUP_NAME")?, + }; + Ok(conf) + } +} + +tokio::task_local! { + pub static INVOCATION_CTX: types::LambdaCtx; +} + +/// A trait describing an asynchronous function `A` to `B. +pub trait Handler { + /// Errors returned by this handler. + type Err; + /// The future response value of this handler. + type Fut: Future>; + /// Process the incoming event and return the response asynchronously. + fn call(&mut self, event: A) -> Self::Fut; +} + +/// Returns a new `HandlerFn` with the given closure. +pub fn handler_fn(f: F) -> HandlerFn { + HandlerFn { f } +} + +/// A `Handler` or `HttpHandler` implemented by a closure. +#[derive(Clone, Debug)] +pub struct HandlerFn { + f: F, +} + +impl Handler for HandlerFn +where + F: Fn(A) -> Fut, + Fut: Future> + Send, + Err: Into> + fmt::Debug, +{ + type Err = Err; + type Fut = Fut; + fn call(&mut self, req: A) -> Self::Fut { + // we pass along the context here + (self.f)(req) + } +} + +/// Starts the Lambda Rust runtime and begins polling for events on the [Lambda +/// Runtime APIs](https://docs.aws.amazon.com/lambda/latest/dg/runtimes-api.html). +/// +/// # Example +/// ```no_run +/// use lambda::handler_fn; +/// +/// type Error = Box; +/// +/// #[tokio::main] +/// async fn main() -> Result<(), Error> { +/// let func = handler_fn(func); +/// lambda::run(func).await?; +/// Ok(()) +/// } +/// +/// async fn func(s: String) -> Result { +/// Ok(s) +/// } +/// ``` +pub async fn run(handler: F) -> Result<(), Err> +where + F: Handler, + >::Err: fmt::Debug, + A: for<'de> Deserialize<'de>, + B: Serialize, +{ + let mut handler = handler; + let config = Config::from_env()?; + let client = Client::with(&config.endpoint, hyper::Client::new())?; + let mut exec = Executor { client }; + exec.run(&mut handler, false).await?; + + Ok(()) +} + +/// Runs the lambda function almost entirely in-memory. This is meant for testing. +pub async fn run_simulated(handler: F, url: &str) -> Result<(), Err> +where + F: Handler, + >::Err: fmt::Debug, + A: for<'de> Deserialize<'de>, + B: Serialize, +{ + let mut handler = handler; + let client = Client::with(url, hyper::Client::new())?; + let mut exec = Executor { client }; + exec.run(&mut handler, true).await?; + + Ok(()) +} + +struct Executor { + client: Client, +} + +struct Incoming { + client: Client, + future: Option, +} + +impl futures::Stream for Incoming +where + S: Service, Response = Response>, + >>::Error: Error + Send + Sync + 'static, + F: Future, +{ + type Item = Result, S::Error>; + + fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { + unimplemented!() + } +} + +impl Executor +where + S: Service, Response = Response>, + >>::Error: Error + Send + Sync + 'static, +{ + async fn run(&mut self, handler: &mut F, once: bool) -> Result<(), Err> + where + F: Handler, + >::Err: fmt::Debug, + A: for<'de> Deserialize<'de>, + B: Serialize, + { + let client = &mut self.client; + // todo: refactor this into a stream so that the `once` boolean can be replaced + // a `.take(n).await` combinator if we want to run this once, if `n` is `1`. + loop { + let req = NextEventRequest.into_req()?; + let event = client.call(req).await?; + let (parts, body) = event.into_parts(); + + let ctx = LambdaCtx::try_from(parts.headers)?; + let body = hyper::body::to_bytes(body).await?; + let body = serde_json::from_slice(&body)?; + + let request_id = &ctx.request_id.clone(); + let f = INVOCATION_CTX.scope(ctx, { handler.call(body) }); + + let req = match f.await { + Ok(res) => EventCompletionRequest { request_id, body: res }.into_req()?, + Err(err) => EventErrorRequest { + request_id, + diagnostic: Diagnostic { + error_message: format!("{:?}", err), + error_type: type_name_of_val(err).to_owned(), + }, + } + .into_req()?, + }; + client.call(req).await?; + if once { + break Ok(()); + } + } + } +} + +fn type_name_of_val(_: T) -> &'static str { + std::any::type_name::() +} diff --git a/lambda/src/requests.rs b/lambda/src/requests.rs new file mode 100644 index 00000000..2273d9ab --- /dev/null +++ b/lambda/src/requests.rs @@ -0,0 +1,156 @@ +use crate::{types::Diagnostic, Err}; +use http::{Method, Request, Response, Uri}; +use hyper::Body; +use serde::Serialize; +use std::str::FromStr; + +pub(crate) trait IntoRequest { + fn into_req(self) -> Result, Err>; +} + +pub(crate) trait IntoResponse { + fn into_rsp(self) -> Result, Err>; +} + +// /runtime/invocation/next +#[derive(Debug, PartialEq)] +pub(crate) struct NextEventRequest; + +impl IntoRequest for NextEventRequest { + fn into_req(self) -> Result, Err> { + let req = Request::builder() + .method(Method::GET) + .uri(Uri::from_static("/2018-06-01/runtime/invocation/next")) + .body(Body::empty())?; + Ok(req) + } +} + +#[derive(Debug, PartialEq)] +pub struct NextEventResponse<'a> { + // lambda-runtime-aws-request-id + pub request_id: &'a str, + // lambda-runtime-deadline-ms + pub deadline: u64, + // lambda-runtime-invoked-function-arn + pub arn: &'a str, + // lambda-runtime-trace-id + pub trace_id: &'a str, + // the actual body, + pub body: Vec, +} + +impl<'a> IntoResponse for NextEventResponse<'a> { + fn into_rsp(self) -> Result, Err> { + let rsp = Response::builder() + .header("lambda-runtime-aws-request-id", self.request_id) + .header("lambda-runtime-deadline-ms", self.deadline) + .header("lambda-runtime-invoked-function-arn", self.arn) + .header("lambda-runtime-trace-id", self.trace_id) + .body(Body::from(self.body))?; + Ok(rsp) + } +} +#[test] +fn test_next_event_request() { + let req = NextEventRequest; + let req = req.into_req().unwrap(); + assert_eq!(req.method(), Method::GET); + assert_eq!(req.uri(), &Uri::from_static("/2018-06-01/runtime/invocation/next")); +} + +// /runtime/invocation/{AwsRequestId}/response +pub(crate) struct EventCompletionRequest<'a, T> { + pub(crate) request_id: &'a str, + pub(crate) body: T, +} + +impl<'a, T> IntoRequest for EventCompletionRequest<'a, T> +where + T: for<'serialize> Serialize, +{ + fn into_req(self) -> Result, Err> { + let uri = format!("/2018-06-01/runtime/invocation/{}/response", self.request_id); + let uri = Uri::from_str(&uri)?; + let body = serde_json::to_vec(&self.body)?; + let body = Body::from(body); + + let req = Request::builder().method(Method::POST).uri(uri).body(body)?; + Ok(req) + } +} + +#[test] +fn test_event_completion_request() { + let req = EventCompletionRequest { + request_id: "id", + body: "hello, world!", + }; + let req = req.into_req().unwrap(); + let expected = Uri::from_static("/2018-06-01/runtime/invocation/id/response"); + assert_eq!(req.method(), Method::POST); + assert_eq!(req.uri(), &expected); +} + +// /runtime/invocation/{AwsRequestId}/error +pub(crate) struct EventErrorRequest<'a> { + pub(crate) request_id: &'a str, + pub(crate) diagnostic: Diagnostic, +} + +impl<'a> IntoRequest for EventErrorRequest<'a> { + fn into_req(self) -> Result, Err> { + let uri = format!("/2018-06-01/runtime/invocation/{}/error", self.request_id); + let uri = Uri::from_str(&uri)?; + let body = serde_json::to_vec(&self.diagnostic)?; + let body = Body::from(body); + + let req = Request::builder() + .method(Method::POST) + .uri(uri) + .header("lambda-runtime-function-error-type", "unhandled") + .body(body)?; + Ok(req) + } +} + +#[test] +fn test_event_error_request() { + let req = EventErrorRequest { + request_id: "id", + diagnostic: Diagnostic { + error_type: "InvalidEventDataError".to_string(), + error_message: "Error parsing event data".to_string(), + }, + }; + let req = req.into_req().unwrap(); + let expected = Uri::from_static("/2018-06-01/runtime/invocation/id/error"); + assert_eq!(req.method(), Method::POST); + assert_eq!(req.uri(), &expected); +} + +// /runtime/init/error +struct InitErrorRequest; + +impl IntoRequest for InitErrorRequest { + fn into_req(self) -> Result, Err> { + let uri = format!("/2018-06-01/runtime/init/error"); + let uri = Uri::from_str(&uri)?; + + let req = Request::builder() + .method(Method::POST) + .uri(uri) + .header("lambda-runtime-function-error-type", "unhandled") + .body(Body::empty())?; + Ok(req) + } +} + +#[test] +fn test_init_error_request() { + let req = InitErrorRequest; + let req = req.into_req().unwrap(); + let expected = Uri::from_static("/2018-06-01/runtime/init/error"); + assert_eq!(req.method(), Method::POST); + assert_eq!(req.uri(), &expected); +} diff --git a/lambda/src/types.rs b/lambda/src/types.rs new file mode 100644 index 00000000..e33f966a --- /dev/null +++ b/lambda/src/types.rs @@ -0,0 +1,145 @@ +use crate::{Config, Err}; +use http::HeaderMap; +use serde::{Deserialize, Serialize}; +use std::{collections::HashMap, convert::TryFrom}; + +#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub(crate) struct Diagnostic { + pub(crate) error_type: String, + pub(crate) error_message: String, +} + +#[test] +fn round_trip_lambda_error() -> Result<(), Err> { + use serde_json::{json, Value}; + let expected = json!({ + "errorType": "InvalidEventDataError", + "errorMessage": "Error parsing event data.", + }); + + let actual: Diagnostic = serde_json::from_value(expected.clone())?; + let actual: Value = serde_json::to_value(actual)?; + assert_eq!(expected, actual); + + Ok(()) +} + +/// The request ID, which identifies the request that triggered the function invocation. This header +/// tracks the invocation within the Lambda control plane. The request ID is used to specify completion +/// of a given invocation. +#[derive(Debug, Clone, PartialEq)] +pub struct RequestId(pub String); + +/// The date that the function times out in Unix time milliseconds. For example, `1542409706888`. +#[derive(Debug, Clone, PartialEq)] +pub struct InvocationDeadline(pub u64); + +/// The ARN of the Lambda function, version, or alias that is specified in the invocation. +/// For instance, `arn:aws:lambda:us-east-2:123456789012:function:custom-runtime`. +#[derive(Debug, Clone, PartialEq)] +pub struct FunctionArn(pub String); + +/// The AWS X-Ray Tracing header. For more information, +/// please see [AWS' documentation](https://docs.aws.amazon.com/xray/latest/devguide/xray-concepts.html#xray-concepts-tracingheader). +#[derive(Debug, Clone, PartialEq)] +pub struct XRayTraceId(pub String); + +/// For invocations from the AWS Mobile SDK contains data about client application and device. +#[derive(Debug, Clone, PartialEq)] +struct MobileClientContext(String); + +/// For invocations from the AWS Mobile SDK, data about the Amazon Cognito identity provider. +#[derive(Debug, Clone, PartialEq)] +struct MobileClientIdentity(String); + +/// Client context sent by the AWS Mobile SDK. +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)] +pub struct ClientContext { + /// Information about the mobile application invoking the function. + pub client: ClientApplication, + /// Custom properties attached to the mobile event context. + pub custom: HashMap, + /// Environment settings from the mobile client. + pub environment: HashMap, +} + +/// AWS Mobile SDK client fields. +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)] +#[serde(rename_all = "camelCase")] +pub struct ClientApplication { + /// The mobile app installation id + pub installation_id: String, + /// The app title for the mobile app as registered with AWS' mobile services. + pub app_title: String, + /// The version name of the application as registered with AWS' mobile services. + pub app_version_name: String, + /// The app version code. + pub app_version_code: String, + /// The package name for the mobile application invoking the function + pub app_package_name: String, +} + +/// Cognito identity information sent with the event +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)] +pub struct CognitoIdentity { + /// The unique identity id for the Cognito credentials invoking the function. + pub identity_id: String, + /// The identity pool id the caller is "registered" with. + pub identity_pool_id: String, +} + +/// The Lambda function execution context. The values in this struct +/// are populated using the [Lambda environment variables](https://docs.aws.amazon.com/lambda/latest/dg/current-supported-versions.html) +/// and the headers returned by the poll request to the Runtime APIs. +#[non_exhaustive] +#[derive(Clone, Debug, PartialEq, Default)] +pub struct LambdaCtx { + /// The AWS request ID generated by the Lambda service. + pub request_id: String, + /// The execution deadline for the current invocation in milliseconds. + pub deadline: u64, + /// The ARN of the Lambda function being invoked. + pub invoked_function_arn: String, + /// The X-Ray trace ID for the current invocation. + pub xray_trace_id: Option, + /// The client context object sent by the AWS mobile SDK. This field is + /// empty unless the function is invoked using an AWS mobile SDK. + pub client_context: Option, + /// The Cognito identity that invoked the function. This field is empty + /// unless the invocation request to the Lambda APIs was made using AWS + /// credentials issues by Amazon Cognito Identity Pools. + pub identity: Option, + /// Lambda function configuration from the local environment variables. + /// Includes information such as the function name, memory allocation, + /// version, and log streams. + pub env_config: Config, +} + +impl TryFrom for LambdaCtx { + type Error = Err; + fn try_from(headers: HeaderMap) -> Result { + let ctx = LambdaCtx { + request_id: headers["lambda-runtime-aws-request-id"] + .to_str() + .expect("Missing Request ID") + .to_owned(), + deadline: headers["lambda-runtime-deadline-ms"] + .to_str()? + .parse() + .expect("Missing deadline"), + invoked_function_arn: headers["lambda-runtime-invoked-function-arn"] + .to_str() + .expect("Missing arn; this is a bug") + .to_owned(), + xray_trace_id: headers.get("lambda-runtime-trace-id").map(|header| { + header + .to_str() + .expect("Invalid XRayTraceID sent by Lambda; this is a bug") + .to_owned() + }), + ..Default::default() + }; + Ok(ctx) + } +}