summaryrefslogtreecommitdiff
path: root/c/wasi-http/0.2.0/download-test/component.c
blob: 78981edb4006c9d181aa2e6101df9c7be323c1fc (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
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);
}