Introduce an `aws-lambda` feature. (#2035)

* Introduce an `aws-lambda` feature.

* Add CHANGELOG

* Use the new and shiny feature syntax to avoid creating an implicit `lambda_http` feature.

* Add `aws-lambda` feature to the Python server. Enable the `aws-lambda` feature in our example. Be explicit in providing an implementation of request rejection for Box<dyn Error>.

* Add an `aws-lambda` feature flag to the generated Python-specific crate. We enable it by default to make sure the Lambda method ends up visible in the final Python wrapper library.
This commit is contained in:
Luca Palmieri 2022-11-29 15:48:48 +00:00 committed by GitHub
parent 0adad6a72d
commit 3a9a42bb16
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 54 additions and 7 deletions

View File

@ -487,3 +487,15 @@ message = "Make generated enum `values()` functions callable in const contexts."
references = ["smithy-rs#2011"] references = ["smithy-rs#2011"]
meta = { "breaking" = false, "tada" = false, "bug" = false, "target" = "all" } meta = { "breaking" = false, "tada" = false, "bug" = false, "target" = "all" }
author = "lsr0" author = "lsr0"
[[smithy-rs]]
message = """
All types that are exclusively relevant within the context of an AWS Lambda function are now gated behind the
`aws-lambda` feature flag.
This will reduce the number of dependencies (and improve build times) for users that are running their Smithy services
in non-serverless environments (e.g. via `hyper`).
"""
references = ["smithy-rs#2035"]
meta = { "breaking" = true, "tada" = false, "bug" = false, "target" = "server" }
author = "LukeMathWalker"

View File

@ -7,6 +7,7 @@ package software.amazon.smithy.rust.codegen.server.python.smithy.customizations
import software.amazon.smithy.model.neighbor.Walker import software.amazon.smithy.model.neighbor.Walker
import software.amazon.smithy.rust.codegen.client.smithy.customize.RustCodegenDecorator import software.amazon.smithy.rust.codegen.client.smithy.customize.RustCodegenDecorator
import software.amazon.smithy.rust.codegen.core.rustlang.Feature
import software.amazon.smithy.rust.codegen.core.rustlang.Writable import software.amazon.smithy.rust.codegen.core.rustlang.Writable
import software.amazon.smithy.rust.codegen.core.rustlang.docs import software.amazon.smithy.rust.codegen.core.rustlang.docs
import software.amazon.smithy.rust.codegen.core.rustlang.rust import software.amazon.smithy.rust.codegen.core.rustlang.rust
@ -103,6 +104,21 @@ class PubUsePythonTypesDecorator : RustCodegenDecorator<ServerProtocolGenerator,
clazz.isAssignableFrom(ServerCodegenContext::class.java) clazz.isAssignableFrom(ServerCodegenContext::class.java)
} }
/**
* Decorator adding an `aws-lambda` feature to the generated crate.
*/
class PythonFeatureFlagsDecorator : RustCodegenDecorator<ServerProtocolGenerator, ServerCodegenContext> {
override val name: String = "PythonFeatureFlagsDecorator"
override val order: Byte = 0
override fun extras(codegenContext: ServerCodegenContext, rustCrate: RustCrate) {
rustCrate.mergeFeature(Feature("aws-lambda", true, listOf("aws-smithy-http-server-python/aws-lambda")))
}
override fun supportsCodegenContext(clazz: Class<out CodegenContext>): Boolean =
clazz.isAssignableFrom(ServerCodegenContext::class.java)
}
val DECORATORS = listOf( val DECORATORS = listOf(
/** /**
* Add the [InternalServerError] error to all operations. * Add the [InternalServerError] error to all operations.
@ -115,4 +131,6 @@ val DECORATORS = listOf(
PubUsePythonTypesDecorator(), PubUsePythonTypesDecorator(),
// Render the Python shared library export. // Render the Python shared library export.
PythonExportModuleDecorator(), PythonExportModuleDecorator(),
// Add the `aws-lambda` feature flag
PythonFeatureFlagsDecorator(),
) )

View File

@ -278,6 +278,7 @@ class PythonApplicationGenerator(
self.run_server(py, address, port, backlog, workers) self.run_server(py, address, port, backlog, workers)
} }
/// Lambda entrypoint: start the server on Lambda. /// Lambda entrypoint: start the server on Lambda.
##[cfg(feature = "aws-lambda")]
##[pyo3(text_signature = "(${'$'}self)")] ##[pyo3(text_signature = "(${'$'}self)")]
pub fn run_lambda( pub fn run_lambda(
&mut self, &mut self,

View File

@ -12,6 +12,9 @@ Python server runtime for Smithy Rust Server Framework.
""" """
publish = true publish = true
[features]
aws-lambda = ["aws-smithy-http-server/aws-lambda", "dep:lambda_http"]
[dependencies] [dependencies]
aws-smithy-http = { path = "../aws-smithy-http" } aws-smithy-http = { path = "../aws-smithy-http" }
aws-smithy-http-server = { path = "../aws-smithy-http-server" } aws-smithy-http-server = { path = "../aws-smithy-http-server" }
@ -22,7 +25,7 @@ bytes = "1.2"
futures = "0.3" futures = "0.3"
http = "0.2" http = "0.2"
hyper = { version = "0.14.20", features = ["server", "http1", "http2", "tcp", "stream"] } hyper = { version = "0.14.20", features = ["server", "http1", "http2", "tcp", "stream"] }
lambda_http = "0.7.1" lambda_http = { version = "0.7.1", optional = true }
num_cpus = "1.13.1" num_cpus = "1.13.1"
parking_lot = "0.12.1" parking_lot = "0.12.1"
pin-project-lite = "0.2" pin-project-lite = "0.2"

View File

@ -3,6 +3,8 @@
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
#![cfg_attr(docsrs, feature(doc_cfg))]
//! Rust/Python bindings, runtime and utilities. //! Rust/Python bindings, runtime and utilities.
//! //!
//! This crates implements all the generic code needed to start and manage //! This crates implements all the generic code needed to start and manage

View File

@ -7,7 +7,7 @@ use std::{collections::HashMap, convert::Infallible, ops::Deref, process, thread
use aws_smithy_http_server::{ use aws_smithy_http_server::{
body::{Body, BoxBody}, body::{Body, BoxBody},
routing::{IntoMakeService, LambdaHandler}, routing::IntoMakeService,
AddExtensionLayer, AddExtensionLayer,
}; };
use http::{Request, Response}; use http::{Request, Response};
@ -422,7 +422,11 @@ event_loop.add_signal_handler(signal.SIGINT,
/// ///
/// Unlike the `run_server`, `run_lambda_handler` does not spawns other processes, /// Unlike the `run_server`, `run_lambda_handler` does not spawns other processes,
/// it starts the Lambda handler on the current process. /// it starts the Lambda handler on the current process.
#[cfg(feature = "aws-lambda")]
#[cfg_attr(docsrs, doc(cfg(feature = "aws-lambda")))]
fn run_lambda_handler(&mut self, py: Python) -> PyResult<()> { fn run_lambda_handler(&mut self, py: Python) -> PyResult<()> {
use aws_smithy_http_server::routing::LambdaHandler;
let event_loop = self.configure_python_event_loop(py)?; let event_loop = self.configure_python_event_loop(py)?;
let service = self.build_and_configure_service(py, event_loop)?; let service = self.build_and_configure_service(py, event_loop)?;
let rt = runtime::Builder::new_multi_thread() let rt = runtime::Builder::new_multi_thread()

View File

@ -13,6 +13,7 @@ Server runtime for Smithy Rust Server Framework.
publish = true publish = true
[features] [features]
aws-lambda = ["dep:lambda_http"]
unredacted-logging = [] unredacted-logging = []
[dependencies] [dependencies]
@ -26,7 +27,7 @@ futures-util = { version = "0.3", default-features = false }
http = "0.2" http = "0.2"
http-body = "0.4" http-body = "0.4"
hyper = { version = "0.14.12", features = ["server", "http1", "http2", "tcp", "stream"] } hyper = { version = "0.14.12", features = ["server", "http1", "http2", "tcp", "stream"] }
lambda_http = "0.7.1" lambda_http = { version = "0.7.1", optional = true }
mime = "0.3" mime = "0.3"
nom = "7" nom = "7"
pin-project-lite = "0.2" pin-project-lite = "0.2"

View File

@ -44,7 +44,7 @@ futures-util = "0.3"
lambda_http = "0.7.1" lambda_http = "0.7.1"
# Local paths # Local paths
aws-smithy-http-server = { path = "../../" } aws-smithy-http-server = { path = "../../", features = ["aws-lambda"] }
pokemon-service-server-sdk = { path = "../pokemon-service-server-sdk/" } pokemon-service-server-sdk = { path = "../pokemon-service-server-sdk/" }
[dev-dependencies] [dev-dependencies]

View File

@ -3,10 +3,11 @@
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
#![cfg_attr(docsrs, feature(doc_cfg))]
//! HTTP server runtime and utilities, loosely based on [axum]. //! HTTP server runtime and utilities, loosely based on [axum].
//! //!
//! [axum]: https://docs.rs/axum/latest/axum/ //! [axum]: https://docs.rs/axum/latest/axum/
#[macro_use] #[macro_use]
pub(crate) mod macros; pub(crate) mod macros;

View File

@ -261,8 +261,9 @@ convert_to_request_rejection!(std::str::Utf8Error, InvalidUtf8);
// everyone will run a Hyper-based server in their services). // everyone will run a Hyper-based server in their services).
convert_to_request_rejection!(hyper::Error, HttpBody); convert_to_request_rejection!(hyper::Error, HttpBody);
// Required in order to accept Lambda HTTP requests using `Router<lambda_http::Body>`. // Useful in general, but it also required in order to accept Lambda HTTP requests using
convert_to_request_rejection!(lambda_http::Error, HttpBody); // `Router<lambda_http::Body>` since `lambda_http::Error` is a type alias for `Box<dyn Error + ..>`.
convert_to_request_rejection!(Box<dyn std::error::Error + Send + Sync + 'static>, HttpBody);
pub mod any_rejections { pub mod any_rejections {
//! This module hosts enums, up to size 8, which implement [`IntoResponse`] when their variants implement //! This module hosts enums, up to size 8, which implement [`IntoResponse`] when their variants implement

View File

@ -29,6 +29,8 @@ use tower_http::map_response_body::MapResponseBodyLayer;
mod future; mod future;
mod into_make_service; mod into_make_service;
#[cfg(feature = "aws-lambda")]
#[cfg_attr(docsrs, doc(cfg(feature = "aws-lambda")))]
mod lambda_handler; mod lambda_handler;
#[doc(hidden)] #[doc(hidden)]
@ -38,6 +40,8 @@ mod route;
pub(crate) mod tiny_map; pub(crate) mod tiny_map;
#[cfg(feature = "aws-lambda")]
#[cfg_attr(docsrs, doc(cfg(feature = "aws-lambda")))]
pub use self::lambda_handler::LambdaHandler; pub use self::lambda_handler::LambdaHandler;
pub use self::{future::RouterFuture, into_make_service::IntoMakeService, route::Route}; pub use self::{future::RouterFuture, into_make_service::IntoMakeService, route::Route};