summaryrefslogblamecommitdiff
path: root/c/wasi-http/0.2.0/download-test/component.c
blob: 78981edb4006c9d181aa2e6101df9c7be323c1fc (plain) (tree)









































































































































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