summaryrefslogblamecommitdiff
path: root/c/wasi-http/0.2.0/large-upload/component.c
blob: a4eeba69104cee04fc39a7d5636848a258bfd6a7 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16















                                                              
                  















                                                                                
                                                     













                                                                             



                                                                     

                                                            






























                                                                                



































                                                                                 
             



                                                                          
/* 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 ex(...) \
        do { \
                printf(__VA_ARGS__); \
		return; \
        } 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)
{
	wasi_http_types_borrow_incoming_request_t b_req;
	wasi_http_types_own_incoming_body_t r_body;
	wasi_http_types_borrow_incoming_body_t b_r_body;
	wasi_http_types_own_outgoing_response_t resp;
	wasi_http_types_result_own_outgoing_response_error_code_t rerr = { };
	wasi_http_types_own_fields_t hdrs;
	wasi_http_types_borrow_fields_t b_hdrs;
	wasi_http_types_own_fields_t fields;
	wasi_http_types_own_input_stream_t in_stream;
	wasi_io_streams_borrow_input_stream_t b_in_stream;
	wasi_io_streams_stream_error_t in_stream_err;
	proxy_list_u8_t data;
	proxy_list_field_value_t f_clen;
	unsigned long long total_bytes_wrote = 0;
	unsigned long long content_len;
	bool ok;
	int fd;

	fields = wasi_http_types_constructor_fields();
	resp = wasi_http_types_constructor_outgoing_response(fields);
	rerr.val.ok = resp;

	fd = open("/var/tmp/wasm-wasi-component-upload.dat",
		  O_CREAT|O_TRUNC|O_WRONLY, 0666);
	if (fd == -1) {
		wasi_http_types_status_code_t sc;
		wasi_http_types_borrow_outgoing_response_t b_resp;

		printf("E: %s (/var/tmp/wasm-wasi-component-upload.dat)\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;
		}

		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;
	}

	b_req = wasi_http_types_borrow_incoming_request(request);

	hdrs = wasi_http_types_method_incoming_request_headers(b_req);
	b_hdrs = wasi_http_types_borrow_fields(hdrs);

	wasi_http_types_method_fields_get(
			b_hdrs,
			&(proxy_string_t){ .ptr = (uint8_t *)"content-length",
					   .len = strlen("content-length") },
			&f_clen);

	content_len = strtoull((const char *)f_clen.ptr[0].ptr, NULL, 10);

	ok = wasi_http_types_method_incoming_request_consume(b_req, &r_body);
        if (!ok)
                ex("wasi_http_types_method_incoming_request_consume() failed\n");
        b_r_body = wasi_http_types_borrow_incoming_body(r_body);
        ok = wasi_http_types_method_incoming_body_stream(b_r_body, &in_stream);
        if (!ok)
                ex("wasi_http_types_method_incoming_body_stream() failed\n");
	b_in_stream = wasi_io_streams_borrow_input_stream(in_stream);

	do {
		ok = wasi_io_streams_method_input_stream_blocking_read(
							b_in_stream,
							8 * 1024*1024,
							&data,
							&in_stream_err);
		if (!ok)
			break;

		write(fd, data.ptr, data.len);
		total_bytes_wrote += data.len;
	} while (total_bytes_wrote < content_len);

out_response:
	wasi_http_types_static_response_outparam_set(response_out, &rerr);

	close(fd);
}