summaryrefslogtreecommitdiffhomepage
path: root/examples/c/luw-echo-request.c
blob: 66c3880f11d6595798429a7a2374ab348c27a19d (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
/* SPDX-License-Identifier: Apache-2.0 */

/*
 * examples/c/luw-echo-request.c - Example of writing a WASM module for use
 *				   with Unit using libunit-wasm
 *
 * Copyright (C) Andrew Clayton
 * Copyright (C) F5, Inc.
 */

#define _XOPEN_SOURCE	500

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>

#include "unit/unit-wasm.h"

static u8 *request_buf;

__luw_export_name("luw_module_end_handler")
void luw_module_end_handler(void)
{
	free(request_buf);
}

__luw_export_name("luw_module_init_handler")
void luw_module_init_handler(void)
{
	request_buf = malloc(luw_mem_get_init_size());
}

static bool hdr_iter_func(luw_ctx_t *ctx, const char *name, const char *value,
			  void *user_data __luw_unused)
{
	luw_mem_writep(ctx, "%s = %s\n", name, value);

	return true;
}

__luw_export_name("luw_request_handler")
int luw_request_handler(u8 *addr)
{
	luw_ctx_t ctx;
	char clen[32];
	const char *method;

	luw_init_ctx(&ctx, addr, 4096 /* Response offset */);
	/* Take a copy of the request and use that */
	luw_set_req_buf(&ctx, &request_buf, LUW_SRB_NONE);

#define BUF_ADD(fmt, member) \
	luw_mem_writep(&ctx, fmt, luw_get_http_##member(&ctx));

	luw_mem_writep(&ctx,
		       " *** Welcome to WebAssembly on Unit! "
		       "[libunit-wasm (%d.%d.%d/%#0.8x)] ***\n\n",
		       LUW_VERSION_MAJOR, LUW_VERSION_MINOR, LUW_VERSION_PATCH,
		       LUW_VERSION_NUMBER);

	luw_mem_writep(&ctx, "[Request Info]\n");
	BUF_ADD("REQUEST_PATH = %s\n", path);
	BUF_ADD("METHOD       = %s\n", method);
	BUF_ADD("VERSION      = %s\n", version);
	BUF_ADD("QUERY        = %s\n", query);
	BUF_ADD("REMOTE       = %s\n", remote);
	BUF_ADD("LOCAL_ADDR   = %s\n", local_addr);
	BUF_ADD("LOCAL_PORT   = %s\n", local_port);
	BUF_ADD("SERVER_NAME  = %s\n", server_name);

	luw_mem_writep(&ctx, "\n[Request Headers]\n");

	luw_http_hdr_iter(&ctx, hdr_iter_func, NULL);

	method = luw_get_http_method(&ctx);
	if (memcmp(method, "POST", strlen(method)) == 0 ||
	    memcmp(method, "PUT", strlen(method)) == 0) {
		luw_mem_writep(&ctx, "\n[%s data]\n", method);
		luw_mem_writep_data(&ctx, luw_get_http_content(&ctx),
				    luw_get_http_content_len(&ctx));
		luw_mem_writep(&ctx, "\n");
	}

	luw_http_init_headers(&ctx, 2, 0);

	snprintf(clen, sizeof(clen), "%lu", luw_get_response_data_size(&ctx));
	luw_http_add_header(&ctx, "Content-Type", "text/plain");
	luw_http_add_header(&ctx, "Content-Length", clen);

	luw_http_send_headers(&ctx);

	luw_http_send_response(&ctx);
	/* Tell Unit no more data to send */
	luw_http_response_end();

	return 0;
}