diff options
author | Andrew Clayton <a.clayton@nginx.com> | 2024-09-05 17:29:51 +0100 |
---|---|---|
committer | Andrew Clayton <a.clayton@nginx.com> | 2024-09-05 19:30:15 +0100 |
commit | 7d0de8d48e202e32bb2879f706a47a3477cd8e2e (patch) | |
tree | 5a8667be12cf8a84e5e639e33ff8c97d756ead75 /c | |
parent | d2517348a45064245e5f114fbdaee7c6c970b1b2 (diff) | |
download | project_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')
-rw-r--r-- | c/wasi-http/0.2.0/download-test/Makefile | 29 | ||||
-rw-r--r-- | c/wasi-http/0.2.0/download-test/component.c | 138 |
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); +} |