1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174
//! # Azure Functions for Rust //! //! The Azure Functions for Rust crate supports writting Azure Functions in Rust. //! //! The following Azure Functions trigger bindings are supported: //! //! * [HTTP triggers](bindings/struct.HttpRequest.html) //! * [Timer triggers](bindings/struct.TimerInfo.html) //! //! The following Azure Functions output bindings are supported: //! //! * [HTTP output](bindings/struct.HttpResponse.html) //! //! Eventually more bindings will be implemented, including custom binding data. //! //! # Examples //! //! Start by creating a new binary package: //! //! ```bash //! $ cargo new --bin example //! ``` //! //! Edit `Cargo.toml` to include the following dependencies: //! //! ```toml //! azure-functions = "0.1.3" //! log = "0.4.2" //! ``` //! //! Azure Functions are implemented by applying a trigger attribute to a Rust function. //! //! For example, let's create `src/greet.rs` that implements a HTTP triggered function by //! applying the `func` attribute: //! //! ```rust //! # #![feature(proc_macro)] extern crate azure_functions; //! # #[macro_use] extern crate log; //! use azure_functions::func; //! use azure_functions::bindings::{HttpRequest, HttpResponse}; //! //! #[func] //! #[binding(name = "request", auth_level = "anonymous")] //! pub fn greet(request: &HttpRequest) -> HttpResponse { //! // Log the request on the Azure Functions Host //! info!("Request: {:?}", request); //! //! // Return a formatted string as the response //! format!( //! "Hello from Rust, {}!", //! request.query_params().get("name").map_or("stranger", |x| x) //! ).into() //! } //! ``` //! //! Replace the contents of `src/main.rs` with the following to register the function with //! the Azure Functions Host: //! //! ```rust,ignore //! #![feature(proc_macro)] //! //! #[macro_use] //! extern crate log; //! extern crate azure_functions; //! //! mod greet; //! //! // The main! macro generates an entrypoint for the binary //! // Expects a list of Azure Functions to register with the Azure Functions host //! azure_functions::main!{ //! greet::greet //! } //! ``` //! //! Run the application with the `--create <root>` option, where `<root>` is the path to //! the desired Azure Functions application root directory: //! //! ```bash //! $ export AzureWebJobsScriptRoot=path-to-root //! $ cargo run -q -- --create $AzureWebJobsScriptRoot //! ``` //! //! Run the Azure Functions Host: //! //! ```bash //! $ cd azure-functions-host/src/WebJobs.Script.WebHost //! $ dotnet run //! ``` //! //! The above Azure Function can be invoked with `http://localhost:5000/api/greet?name=John`. //! //! The expected response would be `Hello from Rust, John!`. #![feature(proc_macro)] #![feature(proc_macro_mod)] #![feature(proc_macro_gen)] #![deny(missing_docs)] extern crate azure_functions_codegen; extern crate clap; extern crate futures; extern crate grpcio; #[macro_use] extern crate log; extern crate protobuf; extern crate serde; extern crate serde_json; #[macro_use] extern crate serde_derive; extern crate chrono; extern crate tokio_threadpool; #[doc(no_inline)] pub use azure_functions_codegen::func; mod cli; mod context; mod logger; mod registry; pub mod bindings; #[doc(hidden)] pub mod codegen; pub mod http; #[doc(hidden)] pub mod rpc; #[doc(no_inline)] pub use azure_functions_codegen::main; pub use context::Context; use futures::Future; use registry::Registry; use std::sync::{Arc, Mutex}; #[doc(hidden)] pub fn worker_main(args: impl Iterator<Item = String>, functions: &[&'static codegen::Function]) { let matches = cli::create_app().get_matches_from(args); let registry = Arc::new(Mutex::new(Registry::new(functions))); if let Some(root) = matches.value_of("create") { cli::generate_functions_app(root, registry); return; } let client = rpc::Client::new( matches .value_of("worker_id") .expect("A worker id is required.") .to_owned(), matches .value_of("max_message_length") .map(|len| len.parse::<i32>().expect("Invalid maximum message length")), ); let host = matches.value_of("host").expect("A host is required."); let port = matches .value_of("port") .map(|port| port.parse::<u32>().expect("Invalid port number")) .expect("Port number is required."); println!("Connecting to Azure Functions host at {}:{}.", host, port); client .connect(host, port) .and_then(|client| { println!( "Connected to Azure Functions host version {}.", client.host_version().unwrap() ); client.process_all_messages(registry) }) .wait() .unwrap(); }