diff options
author | Andrew Clayton <a.clayton@nginx.com> | 2023-08-02 17:03:48 +0100 |
---|---|---|
committer | Andrew Clayton <a.clayton@nginx.com> | 2023-08-21 23:24:12 +0100 |
commit | d6ed6a219b31a58526721f96195c80061d41ce54 (patch) | |
tree | 17a1fd6ecf72a327916ff0f8bc7aaf85b981ceff /examples/c/luw-upload-reflector.c | |
download | unit-wasm-0.1.0.tar.gz unit-wasm-0.1.0.tar.bz2 |
Initial commitv0.1.0
libunit-wasm and example C and Rust WebAssembly modules for NGINX Unit.
Co-developed-by: Timo Stark <t.stark@nginx.com>
Co-developed-by: Liam Crilly <liam@nginx.com>
Signed-off-by: Andrew Clayton <a.clayton@nginx.com>
Diffstat (limited to 'examples/c/luw-upload-reflector.c')
-rw-r--r-- | examples/c/luw-upload-reflector.c | 101 |
1 files changed, 101 insertions, 0 deletions
diff --git a/examples/c/luw-upload-reflector.c b/examples/c/luw-upload-reflector.c new file mode 100644 index 0000000..95bc514 --- /dev/null +++ b/examples/c/luw-upload-reflector.c @@ -0,0 +1,101 @@ +/* SPDX-License-Identifier: Apache-2.0 */ + +/* + * examples/c/luw-upload-reflector.c - Example of writing a WASM module for + * use with Unit using libunit-wasm + * + * Copyright (C) Andrew Clayton + * Copyright (C) F5, Inc. + */ + +#define _XOPEN_SOURCE 500 + +#include <stdio.h> +#include <stdlib.h> + +#include "unit/unit-wasm.h" + +static luw_ctx_t ctx; + +static size_t total_response_sent; + +static u8 *request_buf; + +/* + * While these first two _handlers_ aren't technically required, they + * could be combined or the code could just go in upload_reflector(), + * they demonstrate their use in ensuring the module is in the right + * state for a new request. + */ +__luw_export_name("luw_response_end_handler") +void luw_response_end_handler(void) +{ + total_response_sent = 0; +} + +__luw_export_name("luw_request_end_handler") +void luw_request_end_handler(void) +{ + if (!request_buf) + return; + + free(request_buf); + request_buf = NULL; +} + +static int upload_reflector(luw_ctx_t *ctx) +{ + size_t write_bytes; + + /* Send headers */ + if (total_response_sent == 0) { + static const char *defct = "application/octet-stream"; + const char *ct = luw_http_hdr_get_value(ctx, "Content-Type"); + char clen[32]; + + snprintf(clen, sizeof(clen), "%lu", + luw_get_http_content_len(ctx)); + + luw_http_init_headers(ctx, 2, 0); + luw_http_add_header(ctx, 0, "Content-Type", ct ? ct : defct); + luw_http_add_header(ctx, 1, "Content-Length", clen); + luw_http_send_headers(ctx); + } + + write_bytes = luw_mem_fill_buf_from_req(ctx, total_response_sent); + total_response_sent += write_bytes; + + luw_http_send_response(ctx); + + if (total_response_sent == luw_get_http_content_len(ctx)) { + /* Tell Unit no more data to send */ + luw_http_response_end(); + } + + return 0; +} + +__luw_export_name("luw_request_handler") +int luw_request_handler(u8 *addr) +{ + if (!request_buf) { + luw_init_ctx(&ctx, addr, 0 /* Response offset */); + /* + * Take a copy of the request and use that, we do this + * in APPEND mode so we can build up request_buf from + * multiple requests. + * + * Just allocate memory for the total amount of data we + * expect to get, this includes the request structure + * itself as well as any body content. + */ + luw_set_req_buf(&ctx, &request_buf, + LUW_SRB_APPEND|LUW_SRB_ALLOC|LUW_SRB_FULL_SIZE); + } else { + luw_req_buf_append(&ctx, addr); + } + + upload_reflector(&ctx); + + return 0; +} |