]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // Copyright (c) 2004-2009 Sergey Lyubka |
2 | // | |
3 | // Permission is hereby granted, free of charge, to any person obtaining a copy | |
4 | // of this software and associated documentation files (the "Software"), to deal | |
5 | // in the Software without restriction, including without limitation the rights | |
6 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
7 | // copies of the Software, and to permit persons to whom the Software is | |
8 | // furnished to do so, subject to the following conditions: | |
9 | // | |
10 | // The above copyright notice and this permission notice shall be included in | |
11 | // all copies or substantial portions of the Software. | |
12 | // | |
13 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
14 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
15 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
16 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
17 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
18 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |
19 | // THE SOFTWARE. | |
20 | // | |
21 | // Unit test for the civetweb web server. Tests embedded API. | |
22 | ||
23 | ||
24 | #include <stdlib.h> | |
25 | #include <stdio.h> | |
26 | #include <string.h> | |
27 | #ifndef _WIN32 | |
28 | #include <unistd.h> | |
29 | #endif | |
30 | ||
31 | #include "civetweb.h" | |
32 | ||
33 | #if !defined(LISTENING_PORT) | |
34 | #define LISTENING_PORT "23456" | |
35 | #endif | |
36 | ||
37 | static const char *standard_reply = "HTTP/1.1 200 OK\r\n" | |
38 | "Content-Type: text/plain\r\n" | |
39 | "Connection: close\r\n\r\n"; | |
40 | ||
41 | static void test_get_var(struct mg_connection *conn, | |
42 | const struct mg_request_info *ri) { | |
43 | char *var, *buf; | |
44 | size_t buf_len; | |
45 | const char *cl; | |
46 | int var_len; | |
47 | ||
48 | mg_printf(conn, "%s", standard_reply); | |
49 | ||
50 | buf_len = 0; | |
51 | var = buf = NULL; | |
52 | cl = mg_get_header(conn, "Content-Length"); | |
53 | mg_printf(conn, "cl: %p\n", cl); | |
54 | if ((!strcmp(ri->request_method, "POST") || | |
55 | !strcmp(ri->request_method, "PUT")) | |
56 | && cl != NULL) { | |
57 | buf_len = atoi(cl); | |
58 | buf = malloc(buf_len); | |
59 | /* Read in two pieces, to test continuation */ | |
60 | if (buf_len > 2) { | |
61 | mg_read(conn, buf, 2); | |
62 | mg_read(conn, buf + 2, buf_len - 2); | |
63 | } else { | |
64 | mg_read(conn, buf, buf_len); | |
65 | } | |
66 | } else if (ri->query_string != NULL) { | |
67 | buf_len = strlen(ri->query_string); | |
68 | buf = malloc(buf_len + 1); | |
69 | strcpy(buf, ri->query_string); | |
70 | } | |
71 | var = malloc(buf_len + 1); | |
72 | var_len = mg_get_var(buf, buf_len, "my_var", var, buf_len + 1); | |
73 | mg_printf(conn, "Value: [%s]\n", var); | |
74 | mg_printf(conn, "Value size: [%d]\n", var_len); | |
75 | free(buf); | |
76 | free(var); | |
77 | } | |
78 | ||
79 | static void test_get_header(struct mg_connection *conn, | |
80 | const struct mg_request_info *ri) { | |
81 | const char *value; | |
82 | int i; | |
83 | ||
84 | mg_printf(conn, "%s", standard_reply); | |
85 | printf("HTTP headers: %d\n", ri->num_headers); | |
86 | for (i = 0; i < ri->num_headers; i++) { | |
87 | printf("[%s]: [%s]\n", ri->http_headers[i].name, ri->http_headers[i].value); | |
88 | } | |
89 | ||
90 | value = mg_get_header(conn, "Host"); | |
91 | if (value != NULL) { | |
92 | mg_printf(conn, "Value: [%s]", value); | |
93 | } | |
94 | } | |
95 | ||
96 | static void test_get_request_info(struct mg_connection *conn, | |
97 | const struct mg_request_info *ri) { | |
98 | int i; | |
99 | ||
100 | mg_printf(conn, "%s", standard_reply); | |
101 | ||
102 | mg_printf(conn, "Method: [%s]\n", ri->request_method); | |
103 | mg_printf(conn, "URI: [%s]\n", ri->uri); | |
104 | mg_printf(conn, "HTTP version: [%s]\n", ri->http_version); | |
105 | ||
106 | for (i = 0; i < ri->num_headers; i++) { | |
107 | mg_printf(conn, "HTTP header [%s]: [%s]\n", | |
108 | ri->http_headers[i].name, | |
109 | ri->http_headers[i].value); | |
110 | } | |
111 | ||
112 | mg_printf(conn, "Query string: [%s]\n", | |
113 | ri->query_string ? ri->query_string: ""); | |
114 | mg_printf(conn, "Remote IP: [%lu]\n", ri->remote_ip); | |
115 | mg_printf(conn, "Remote port: [%d]\n", ri->remote_port); | |
116 | mg_printf(conn, "Remote user: [%s]\n", | |
117 | ri->remote_user ? ri->remote_user : ""); | |
118 | } | |
119 | ||
120 | static void test_error(struct mg_connection *conn, | |
121 | const struct mg_request_info *ri) { | |
122 | int status = (int) ri->ev_data; | |
123 | mg_printf(conn, "HTTP/1.1 %d XX\r\n" | |
124 | "Conntection: close\r\n\r\n", status); | |
125 | mg_printf(conn, "Error: [%d]", status); | |
126 | } | |
127 | ||
128 | static void test_post(struct mg_connection *conn, | |
129 | const struct mg_request_info *ri) { | |
130 | const char *cl; | |
131 | char *buf; | |
132 | int len; | |
133 | ||
134 | mg_printf(conn, "%s", standard_reply); | |
135 | if (strcmp(ri->request_method, "POST") == 0 && | |
136 | (cl = mg_get_header(conn, "Content-Length")) != NULL) { | |
137 | len = atoi(cl); | |
138 | if ((buf = malloc(len)) != NULL) { | |
139 | mg_write(conn, buf, len); | |
140 | free(buf); | |
141 | } | |
142 | } | |
143 | } | |
144 | ||
145 | static const struct test_config { | |
146 | enum mg_event event; | |
147 | const char *uri; | |
148 | void (*func)(struct mg_connection *, const struct mg_request_info *); | |
149 | } test_config[] = { | |
150 | {MG_NEW_REQUEST, "/test_get_header", &test_get_header}, | |
151 | {MG_NEW_REQUEST, "/test_get_var", &test_get_var}, | |
152 | {MG_NEW_REQUEST, "/test_get_request_info", &test_get_request_info}, | |
153 | {MG_NEW_REQUEST, "/test_post", &test_post}, | |
154 | {MG_HTTP_ERROR, "", &test_error}, | |
155 | {0, NULL, NULL} | |
156 | }; | |
157 | ||
158 | static void *callback(enum mg_event event, | |
159 | struct mg_connection *conn) { | |
160 | const struct mg_request_info *request_info = mg_get_request_info(conn); | |
161 | int i; | |
162 | ||
163 | for (i = 0; test_config[i].uri != NULL; i++) { | |
164 | if (event == test_config[i].event && | |
165 | (event == MG_HTTP_ERROR || | |
166 | !strcmp(request_info->uri, test_config[i].uri))) { | |
167 | test_config[i].func(conn, request_info); | |
168 | return "processed"; | |
169 | } | |
170 | } | |
171 | ||
172 | return NULL; | |
173 | } | |
174 | ||
175 | int main(void) { | |
176 | struct mg_context *ctx; | |
177 | const char *options[] = {"listening_ports", LISTENING_PORT, NULL}; | |
178 | ||
179 | ctx = mg_start(callback, NULL, options); | |
180 | pause(); | |
181 | return 0; | |
182 | } |