From 011c3ba3f7bc466a04101f81d4f6186001b7aad4 Mon Sep 17 00:00:00 2001 From: Timo Stark Date: Mon, 28 Aug 2023 05:43:31 -0700 Subject: Adding echo Request with body Parsing --- examples/rust/echo-request-wbody/Cargo.toml | 15 ++ examples/rust/echo-request-wbody/src/lib.rs | 152 +++++++++++++++++++++ .../rust/echo-request-wbody/unit-wasm-conf.json | 36 +++++ 3 files changed, 203 insertions(+) create mode 100644 examples/rust/echo-request-wbody/Cargo.toml create mode 100644 examples/rust/echo-request-wbody/src/lib.rs create mode 100644 examples/rust/echo-request-wbody/unit-wasm-conf.json diff --git a/examples/rust/echo-request-wbody/Cargo.toml b/examples/rust/echo-request-wbody/Cargo.toml new file mode 100644 index 0000000..69b9089 --- /dev/null +++ b/examples/rust/echo-request-wbody/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "rust-echo-request" +version = "0.2.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +json = "0.12.4" +serde = "1.0.188" +serde_json = "1.0.105" +unit-wasm = { path = "../../../src/rust", version = "0.1.1" } + +[lib] +crate-type = ["cdylib"] diff --git a/examples/rust/echo-request-wbody/src/lib.rs b/examples/rust/echo-request-wbody/src/lib.rs new file mode 100644 index 0000000..1825874 --- /dev/null +++ b/examples/rust/echo-request-wbody/src/lib.rs @@ -0,0 +1,152 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +/* + * Copyright (C) Andrew Clayton + * Copyright (C) Timo Stark + * Copyright (C) F5, Inc. + */ + +use unit_wasm::rusty::*; + +use std::ffi::CStr; +use std::os::raw::c_char; +use std::os::raw::c_void; +use std::ptr::null_mut; + +use serde_json::{Result, Value}; + +// Buffer of some size to store the copy of the request +static mut REQUEST_BUF: *mut u8 = null_mut(); + +#[no_mangle] +pub extern "C" fn uwr_module_end_handler() { + unsafe { + uwr_free(REQUEST_BUF); + } +} + +#[no_mangle] +pub extern "C" fn uwr_module_init_handler() { + unsafe { + REQUEST_BUF = uwr_malloc(uwr_mem_get_init_size()); + } +} + +pub extern "C" fn hdr_iter_func( + ctx: *mut luw_ctx_t, + name: *const c_char, + value: *const c_char, + _data: *mut c_void, +) -> bool { + uwr_write_str!(ctx, "{} = {}\n", C2S!(name), C2S!(value)); + + return true; +} + +#[no_mangle] +pub extern "C" fn uwr_request_handler(addr: *mut u8) -> i32 { + // Declare a 0-initialised context structure + + let ctx = &mut UWR_CTX_INITIALIZER(); + // get the HTTP Method + let method = uwr_get_http_method(ctx); + + // Initialise the context structure. + // + // addr is the address of the previously allocated memory shared + // between the module and unit. + // + // The response data will be stored @ addr + offset (of 4096 bytes). + // This will leave some space for the response headers. + uwr_init_ctx(ctx, addr, 4096); + + // Set where we will copy the request into + unsafe { + uwr_set_req_buf(ctx, &mut REQUEST_BUF, LUW_SRB_NONE); + } + + // Get request body + let request_body: &CStr; + let mystring: String; + + //if method == "POST" || method == "PUT" { + request_body = unsafe { CStr::from_ptr(uwr_get_http_content(ctx) as *mut i8) }; + // Get copy-on-write Cow<'_, str>, then guarantee a freshly-owned String allocation + mystring = String::from_utf8_lossy(request_body.to_bytes()).to_string(); + + + fn parser(data: String) -> Result { + let json: Value = serde_json::from_str(&data)?; + // Like a return statement in case of no error + Ok(json) + } + + let json = parser(mystring); + match json { + Ok(result) => { uwr_write_str!(ctx, "Message: {}\n", result["message"]);}, + Err(error) => println!("{}", error), + } + + //} + + // Define the Response Body Text. + uwr_write_str!( + ctx, + " * Welcome to WebAssembly in Rust on Unit! \ + [libunit-wasm ({}.{}.{}/{:#010x})] *\n\n", + LUW_VERSION_MAJOR, + LUW_VERSION_MINOR, + LUW_VERSION_PATCH, + LUW_VERSION_NUMBER, + ); + + uwr_write_str!(ctx, "[Request Info]\n"); + uwr_write_str!(ctx, "REQUEST_PATH = {}\n", uwr_get_http_path(ctx)); + uwr_write_str!(ctx, "METHOD = {}\n", uwr_get_http_method(ctx)); + uwr_write_str!(ctx, "VERSION = {}\n", uwr_get_http_version(ctx)); + uwr_write_str!(ctx, "QUERY = {}\n", uwr_get_http_query(ctx)); + uwr_write_str!(ctx, "REMOTE = {}\n", uwr_get_http_remote(ctx)); + uwr_write_str!(ctx, "LOCAL_ADDR = {}\n", uwr_get_http_local_addr(ctx)); + uwr_write_str!(ctx, "LOCAL_PORT = {}\n", uwr_get_http_local_port(ctx)); + uwr_write_str!(ctx, "SERVER_NAME = {}\n", uwr_get_http_server_name(ctx)); + + uwr_write_str!(ctx, "\n[Request Headers]\n"); + + uwr_http_hdr_iter(ctx, Some(hdr_iter_func), null_mut()); + + if method == "POST" || method == "PUT" { + uwr_write_str!(ctx, "\n[{} data]\n", method); + uwr_mem_write_buf( + ctx, + uwr_get_http_content(ctx), + uwr_get_http_content_len(ctx), + ); + uwr_write_str!(ctx, "\n"); + } + + // Init Response Headers + // + // Needs the context, number of headers about to add as well as + // the offset where to store the headers. In this case we are + // storing the response headers at the beginning of our shared + // memory at offset 0. + uwr_http_init_headers(ctx, 2, 0); + uwr_http_add_header(ctx, 0, "Content-Type", "text/plain"); + uwr_http_add_header( + ctx, + 1, + "Content-Length", + &format!("{}", uwr_get_response_data_size(ctx)), + ); + + // This calls nxt_wasm_send_headers() in Unit + uwr_http_send_headers(ctx); + + // This calls nxt_wasm_send_response() in Unit + uwr_http_send_response(ctx); + + // This calls nxt_wasm_response_end() in Unit + uwr_http_response_end(); + + return 0; +} diff --git a/examples/rust/echo-request-wbody/unit-wasm-conf.json b/examples/rust/echo-request-wbody/unit-wasm-conf.json new file mode 100644 index 0000000..cb799ee --- /dev/null +++ b/examples/rust/echo-request-wbody/unit-wasm-conf.json @@ -0,0 +1,36 @@ +{ + "listeners": { + "[::1]:8888": { + "pass": "routes" + } + }, + + "settings": { + "http": { + "max_body_size": 1073741824 + } + }, + + "routes": [ + { + "match": { + "uri": "/echo*" + }, + "action": { + "pass": "applications/rust-echo-request" + } + } + ], + + "applications": { + "rust-echo-request": { + "type": "wasm", + "module": "/home/timo/unit1.31/unit-wasm/examples/rust/echo-request-wbody/target/wasm32-wasi/debug/rust_echo_request.wasm", + "request_handler": "uwr_request_handler", + "malloc_handler": "luw_malloc_handler", + "free_handler": "luw_free_handler", + "module_init_handler": "uwr_module_init_handler", + "module_end_handler": "uwr_module_end_handler" + } + } +} -- cgit