/* 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);
}