/* * Copyright 2020-present, Nike, Inc. * All rights reserved. * * This source code is licensed under the Apache-2.0 license found in * the LICENSE file in the root of this source tree. */ //! An example of a long-lived green grass lambda. //! This example creates an http endpoint on the greengrass device. It will then forward //! messages it receives to the MQTT topic longlived/device-sent. //! //! See the following guide for long lived functions: https://docs.aws.amazon.com/greengrass/latest/developerguide/long-lived.html //! //! ## Sample Request //! ```shell script //! curl -vvvv -H "Content-Type: application/json" -d '{"msg": "hello"}' http://127.0.0.1:5020/ //! ``` use aws_greengrass_core_rust::iotdata::IOTDataClient; use aws_greengrass_core_rust::log as gglog; use aws_greengrass_core_rust::runtime::{Runtime, RuntimeOption}; use aws_greengrass_core_rust::{GGResult, Initializer}; use hyper::service::{make_service_fn, service_fn}; use hyper::{Body, Method, Request, Response, Server, StatusCode}; use log::{error, info, LevelFilter}; const SEND_TOPIC: &str = "longlived/device-sent"; async fn serve(req: Request) -> Result, hyper::Error> { match (req.method(), req.uri().path()) { // Simply echo the body back to the client. (&Method::POST, "/") => { let body = hyper::body::to_bytes(req.into_body()).await?; match publish(&body).await { Ok(_) => { let mut accepted = Response::default(); *accepted.status_mut() = StatusCode::ACCEPTED; Ok(accepted) } Err(e) => { error!("greengrass error occurred: {}", e); let mut internal_error = Response::new(Body::from(format!("{}", e))); *internal_error.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; Ok(internal_error) } } } // Return the 404 Not Found for other routes. _ => { let mut not_found = Response::default(); *not_found.status_mut() = StatusCode::NOT_FOUND; Ok(not_found) } } } async fn publish(bytes: &[u8]) -> GGResult<()> { // convert to a string for logging purposes info!("publishing message of {}", String::from_utf8_lossy(bytes)); IOTDataClient::default().publish(SEND_TOPIC, bytes) } #[tokio::main] async fn main() -> Result<(), Box> { // Initialize logging gglog::init_log(LevelFilter::Debug); // Initialize Greengrass, long lived functions need to be configured with RuntimeOption::Async let runtime = Runtime::default().with_runtime_option(RuntimeOption::Async); Initializer::default().with_runtime(runtime).init()?; // Initialize hyper let addr = ([0, 0, 0, 0], 5020).into(); let service = make_service_fn(|_| async { Ok::<_, hyper::Error>(service_fn(serve)) }); let server = Server::bind(&addr).serve(service); info!("Listening on http://{}", addr); server.await?; info!("longlived lambda exiting"); Ok(()) }