summaryrefslogtreecommitdiff
path: root/c/wasi-http/0.2.0
diff options
context:
space:
mode:
authorAndrew Clayton <a.clayton@nginx.com>2024-09-05 17:29:51 +0100
committerAndrew Clayton <a.clayton@nginx.com>2024-09-05 19:30:15 +0100
commit7d0de8d48e202e32bb2879f706a47a3477cd8e2e (patch)
tree5a8667be12cf8a84e5e639e33ff8c97d756ead75 /c/wasi-http/0.2.0
parentd2517348a45064245e5f114fbdaee7c6c970b1b2 (diff)
downloadproject_blackbird-7d0de8d48e202e32bb2879f706a47a3477cd8e2e.tar.gz
project_blackbird-7d0de8d48e202e32bb2879f706a47a3477cd8e2e.tar.bz2
w-h/0.2.0: Add an example of a file download
This also shows an example of (at least the best I could figure out) how to send an error 4xx/5xx response back. Signed-off-by: Andrew Clayton <a.clayton@nginx.com>
Diffstat (limited to 'c/wasi-http/0.2.0')
-rw-r--r--c/wasi-http/0.2.0/download-test/Makefile29
-rw-r--r--c/wasi-http/0.2.0/download-test/component.c138
2 files changed, 167 insertions, 0 deletions
diff --git a/c/wasi-http/0.2.0/download-test/Makefile b/c/wasi-http/0.2.0/download-test/Makefile
new file mode 100644
index 0000000..f9e3bfe
--- /dev/null
+++ b/c/wasi-http/0.2.0/download-test/Makefile
@@ -0,0 +1,29 @@
+# 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 -g --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
+ /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 ../../adaptors/24.0.0/wasi_snapshot_preview1.reactor.wasm -o component.wasm
+
+clean:
+ rm -f component.wasm module.wasm proxy*
diff --git a/c/wasi-http/0.2.0/download-test/component.c b/c/wasi-http/0.2.0/download-test/component.c
new file mode 100644
index 0000000..78981ed
--- /dev/null
+++ b/c/wasi-http/0.2.0/download-test/component.c
@@ -0,0 +1,138 @@
+/* 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 <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include "proxy.h"
+
+#define IMG_SZ (256 * 1024*1024UL)
+
+#define ex(...) \
+ do { \
+ printf(__VA_ARGS__); \
+ exit(EXIT_FAILURE); \
+ } while (0);
+
+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)
+{
+ int fd;
+ bool ok;
+ char clen[32];
+ char *buf;
+ 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;
+
+ (void)request;
+
+ buf = malloc(IMG_SZ);
+ fd = open("/var/tmp/img", O_RDONLY);
+ if (fd == -1) {
+ wasi_http_types_status_code_t sc;
+
+ printf("E: %s (/var/tmp/img)\n", strerror(errno));
+
+ switch (errno) {
+ case EACCES:
+ case EFAULT:
+ case EPERM:
+ sc = 403;
+ break;
+ case EBADF:
+ case ENAMETOOLONG:
+ case ENODEV:
+ case ENOENT:
+ case ENOTDIR:
+ sc = 404;
+ break;
+ default:
+ sc = 500;
+ }
+
+ fields = wasi_http_types_constructor_fields();
+ resp = wasi_http_types_constructor_outgoing_response(fields);
+ b_resp = wasi_http_types_borrow_outgoing_response(resp);
+ wasi_http_types_method_outgoing_response_set_status_code(b_resp,
+ sc);
+ rerr.val.ok = resp;
+
+ goto out_response;
+ }
+
+ read(fd, buf, IMG_SZ);
+ close(fd);
+
+ fields = wasi_http_types_constructor_fields();
+ b_fields = wasi_http_types_borrow_fields(fields);
+
+ proxy_string_set((proxy_string_t *)&key, "Content-Type");
+ proxy_string_set((proxy_string_t *)&value, "application/octet-stream");
+
+ ok = wasi_http_types_method_fields_append(b_fields, &key, &value,
+ &hdr_err);
+ if (!ok)
+ ex("wasi_http_types_method_fields_append(Content-Type) failed\n");
+
+ proxy_string_set((proxy_string_t *)&key, "Content-Length");
+ sprintf(clen, "%zu", IMG_SZ);
+ 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(Content-Length) failed\n");
+
+ resp = wasi_http_types_constructor_outgoing_response(fields);
+ rerr.val.ok = resp;
+
+ 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 = IMG_SZ;
+ stream_data.ptr = (uint8_t *)buf;
+ ok = wasi_io_streams_method_output_stream_write(b_out_stream,
+ &stream_data,
+ &stream_err);
+ if (!ok)
+ ex("wasi_io_streams_method_output_stream_blocking_write_and_flush() failed\n");
+
+out_response:
+
+ wasi_http_types_static_response_outparam_set(response_out, &rerr);
+
+ free(buf);
+}