summaryrefslogtreecommitdiffhomepage
path: root/examples/c/luw-upload-reflector.c
diff options
context:
space:
mode:
authorAndrew Clayton <a.clayton@nginx.com>2023-08-02 17:03:48 +0100
committerAndrew Clayton <a.clayton@nginx.com>2023-08-21 23:24:12 +0100
commitd6ed6a219b31a58526721f96195c80061d41ce54 (patch)
tree17a1fd6ecf72a327916ff0f8bc7aaf85b981ceff /examples/c/luw-upload-reflector.c
downloadunit-wasm-c43c6b57d70ae3a2cb3a52f5f991cd68fd39b47d.tar.gz
unit-wasm-c43c6b57d70ae3a2cb3a52f5f991cd68fd39b47d.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.c101
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;
+}