Line data Source code
1 : /*
2 : * lwan - web server
3 : * Copyright (c) 2012 L. A. F. Pereira <l@tia.mat.br>
4 : *
5 : * This program is free software; you can redistribute it and/or
6 : * modify it under the terms of the GNU General Public License
7 : * as published by the Free Software Foundation; either version 2
8 : * of the License, or any later version.
9 : *
10 : * This program is distributed in the hope that it will be useful,
11 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 : * GNU General Public License for more details.
14 : *
15 : * You should have received a copy of the GNU General Public License
16 : * along with this program; if not, write to the Free Software
17 : * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 : */
19 :
20 : #define _GNU_SOURCE
21 : #include <stdlib.h>
22 : #include <unistd.h>
23 :
24 : #include "lwan-private.h"
25 :
26 87 : LWAN_HANDLER(quit_lwan)
27 : {
28 87 : exit(0);
29 : return HTTP_OK;
30 : }
31 :
32 0 : LWAN_HANDLER(gif_beacon)
33 : {
34 : /*
35 : * 1x1 transparent GIF image generated with tinygif
36 : * http://www.perlmonks.org/?node_id=7974
37 : */
38 : static const unsigned char gif_beacon_data[] = {
39 : 0x47, 0x49, 0x46, 0x38, 0x39, 0x61, 0x01, 0x00, 0x01, 0x00, 0x90,
40 : 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x21, 0xF9, 0x04,
41 : 0x05, 0x10, 0x00, 0x00, 0x00, 0x2C, 0x00, 0x00, 0x00, 0x00, 0x01,
42 : 0x00, 0x01, 0x00, 0x00, 0x02, 0x02, 0x04, 0x01
43 : };
44 :
45 0 : response->mime_type = "image/gif";
46 0 : lwan_strbuf_set_static(response->buffer, (char*)gif_beacon_data, sizeof(gif_beacon_data));
47 :
48 0 : return HTTP_OK;
49 : }
50 :
51 1 : LWAN_HANDLER(test_chunked_encoding)
52 : {
53 : int i;
54 :
55 1 : response->mime_type = "text/plain";
56 :
57 1 : lwan_strbuf_printf(response->buffer, "Testing chunked encoding! First chunk\n");
58 1 : lwan_response_send_chunk(request);
59 :
60 12 : for (i = 0; i <= 10; i++) {
61 11 : lwan_strbuf_printf(response->buffer, "*This is chunk %d*\n", i);
62 11 : lwan_response_send_chunk(request);
63 : }
64 :
65 1 : lwan_strbuf_printf(response->buffer, "Last chunk\n");
66 1 : lwan_response_send_chunk(request);
67 :
68 1 : return HTTP_OK;
69 : }
70 :
71 0 : LWAN_HANDLER(test_server_sent_event)
72 : {
73 : int i;
74 :
75 0 : for (i = 0; i <= 10; i++) {
76 0 : lwan_strbuf_printf(response->buffer, "Current value is %d", i);
77 0 : lwan_response_send_event(request, "currval");
78 : }
79 :
80 0 : return HTTP_OK;
81 : }
82 :
83 10 : LWAN_HANDLER(test_proxy)
84 : {
85 10 : struct lwan_key_value *headers = coro_malloc(request->conn->coro, sizeof(*headers) * 2);
86 10 : if (UNLIKELY(!headers))
87 0 : return HTTP_INTERNAL_ERROR;
88 :
89 10 : char *buffer = coro_malloc(request->conn->coro, INET6_ADDRSTRLEN);
90 10 : if (UNLIKELY(!buffer))
91 0 : return HTTP_INTERNAL_ERROR;
92 :
93 10 : headers[0].key = "X-Proxy";
94 10 : headers[0].value = (char*) lwan_request_get_remote_address(request, buffer);
95 10 : headers[1].key = NULL;
96 10 : headers[1].value = NULL;
97 :
98 10 : response->headers = headers;
99 :
100 10 : return HTTP_OK;
101 : }
102 :
103 1 : LWAN_HANDLER(test_post_will_it_blend)
104 : {
105 : static const char type[] = "application/json";
106 : static const char request_body[] = "{\"will-it-blend\": true}";
107 : static const char response_body[] = "{\"did-it-blend\": \"oh-hell-yeah\"}";
108 : const struct lwan_value *content_type =
109 1 : lwan_request_get_content_type(request);
110 1 : const struct lwan_value *body = lwan_request_get_request_body(request);
111 :
112 1 : if (!content_type->value)
113 0 : return HTTP_BAD_REQUEST;
114 1 : if (content_type->len != sizeof(type) - 1)
115 0 : return HTTP_BAD_REQUEST;
116 1 : if (memcmp(content_type->value, type, sizeof(type) - 1) != 0)
117 0 : return HTTP_BAD_REQUEST;
118 :
119 1 : if (!body->value)
120 0 : return HTTP_BAD_REQUEST;
121 1 : if (body->len != sizeof(request_body) - 1)
122 0 : return HTTP_BAD_REQUEST;
123 1 : if (memcmp(body->value, request_body, sizeof(request_body) - 1) != 0)
124 0 : return HTTP_BAD_REQUEST;
125 :
126 1 : response->mime_type = type;
127 1 : lwan_strbuf_set_static(response->buffer, response_body,
128 : sizeof(response_body) - 1);
129 :
130 1 : return HTTP_OK;
131 : }
132 :
133 5 : LWAN_HANDLER(test_post_big)
134 : {
135 : static const char type[] = "x-test/trololo";
136 5 : size_t i, sum = 0;
137 : const struct lwan_value *content_type =
138 5 : lwan_request_get_content_type(request);
139 5 : const struct lwan_value *body = lwan_request_get_request_body(request);
140 :
141 5 : if (!content_type->value)
142 0 : return HTTP_BAD_REQUEST;
143 5 : if (content_type->len != sizeof(type) - 1)
144 0 : return HTTP_BAD_REQUEST;
145 5 : if (memcmp(content_type->value, type, sizeof(type) - 1) != 0)
146 0 : return HTTP_BAD_REQUEST;
147 :
148 222225 : for (i = 0; i < body->len; i++)
149 222220 : sum += (size_t)body->value[i];
150 :
151 5 : response->mime_type = "application/json";
152 5 : lwan_strbuf_printf(response->buffer, "{\"received\": %zu, \"sum\": %zu}",
153 5 : body->len, sum);
154 :
155 5 : return HTTP_OK;
156 : }
157 :
158 390 : LWAN_HANDLER(hello_world)
159 : {
160 : struct lwan_key_value *iter;
161 : static struct lwan_key_value headers[] = {
162 : { .key = "X-The-Answer-To-The-Universal-Question", .value = "42" },
163 : { NULL, NULL }
164 : };
165 390 : response->headers = headers;
166 390 : response->mime_type = "text/plain";
167 :
168 390 : request->flags |= RESPONSE_INCLUDE_REQUEST_ID;
169 :
170 390 : const char *name = lwan_request_get_query_param(request, "name");
171 390 : if (name)
172 276 : lwan_strbuf_printf(response->buffer, "Hello, %s!", name);
173 : else
174 114 : lwan_strbuf_set_static(response->buffer, "Hello, world!", sizeof("Hello, world!") -1);
175 :
176 390 : const char *dump_vars = lwan_request_get_query_param(request, "dump_vars");
177 390 : if (!dump_vars)
178 367 : goto end;
179 :
180 23 : lwan_strbuf_append_strz(response->buffer, "\n\nCookies\n");
181 23 : lwan_strbuf_append_strz(response->buffer, "-------\n\n");
182 :
183 26 : LWAN_ARRAY_FOREACH(lwan_request_get_cookies(request), iter) {
184 3 : lwan_strbuf_append_printf(response->buffer,
185 : "Key = \"%s\"; Value = \"%s\"\n", iter->key, iter->value);
186 : }
187 :
188 23 : lwan_strbuf_append_strz(response->buffer, "\n\nQuery String Variables\n");
189 23 : lwan_strbuf_append_strz(response->buffer, "----------------------\n\n");
190 :
191 69 : LWAN_ARRAY_FOREACH(lwan_request_get_query_params(request), iter) {
192 46 : lwan_strbuf_append_printf(response->buffer,
193 : "Key = \"%s\"; Value = \"%s\"\n", iter->key, iter->value);
194 : }
195 :
196 23 : if (lwan_request_get_method(request) == REQUEST_METHOD_POST) {
197 1 : lwan_strbuf_append_strz(response->buffer, "\n\nPOST data\n");
198 1 : lwan_strbuf_append_strz(response->buffer, "---------\n\n");
199 :
200 3 : LWAN_ARRAY_FOREACH(lwan_request_get_post_params(request), iter) {
201 2 : lwan_strbuf_append_printf(response->buffer,
202 : "Key = \"%s\"; Value = \"%s\"\n", iter->key, iter->value);
203 : }
204 : }
205 :
206 23 : const char *dump_request_id = lwan_request_get_query_param(request, "dump_request_id");
207 23 : if (dump_request_id && streq(dump_request_id, "1")) {
208 20 : lwan_strbuf_append_printf(response->buffer, "\nRequest ID: <<%016lx>>",
209 : lwan_request_get_id(request));
210 : }
211 :
212 3 : end:
213 390 : return HTTP_OK;
214 : }
215 :
216 1 : LWAN_HANDLER(sleep)
217 : {
218 1 : const char *ms_param = lwan_request_get_query_param(request, "ms");
219 : uint64_t ms;
220 :
221 1 : if (!ms_param)
222 0 : return HTTP_INTERNAL_ERROR;
223 :
224 1 : ms = (uint64_t)parse_long(ms_param, 0);
225 1 : response->mime_type = "text/plain";
226 :
227 1 : if (ms) {
228 : struct timespec t1, t2;
229 : int64_t diff_ms;
230 :
231 1 : clock_gettime(CLOCK_MONOTONIC, &t1);
232 :
233 1 : lwan_request_sleep(request, ms);
234 :
235 1 : clock_gettime(CLOCK_MONOTONIC, &t2);
236 1 : diff_ms = (t2.tv_sec - t1.tv_sec) * 1000;
237 1 : diff_ms += (t2.tv_nsec - t1.tv_nsec) / 1000000;
238 :
239 1 : lwan_strbuf_printf(response->buffer,
240 : "Returned from sleep. diff_ms = %"PRIi64, diff_ms);
241 : } else {
242 0 : lwan_strbuf_set_staticz(response->buffer, "Did not sleep");
243 : }
244 :
245 1 : return HTTP_OK;
246 : }
247 :
248 2 : LWAN_HANDLER(custom_header)
249 : {
250 2 : const char *hdr = lwan_request_get_query_param(request, "hdr");
251 :
252 2 : if (!hdr)
253 0 : return HTTP_NOT_FOUND;
254 :
255 2 : const char *val = lwan_request_get_header(request, hdr);
256 2 : if (!val)
257 1 : return HTTP_NOT_FOUND;
258 :
259 1 : response->mime_type = "text/plain";
260 1 : lwan_strbuf_printf(response->buffer, "Header value: '%s'", val);
261 1 : return HTTP_OK;
262 : }
263 :
264 : int
265 87 : main()
266 : {
267 : struct lwan l;
268 :
269 87 : lwan_init(&l);
270 87 : lwan_main_loop(&l);
271 0 : lwan_shutdown(&l);
272 :
273 0 : return EXIT_SUCCESS;
274 : }
|