summaryrefslogtreecommitdiff
path: root/c/wasi-http/0.2.0/echo-request
diff options
context:
space:
mode:
authorAndrew Clayton <a.clayton@nginx.com>2024-02-06 21:32:08 +0000
committerAndrew Clayton <a.clayton@nginx.com>2024-02-06 21:32:08 +0000
commit81bbdb1c65b381b8af77f695979752e13f64458b (patch)
tree1bb00d2ed08e5f45ef5f12714b62e0a232d2919d /c/wasi-http/0.2.0/echo-request
parent031044579c81c3114dbd66d93b73a124de1bef7d (diff)
downloadproject_blackbird-81bbdb1c65b381b8af77f695979752e13f64458b.tar.gz
project_blackbird-81bbdb1c65b381b8af77f695979752e13f64458b.tar.bz2
Add a wasi-http 0.2.0 echo-request component in C
This adds a WASI 0.2.0 version of c/wasi-http/echo-request, although there is no change in component.c, you do now need to link against the 'proxy' adaptor (which is included). This is for running under wasmtime 17. Signed-off-by: Andrew Clayton <a.clayton@nginx.com>
Diffstat (limited to '')
-rw-r--r--c/wasi-http/0.2.0/echo-request/Makefile31
-rw-r--r--c/wasi-http/0.2.0/echo-request/component.c167
-rw-r--r--c/wasi-http/0.2.0/echo-request/wasi_snapshot_preview1.proxy.wasmbin0 -> 28355 bytes
3 files changed, 198 insertions, 0 deletions
diff --git a/c/wasi-http/0.2.0/echo-request/Makefile b/c/wasi-http/0.2.0/echo-request/Makefile
new file mode 100644
index 0000000..6e2d873
--- /dev/null
+++ b/c/wasi-http/0.2.0/echo-request/Makefile
@@ -0,0 +1,31 @@
+# Look for wasi-sysroot in some common places, falling back
+# to provided WASI_SYSROOT
+ifneq ("$(wildcard /usr/wasm32-wasi)", "")
+ # Fedora
+ WASI_SYSROOT ?= /usr/wasm32-wasi
+endif
+
+export WASI_SYSROOT
+
+CC = clang
+CFLAGS = -Wall -Wextra --target=wasm32-wasi --sysroot=$(WASI_SYSROOT)
+LDFLAGS = -Wl,--no-entry,--export=__heap_base,--export=__data_end,--export=malloc,--export=free,--stack-first,-z,stack-size=$$((8*1024*1024)) -mexec-model=reactor --rtlib=compiler-rt
+
+all: component.wasm
+
+bindgen:
+ /home/andrew/src/c/wasm/git/wit-bindgen/target/release/wit-bindgen c /home/andrew/src/c/wasm/git/wasi-http/wit --autodrop-borrows yes --world wasi:http/proxy
+ sed -i 's/_0_2_0//g' proxy.[ch]
+ sed -i 's/_0_2_0//g' proxy.[ch]
+ /home/andrew/src/c/wasm/git/wit-bindgen/target/release/wit-bindgen markdown /home/andrew/src/c/wasm/git/wasi-http/wit --world wasi:http/proxy
+
+.PHONY:
+module.wasm: bindgen
+ $(CC) $(CFLAGS) $(LDFLAGS) -o $@ proxy.c proxy_component_type.o component.c
+
+.PHONY:
+component.wasm: module.wasm
+ /home/andrew/src/c/wasm/git/wasm-tools/target/release/wasm-tools component new module.wasm --adapt wasi_snapshot_preview1.proxy.wasm -o component.wasm
+
+clean:
+ rm -f component.wasm module.wasm proxy*
diff --git a/c/wasi-http/0.2.0/echo-request/component.c b/c/wasi-http/0.2.0/echo-request/component.c
new file mode 100644
index 0000000..6f4c626
--- /dev/null
+++ b/c/wasi-http/0.2.0/echo-request/component.c
@@ -0,0 +1,167 @@
+/* SPDX-License-Identifier: Apache-2.0 */
+
+/*
+ * component.c - Example of writing a wasi-http Wasm component
+ *
+ * Copyright (C) Andrew Clayton
+ * Copyright (C) F5, Inc.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <string.h>
+
+#include "proxy.h"
+
+#define ex(...) \
+ do { \
+ printf(__VA_ARGS__); \
+ exit(EXIT_FAILURE); \
+ } while (0);
+
+static const struct {
+ const char *method;
+} http_method_map[] = {
+ [WASI_HTTP_TYPES_METHOD_GET] = { "GET" },
+ [WASI_HTTP_TYPES_METHOD_HEAD] = { "HEAD" },
+ [WASI_HTTP_TYPES_METHOD_POST] = { "POST" },
+ [WASI_HTTP_TYPES_METHOD_PUT] = { "PUT" },
+ [WASI_HTTP_TYPES_METHOD_DELETE] = { "DELETE" },
+ [WASI_HTTP_TYPES_METHOD_CONNECT] = { "CONNECT" },
+ [WASI_HTTP_TYPES_METHOD_OPTIONS] = { "OPTIONS" },
+ [WASI_HTTP_TYPES_METHOD_TRACE] = { "TRACE" },
+ [WASI_HTTP_TYPES_METHOD_PATCH] = { "PATCH" },
+ [WASI_HTTP_TYPES_METHOD_OTHER] = { "OTHER" }
+};
+
+void exports_wasi_http_incoming_handler_handle(
+ exports_wasi_http_incoming_handler_own_incoming_request_t request,
+ exports_wasi_http_incoming_handler_own_response_outparam_t response_out)
+{
+ bool ok;
+ FILE *out;
+ size_t size;
+ char *out_ptr;
+ char *ptr;
+ char clen[32];
+ wasi_http_types_borrow_incoming_request_t b_req;
+ wasi_http_types_own_headers_t hdrs;
+ wasi_http_types_borrow_fields_t b_hdrs;
+ wasi_http_types_own_incoming_body_t r_body;
+ wasi_http_types_borrow_incoming_body_t b_r_body;
+ wasi_http_types_own_outgoing_response_t resp;
+ wasi_http_types_borrow_outgoing_response_t b_resp;
+ wasi_http_types_own_fields_t fields;
+ wasi_http_types_borrow_fields_t b_fields;
+ wasi_http_types_result_own_outgoing_response_error_code_t rerr = { };
+ wasi_http_types_own_outgoing_body_t body;
+ wasi_http_types_borrow_outgoing_body_t b_body;
+ wasi_io_streams_own_output_stream_t out_stream;
+ wasi_io_streams_borrow_output_stream_t b_out_stream;
+ proxy_list_u8_t stream_data;
+ wasi_io_streams_stream_error_t stream_err;
+ wasi_http_types_header_error_t hdr_err;
+ wasi_http_types_field_key_t key;
+ wasi_http_types_field_value_t value;
+ wasi_http_types_method_t method;
+ proxy_list_tuple2_field_key_field_value_t fvk;
+ wasi_http_types_own_input_stream_t in_stream;
+ wasi_io_streams_borrow_input_stream_t b_in_stream;
+ proxy_list_u8_t data;
+ wasi_io_streams_stream_error_t in_stream_err;
+ proxy_string_t prstr;
+
+ b_req = wasi_http_types_borrow_incoming_request(request);
+
+ out = open_memstream(&out_ptr, &size);
+
+#define BUF_ADD(fmt, ...) \
+ fprintf(out, fmt, ##__VA_ARGS__);
+
+ BUF_ADD("*** Welcome to WebAssembly with wasi-http / C ***\n\n");
+
+ BUF_ADD("[Request Info]\n");
+ wasi_http_types_method_incoming_request_path_with_query(b_req, &prstr);
+ BUF_ADD("REQUEST_PATH = %.*s\n", (int)prstr.len, prstr.ptr);
+ wasi_http_types_method_incoming_request_method(b_req, &method);
+ BUF_ADD("METHOD = %s\n", http_method_map[method.tag].method);
+ ptr = memchr(prstr.ptr, '?', prstr.len);
+ BUF_ADD("QUERY = %.*s\n",
+ ptr ? (int)(((char *)(prstr.ptr + prstr.len)) - ptr - 1) : 0,
+ ptr ? ptr + 1 : "");
+
+ BUF_ADD("\n[Request Headers]\n");
+ hdrs = wasi_http_types_method_incoming_request_headers(b_req);
+ b_hdrs = wasi_http_types_borrow_fields(hdrs);
+
+ wasi_http_types_method_fields_entries(b_hdrs, &fvk);
+ for (size_t i = 0; i < fvk.len; i++)
+ BUF_ADD("%.*s = %.*s\n",
+ (int)fvk.ptr[i].f0.len, fvk.ptr[i].f0.ptr,
+ (int)fvk.ptr[i].f1.len, fvk.ptr[i].f1.ptr);
+
+ proxy_list_tuple2_field_key_field_value_free(&fvk);
+
+ ok = wasi_http_types_method_incoming_request_consume(b_req, &r_body);
+ if (!ok)
+ ex("wasi_http_types_method_incoming_request_consume() failed\n");
+ b_r_body = wasi_http_types_borrow_incoming_body(r_body);
+ ok = wasi_http_types_method_incoming_body_stream(b_r_body, &in_stream);
+ if (!ok)
+ ex("wasi_http_types_method_incoming_body_stream() failed\n");
+ b_in_stream = wasi_io_streams_borrow_input_stream(in_stream);
+
+ ok = wasi_io_streams_method_input_stream_blocking_read(b_in_stream,
+ 8 * 1024*1024,
+ &data,
+ &in_stream_err);
+
+ if (method.tag == WASI_HTTP_TYPES_METHOD_POST ||
+ method.tag == WASI_HTTP_TYPES_METHOD_PUT) {
+ BUF_ADD("\n[%s data]\n",
+ http_method_map[method.tag].method);
+ BUF_ADD("%.*s\n", (int)data.len, data.ptr);
+ }
+
+ fclose(out);
+
+ fields = wasi_http_types_constructor_fields();
+ b_fields = wasi_http_types_borrow_fields(fields);
+
+ proxy_string_set((proxy_string_t *)&key, "Content-Length");
+ sprintf(clen, "%zu", size);
+ proxy_string_set((proxy_string_t *)&value, clen);
+
+ ok = wasi_http_types_method_fields_append(b_fields, &key, &value,
+ &hdr_err);
+ if (!ok)
+ ex("wasi_http_types_method_fields_append() failed\n");
+
+ resp = wasi_http_types_constructor_outgoing_response(fields);
+
+ b_resp = wasi_http_types_borrow_outgoing_response(resp);
+ ok = wasi_http_types_method_outgoing_response_body(b_resp, &body);
+ if (!ok)
+ ex("wasi_http_types_method_outgoing_response_body() failed\n");
+ b_body = wasi_http_types_borrow_outgoing_body(body);
+
+ ok = wasi_http_types_method_outgoing_body_write(b_body, &out_stream);
+ if (!ok)
+ ex("wasi_http_types_method_outgoing_body_write() failed\n");
+ b_out_stream = wasi_io_streams_borrow_output_stream(out_stream);
+
+ stream_data.len = size;
+ stream_data.ptr = (uint8_t *)out_ptr;
+ ok = wasi_io_streams_method_output_stream_blocking_write_and_flush(
+ b_out_stream,
+ &stream_data,
+ &stream_err);
+ if (!ok)
+ ex("wasi_io_streams_method_output_stream_blocking_write_and_flush() failed\n");
+
+ free(out_ptr);
+
+ wasi_http_types_static_response_outparam_set(response_out, &rerr);
+}
diff --git a/c/wasi-http/0.2.0/echo-request/wasi_snapshot_preview1.proxy.wasm b/c/wasi-http/0.2.0/echo-request/wasi_snapshot_preview1.proxy.wasm
new file mode 100644
index 0000000..5f71e3e
--- /dev/null
+++ b/c/wasi-http/0.2.0/echo-request/wasi_snapshot_preview1.proxy.wasm
Binary files differ