iodine 0.4.19 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of iodine might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/.travis.yml +1 -2
- data/CHANGELOG.md +22 -0
- data/LIMITS.md +19 -9
- data/README.md +92 -77
- data/SPEC-PubSub-Draft.md +113 -0
- data/SPEC-Websocket-Draft.md +127 -143
- data/bin/http-hello +0 -1
- data/bin/raw-rbhttp +1 -1
- data/bin/raw_broadcast +8 -10
- data/bin/updated api +2 -2
- data/bin/ws-broadcast +2 -4
- data/bin/ws-echo +2 -2
- data/examples/config.ru +13 -13
- data/examples/echo.ru +5 -6
- data/examples/hello.ru +2 -3
- data/examples/info.md +316 -0
- data/examples/pubsub_engine.ru +81 -0
- data/examples/redis.ru +9 -9
- data/examples/shootout.ru +45 -11
- data/ext/iodine/defer.c +194 -297
- data/ext/iodine/defer.h +61 -53
- data/ext/iodine/evio.c +0 -260
- data/ext/iodine/evio.h +50 -22
- data/ext/iodine/evio_callbacks.c +26 -0
- data/ext/iodine/evio_epoll.c +251 -0
- data/ext/iodine/evio_kqueue.c +193 -0
- data/ext/iodine/extconf.rb +1 -1
- data/ext/iodine/facil.c +1420 -542
- data/ext/iodine/facil.h +151 -64
- data/ext/iodine/fio_ary.h +418 -0
- data/ext/iodine/{base64.c → fio_base64.c} +33 -24
- data/ext/iodine/{base64.h → fio_base64.h} +6 -7
- data/ext/iodine/{fio_cli_helper.c → fio_cli.c} +77 -58
- data/ext/iodine/{fio_cli_helper.h → fio_cli.h} +9 -4
- data/ext/iodine/fio_hashmap.h +759 -0
- data/ext/iodine/fio_json_parser.h +651 -0
- data/ext/iodine/fio_llist.h +257 -0
- data/ext/iodine/fio_mem.c +672 -0
- data/ext/iodine/fio_mem.h +140 -0
- data/ext/iodine/fio_random.c +248 -0
- data/ext/iodine/{random.h → fio_random.h} +11 -14
- data/ext/iodine/{sha1.c → fio_sha1.c} +28 -24
- data/ext/iodine/{sha1.h → fio_sha1.h} +38 -16
- data/ext/iodine/{sha2.c → fio_sha2.c} +66 -49
- data/ext/iodine/{sha2.h → fio_sha2.h} +57 -26
- data/ext/iodine/{fiobj_internal.c → fio_siphash.c} +9 -90
- data/ext/iodine/fio_siphash.h +18 -0
- data/ext/iodine/fio_tmpfile.h +38 -0
- data/ext/iodine/fiobj.h +24 -7
- data/ext/iodine/fiobj4sock.h +23 -0
- data/ext/iodine/fiobj_ary.c +143 -226
- data/ext/iodine/fiobj_ary.h +17 -16
- data/ext/iodine/fiobj_data.c +1160 -0
- data/ext/iodine/fiobj_data.h +164 -0
- data/ext/iodine/fiobj_hash.c +298 -406
- data/ext/iodine/fiobj_hash.h +101 -54
- data/ext/iodine/fiobj_json.c +478 -601
- data/ext/iodine/fiobj_json.h +34 -9
- data/ext/iodine/fiobj_numbers.c +383 -51
- data/ext/iodine/fiobj_numbers.h +87 -11
- data/ext/iodine/fiobj_str.c +423 -184
- data/ext/iodine/fiobj_str.h +81 -32
- data/ext/iodine/fiobject.c +273 -522
- data/ext/iodine/fiobject.h +477 -112
- data/ext/iodine/http.c +2243 -83
- data/ext/iodine/http.h +842 -121
- data/ext/iodine/http1.c +810 -385
- data/ext/iodine/http1.h +16 -39
- data/ext/iodine/http1_parser.c +146 -74
- data/ext/iodine/http1_parser.h +15 -4
- data/ext/iodine/http_internal.c +1258 -0
- data/ext/iodine/http_internal.h +226 -0
- data/ext/iodine/http_mime_parser.h +341 -0
- data/ext/iodine/iodine.c +86 -68
- data/ext/iodine/iodine.h +26 -11
- data/ext/iodine/iodine_helpers.c +8 -7
- data/ext/iodine/iodine_http.c +487 -324
- data/ext/iodine/iodine_json.c +304 -0
- data/ext/iodine/iodine_json.h +6 -0
- data/ext/iodine/iodine_protocol.c +107 -45
- data/ext/iodine/iodine_pubsub.c +526 -225
- data/ext/iodine/iodine_pubsub.h +10 -0
- data/ext/iodine/iodine_websockets.c +268 -510
- data/ext/iodine/iodine_websockets.h +2 -4
- data/ext/iodine/pubsub.c +726 -432
- data/ext/iodine/pubsub.h +85 -103
- data/ext/iodine/rb-call.c +4 -4
- data/ext/iodine/rb-defer.c +46 -22
- data/ext/iodine/rb-fiobj2rb.h +117 -0
- data/ext/iodine/rb-rack-io.c +73 -238
- data/ext/iodine/rb-rack-io.h +2 -2
- data/ext/iodine/rb-registry.c +35 -93
- data/ext/iodine/rb-registry.h +1 -0
- data/ext/iodine/redis_engine.c +742 -304
- data/ext/iodine/redis_engine.h +42 -39
- data/ext/iodine/resp_parser.h +311 -0
- data/ext/iodine/sock.c +627 -490
- data/ext/iodine/sock.h +345 -297
- data/ext/iodine/spnlock.inc +15 -4
- data/ext/iodine/websocket_parser.h +16 -20
- data/ext/iodine/websockets.c +188 -257
- data/ext/iodine/websockets.h +24 -133
- data/lib/iodine.rb +52 -7
- data/lib/iodine/cli.rb +6 -24
- data/lib/iodine/json.rb +40 -0
- data/lib/iodine/version.rb +1 -1
- data/lib/iodine/websocket.rb +5 -3
- data/lib/rack/handler/iodine.rb +58 -13
- metadata +38 -48
- data/bin/ws-shootout +0 -107
- data/examples/broadcast.ru +0 -56
- data/ext/iodine/bscrypt-common.h +0 -116
- data/ext/iodine/bscrypt.h +0 -49
- data/ext/iodine/fio2resp.c +0 -60
- data/ext/iodine/fio2resp.h +0 -51
- data/ext/iodine/fio_dict.c +0 -446
- data/ext/iodine/fio_dict.h +0 -99
- data/ext/iodine/fio_hash_table.h +0 -370
- data/ext/iodine/fio_list.h +0 -111
- data/ext/iodine/fiobj_internal.h +0 -280
- data/ext/iodine/fiobj_primitives.c +0 -131
- data/ext/iodine/fiobj_primitives.h +0 -55
- data/ext/iodine/fiobj_sym.c +0 -135
- data/ext/iodine/fiobj_sym.h +0 -60
- data/ext/iodine/hex.c +0 -124
- data/ext/iodine/hex.h +0 -70
- data/ext/iodine/http1_request.c +0 -81
- data/ext/iodine/http1_request.h +0 -58
- data/ext/iodine/http1_response.c +0 -417
- data/ext/iodine/http1_response.h +0 -95
- data/ext/iodine/http_request.c +0 -111
- data/ext/iodine/http_request.h +0 -102
- data/ext/iodine/http_response.c +0 -1703
- data/ext/iodine/http_response.h +0 -250
- data/ext/iodine/misc.c +0 -182
- data/ext/iodine/misc.h +0 -74
- data/ext/iodine/random.c +0 -208
- data/ext/iodine/redis_connection.c +0 -278
- data/ext/iodine/redis_connection.h +0 -86
- data/ext/iodine/resp.c +0 -842
- data/ext/iodine/resp.h +0 -261
- data/ext/iodine/siphash.c +0 -154
- data/ext/iodine/siphash.h +0 -22
- data/ext/iodine/xor-crypt.c +0 -193
- data/ext/iodine/xor-crypt.h +0 -107
data/ext/iodine/http.h
CHANGED
@@ -1,45 +1,24 @@
|
|
1
|
+
#ifndef H_HTTP_H
|
1
2
|
/*
|
2
|
-
|
3
|
-
|
3
|
+
Copyright: Boaz Segev, 2016-2018
|
4
|
+
License: MIT
|
4
5
|
|
5
6
|
Feel free to copy, use and enjoy according to the license provided.
|
6
7
|
*/
|
7
|
-
#
|
8
|
-
#define HTTP_H
|
8
|
+
#define H_HTTP_H
|
9
9
|
|
10
10
|
#include "facil.h"
|
11
11
|
|
12
|
-
|
13
|
-
enum HTTP_VERSION { HTTP_V1 = 0, HTTP_V2 = 1 };
|
12
|
+
#include <time.h>
|
14
13
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
const char *data;
|
20
|
-
const char *value;
|
21
|
-
};
|
22
|
-
uint32_t name_len;
|
23
|
-
union {
|
24
|
-
uint32_t data_len;
|
25
|
-
uint32_t value_len;
|
26
|
-
};
|
27
|
-
} http_header_s;
|
28
|
-
|
29
|
-
/** Settings typedef */
|
30
|
-
typedef struct http_settings_s http_settings_s;
|
14
|
+
/* support C++ */
|
15
|
+
#ifdef __cplusplus
|
16
|
+
extern "C" {
|
17
|
+
#endif
|
31
18
|
|
32
19
|
/* *****************************************************************************
|
33
|
-
|
34
|
-
*/
|
35
|
-
// clang-format off
|
36
|
-
#include <time.h>
|
37
|
-
#include "http_request.h"
|
38
|
-
#include "http_response.h"
|
39
|
-
// clang-format on
|
40
|
-
/* *****************************************************************************
|
41
|
-
Hard Coded Settings
|
42
|
-
*/
|
20
|
+
Compile Time Settings
|
21
|
+
***************************************************************************** */
|
43
22
|
|
44
23
|
/** When a new connection is accepted, it will be immediately declined with a
|
45
24
|
* 503 service unavailable (server busy) response unless the following number of
|
@@ -52,94 +31,857 @@ Hard Coded Settings
|
|
52
31
|
#define HTTP_DEFAULT_BODY_LIMIT (1024 * 1024 * 50)
|
53
32
|
#endif
|
54
33
|
|
55
|
-
|
56
|
-
#
|
57
|
-
|
34
|
+
#ifndef HTTP_MAX_HEADER_COUNT
|
35
|
+
#define HTTP_MAX_HEADER_COUNT 128
|
36
|
+
#endif
|
37
|
+
|
38
|
+
#ifndef HTTP_MAX_HEADER_LENGTH
|
39
|
+
/** the default maximum length for a single header line */
|
40
|
+
#define HTTP_MAX_HEADER_LENGTH 8192
|
58
41
|
#endif
|
59
42
|
|
43
|
+
/** the `http_listen settings, see detils in the struct definition. */
|
44
|
+
typedef struct http_settings_s http_settings_s;
|
45
|
+
|
60
46
|
/* *****************************************************************************
|
61
|
-
|
62
|
-
*/
|
47
|
+
The Request / Response type and functions
|
48
|
+
***************************************************************************** */
|
63
49
|
|
64
|
-
/**
|
65
|
-
|
50
|
+
/**
|
51
|
+
* A generic HTTP handle used for HTTP request/response data.
|
52
|
+
*
|
53
|
+
* The `http_s` data can only be accessed safely from within the `on_request`
|
54
|
+
* HTTP callback OR an `http_defer` callback.
|
55
|
+
*/
|
56
|
+
typedef struct {
|
57
|
+
/** the HTTP request's "head" starts with a private data used by facil.io */
|
58
|
+
struct {
|
59
|
+
/** the function touting table - used by facil.io, don't use directly! */
|
60
|
+
void *vtbl;
|
61
|
+
/** the connection's owner / uuid - used by facil.io, don't use directly! */
|
62
|
+
uintptr_t flag;
|
63
|
+
/** The response headers, if they weren't sent. Don't access directly. */
|
64
|
+
FIOBJ out_headers;
|
65
|
+
} private_data;
|
66
|
+
/** a time merker indicating when the request was received. */
|
67
|
+
struct timespec received_at;
|
68
|
+
/** a String containing the method data (supports non-standard methods. */
|
69
|
+
FIOBJ method;
|
70
|
+
/** The status string, for response objects (client mode response). */
|
71
|
+
FIOBJ status_str;
|
72
|
+
/** The HTTP version string, if any. */
|
73
|
+
FIOBJ version;
|
74
|
+
/** The status used for the response (or if the object is a response).
|
75
|
+
*
|
76
|
+
* When sending a request, the status should be set to 0.
|
77
|
+
*/
|
78
|
+
uintptr_t status;
|
79
|
+
/** The request path, if any. */
|
80
|
+
FIOBJ path;
|
81
|
+
/** The request query, if any. */
|
82
|
+
FIOBJ query;
|
83
|
+
/** a hash of general header data. When a header is set multiple times (such
|
84
|
+
* as cookie headers), an Array will be used instead of a String. */
|
85
|
+
FIOBJ headers;
|
86
|
+
/**
|
87
|
+
* a placeholder for a hash of cookie data.
|
88
|
+
* the hash will be initialized when parsing the request.
|
89
|
+
*/
|
90
|
+
FIOBJ cookies;
|
91
|
+
/**
|
92
|
+
* a placeholder for a hash of request data.
|
93
|
+
* the hash will be initialized when parsing the request.
|
94
|
+
*/
|
95
|
+
FIOBJ params;
|
66
96
|
/**
|
67
|
-
|
97
|
+
* a reader for body data (might be a temporary file or a string or NULL).
|
98
|
+
* see fiobj_data.h for details.
|
99
|
+
*/
|
100
|
+
FIOBJ body;
|
101
|
+
/** an opaque user data pointer, to be used BEFORE calling `http_defer`. */
|
102
|
+
void *udata;
|
103
|
+
} http_s;
|
68
104
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
105
|
+
/**
|
106
|
+
* This is a helper for setting cookie data.
|
107
|
+
|
108
|
+
This struct is used together with the `http_response_set_cookie`. i.e.:
|
109
|
+
|
110
|
+
http_response_set_cookie(response,
|
111
|
+
.name = "my_cookie",
|
112
|
+
.value = "data" );
|
113
|
+
|
114
|
+
*/
|
115
|
+
typedef struct {
|
116
|
+
/** The cookie's name (Symbol). */
|
117
|
+
char *name;
|
118
|
+
/** The cookie's value (leave blank to delete cookie). */
|
119
|
+
char *value;
|
120
|
+
/** The cookie's domain (optional). */
|
121
|
+
char *domain;
|
122
|
+
/** The cookie's path (optional). */
|
123
|
+
char *path;
|
124
|
+
/** The cookie name's size in bytes or a terminating NULL will be assumed.*/
|
125
|
+
size_t name_len;
|
126
|
+
/** The cookie value's size in bytes or a terminating NULL will be assumed.*/
|
127
|
+
size_t value_len;
|
128
|
+
/** The cookie domain's size in bytes or a terminating NULL will be assumed.*/
|
129
|
+
size_t domain_len;
|
130
|
+
/** The cookie path's size in bytes or a terminating NULL will be assumed.*/
|
131
|
+
size_t path_len;
|
132
|
+
/** Max Age (how long should the cookie persist), in seconds (0 == session).*/
|
133
|
+
int max_age;
|
134
|
+
/** Limit cookie to secure connections.*/
|
135
|
+
unsigned secure : 1;
|
136
|
+
/** Limit cookie to HTTP (intended to prevent javascript access/hijacking).*/
|
137
|
+
unsigned http_only : 1;
|
138
|
+
} http_cookie_args_s;
|
139
|
+
|
140
|
+
/**
|
141
|
+
* Sets a response header, taking ownership of the value object, but NOT the
|
142
|
+
* name object (so name objects could be reused in future responses).
|
143
|
+
*
|
144
|
+
* Returns -1 on error and 0 on success.
|
145
|
+
*/
|
146
|
+
int http_set_header(http_s *h, FIOBJ name, FIOBJ value);
|
147
|
+
|
148
|
+
/**
|
149
|
+
* Sets a response header, taking ownership of the value object, but NOT the
|
150
|
+
* name object (so name objects could be reused in future responses).
|
151
|
+
*
|
152
|
+
* Returns -1 on error and 0 on success.
|
153
|
+
*/
|
154
|
+
int http_set_header2(http_s *h, fio_cstr_s name, fio_cstr_s value);
|
155
|
+
|
156
|
+
/**
|
157
|
+
* Sets a response cookie, taking ownership of the value object, but NOT the
|
158
|
+
* name object (so name objects could be reused in future responses).
|
159
|
+
*
|
160
|
+
* Returns -1 on error and 0 on success.
|
161
|
+
*
|
162
|
+
* Note: Long cookie names and long cookie values will be considered a security
|
163
|
+
* vaiolation and an error will be returned. It should be noted that most
|
164
|
+
* proxies and servers will refuse long cookie names or values and many impose
|
165
|
+
* total header lengths (including cookies) of ~8Kib.
|
166
|
+
*/
|
167
|
+
int http_set_cookie(http_s *h, http_cookie_args_s);
|
168
|
+
#define http_set_cookie(http___handle, ...) \
|
169
|
+
http_set_cookie((http___handle), (http_cookie_args_s){__VA_ARGS__})
|
170
|
+
|
171
|
+
/**
|
172
|
+
* Sends the response headers and body.
|
173
|
+
*
|
174
|
+
* **Note**: The body is *copied* to the HTTP stream and it's memory should be
|
175
|
+
* freed by the calling function.
|
176
|
+
*
|
177
|
+
* Returns -1 on error and 0 on success.
|
178
|
+
*
|
179
|
+
* AFTER THIS FUNCTION IS CALLED, THE `http_s` OBJECT IS NO LONGER VALID.
|
180
|
+
*/
|
181
|
+
int http_send_body(http_s *h, void *data, uintptr_t length);
|
182
|
+
|
183
|
+
/**
|
184
|
+
* Sends the response headers and the specified file (the response's body).
|
185
|
+
*
|
186
|
+
* The file is closed automatically.
|
187
|
+
*
|
188
|
+
* Returns -1 on error and 0 on success.
|
189
|
+
*
|
190
|
+
* AFTER THIS FUNCTION IS CALLED, THE `http_s` OBJECT IS NO LONGER VALID.
|
191
|
+
*/
|
192
|
+
int http_sendfile(http_s *h, int fd, uintptr_t length, uintptr_t offset);
|
193
|
+
|
194
|
+
/**
|
195
|
+
* Sends the response headers and the specified file (the response's body).
|
196
|
+
*
|
197
|
+
* The `local` and `encoded` strings will be joined into a single string that
|
198
|
+
* represent the file name. Either or both of these strings can be empty.
|
199
|
+
*
|
200
|
+
* The `encoded` string will be URL decoded while the `local` string will used
|
201
|
+
* as is.
|
202
|
+
*
|
203
|
+
* Returns 0 on success. A success value WILL CONSUME the `http_s` handle (it
|
204
|
+
* will become invalid).
|
205
|
+
*
|
206
|
+
* Returns -1 on error (The `http_s` handle should still be used).
|
207
|
+
*/
|
208
|
+
int http_sendfile2(http_s *h, const char *prefix, size_t prefix_len,
|
209
|
+
const char *encoded, size_t encoded_len);
|
210
|
+
|
211
|
+
/**
|
212
|
+
* Sends an HTTP error response.
|
213
|
+
*
|
214
|
+
* Returns -1 on error and 0 on success.
|
215
|
+
*
|
216
|
+
* AFTER THIS FUNCTION IS CALLED, THE `http_s` OBJECT IS NO LONGER VALID.
|
217
|
+
*
|
218
|
+
* The `uuid` and `settings` arguments are only required if the `http_s` handle
|
219
|
+
* is NULL.
|
220
|
+
*/
|
221
|
+
int http_send_error(http_s *h, size_t error_code);
|
222
|
+
|
223
|
+
/**
|
224
|
+
* Sends the response headers for a header only response.
|
225
|
+
*
|
226
|
+
* AFTER THIS FUNCTION IS CALLED, THE `http_s` OBJECT IS NO LONGER VALID.
|
227
|
+
*/
|
228
|
+
void http_finish(http_s *h);
|
229
|
+
|
230
|
+
/**
|
231
|
+
* Pushes a data response when supported (HTTP/2 only).
|
232
|
+
*
|
233
|
+
* Returns -1 on error and 0 on success.
|
234
|
+
*/
|
235
|
+
int http_push_data(http_s *h, void *data, uintptr_t length, FIOBJ mime_type);
|
236
|
+
|
237
|
+
/**
|
238
|
+
* Pushes a file response when supported (HTTP/2 only).
|
239
|
+
*
|
240
|
+
* If `mime_type` is NULL, an attempt at automatic detection using `filename`
|
241
|
+
* will be made.
|
242
|
+
*
|
243
|
+
* Returns -1 on error and 0 on success.
|
244
|
+
*/
|
245
|
+
int http_push_file(http_s *h, FIOBJ filename, FIOBJ mime_type);
|
246
|
+
|
247
|
+
/* *****************************************************************************
|
248
|
+
HTTP evented API (pause / resume HTTp handling)
|
249
|
+
***************************************************************************** */
|
250
|
+
|
251
|
+
/**
|
252
|
+
* Pauses the request / response handling and INVALIDATES the current `http_s`
|
253
|
+
* handle (no `http` functions can be called).
|
254
|
+
*
|
255
|
+
* The `http_resume` function MUST be called (at some point) using the opaque
|
256
|
+
* `http` pointer given to the callback `task`.
|
257
|
+
*
|
258
|
+
* The opaque `http` pointer is only valid for a single call to `http_resume`
|
259
|
+
* and can't be used by any other `http` function (it's a different data type).
|
260
|
+
*
|
261
|
+
* Note: the currecnt `http_s` handle will become invalid once this function is
|
262
|
+
* called and it's data might be deallocated, invalid or used by a different
|
263
|
+
* thread.
|
264
|
+
*/
|
265
|
+
void http_pause(http_s *h, void (*task)(void *http));
|
266
|
+
|
267
|
+
/**
|
268
|
+
* Resumes a request / response handling within a task and INVALIDATES the
|
269
|
+
* current `http_s` handle.
|
270
|
+
*
|
271
|
+
* The `task` MUST call one of the `http_send_*`, `http_finish`, or
|
272
|
+
* `http_pause`functions.
|
273
|
+
*
|
274
|
+
* The (optional) `fallback` will receive the opaque `udata` that was stored in
|
275
|
+
* the HTTP handle and can be used for cleanup.
|
276
|
+
*
|
277
|
+
* Note: `http_resume` can only be called after calling `http_pause` and
|
278
|
+
* entering it's task.
|
279
|
+
*
|
280
|
+
* Note: the current `http_s` handle will become invalid once this function is
|
281
|
+
* called and it's data might be deallocated, invalidated or used by a
|
282
|
+
* different thread.
|
283
|
+
*/
|
284
|
+
void http_resume(void *http, void (*task)(http_s *h),
|
285
|
+
void (*fallback)(void *udata));
|
286
|
+
|
287
|
+
/** Returns the `udata` associated with the paused opaque handle */
|
288
|
+
void *http_paused_udata_get(void *http);
|
289
|
+
|
290
|
+
/**
|
291
|
+
* Sets the `udata` associated with the paused opaque handle, returning the
|
292
|
+
* old value.
|
293
|
+
*/
|
294
|
+
void *http_paused_udata_set(void *http, void *udata);
|
295
|
+
|
296
|
+
/* *****************************************************************************
|
297
|
+
HTTP Connections - Listening / Connecting / Hijacking
|
298
|
+
***************************************************************************** */
|
299
|
+
|
300
|
+
/** The HTTP settings. */
|
301
|
+
typedef struct http_settings_s {
|
302
|
+
/** Callback for normal HTTP requests. */
|
303
|
+
void (*on_request)(http_s *request);
|
304
|
+
/**
|
305
|
+
* Callback for Upgrade and EventSource (SSE) requests.
|
306
|
+
*
|
307
|
+
* SSE/EventSource requests set the `requested_protocol` string to `"sse"`.
|
308
|
+
*/
|
309
|
+
void (*on_upgrade)(http_s *request, char *requested_protocol, size_t len);
|
310
|
+
/** CLIENT REQUIRED: a callback for the HTTP response. */
|
311
|
+
void (*on_response)(http_s *response);
|
312
|
+
/** (optional) the callback to be performed when the HTTP service closes. */
|
313
|
+
void (*on_finish)(struct http_settings_s *settings);
|
314
|
+
/** Opaque user data. Facil.io will ignore this field, but you can use it. */
|
315
|
+
void *udata;
|
74
316
|
/**
|
75
|
-
|
76
|
-
|
77
|
-
|
317
|
+
* A public folder for file transfers - allows to circumvent any application
|
318
|
+
* layer logic and simply serve static files.
|
319
|
+
*
|
320
|
+
* Supports automatic `gz` pre-compressed alternatives.
|
321
|
+
*/
|
78
322
|
const char *public_folder;
|
79
323
|
/**
|
80
|
-
|
81
|
-
|
324
|
+
* The length of the public_folder string.
|
325
|
+
*/
|
82
326
|
size_t public_folder_length;
|
83
|
-
/** Opaque user data. */
|
84
|
-
void *udata;
|
85
|
-
/** Opaque user data for the optional `set_rw_hooks`. */
|
86
|
-
void *rw_udata;
|
87
|
-
/** (optional) the callback to be performed when the HTTP service closes. */
|
88
|
-
void (*on_finish)(intptr_t uuid, void *udata);
|
89
327
|
/**
|
90
|
-
*
|
91
|
-
*
|
328
|
+
* The maximum number of bytes allowed for the request string (method, path,
|
329
|
+
* query), header names and fields.
|
330
|
+
*
|
331
|
+
* Defaults to 32Kib (which is about 4 times more than I would recommend).
|
332
|
+
*
|
333
|
+
* This reflects the total overall size. On HTTP/1.1, each header line (name +
|
334
|
+
* value pair) is also limitied to a hardcoded HTTP_MAX_HEADER_LENGTH bytes.
|
92
335
|
*/
|
93
|
-
|
336
|
+
size_t max_header_size;
|
94
337
|
/**
|
95
|
-
*
|
338
|
+
* The maximum size of an HTTP request's body (posting / downloading).
|
339
|
+
*
|
340
|
+
* Defaults to ~ 50Mb.
|
96
341
|
*/
|
97
|
-
|
342
|
+
size_t max_body_size;
|
98
343
|
/**
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
344
|
+
* The maximum number of clients that are allowed to connect concurrently.
|
345
|
+
*
|
346
|
+
* This value's default setting is usually for the best.
|
347
|
+
*
|
348
|
+
* The default value is computed according to the server's capacity, leaving
|
349
|
+
* some breathing room for other network and disk operations.
|
350
|
+
*
|
351
|
+
* Note: clients, by the nature of socket programming, are counted according
|
352
|
+
* to their internal file descriptor (`fd`) value. Open files and other
|
353
|
+
* sockets count towards a server's limit.
|
354
|
+
*/
|
355
|
+
intptr_t max_clients;
|
356
|
+
/** reserved for future use. */
|
357
|
+
intptr_t reserved1;
|
358
|
+
/** reserved for future use. */
|
359
|
+
intptr_t reserved2;
|
360
|
+
/** reserved for future use. */
|
361
|
+
intptr_t reserved3;
|
362
|
+
/** reserved for future use. */
|
363
|
+
intptr_t reserved4;
|
364
|
+
/**
|
365
|
+
* The maximum websocket message size/buffer (in bytes) for Websocket
|
366
|
+
* connections. Defaults to ~250KB.
|
367
|
+
*/
|
368
|
+
size_t ws_max_msg_size;
|
369
|
+
/**
|
370
|
+
* An HTTP/1.x connection timeout.
|
371
|
+
*
|
372
|
+
* `http_listen` defaults to ~40s and `http_connect` defaults to ~30s.
|
373
|
+
*
|
374
|
+
* Note: the connection might be closed (by other side) before timeout occurs.
|
375
|
+
*/
|
105
376
|
uint8_t timeout;
|
106
377
|
/**
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
378
|
+
* Timeout for the websocket connections, a ping will be sent whenever the
|
379
|
+
* timeout is reached. Defaults to 40 seconds.
|
380
|
+
*
|
381
|
+
* Connections are only closed when a ping cannot be sent (the network layer
|
382
|
+
* fails). Pongs are ignored.
|
383
|
+
*/
|
384
|
+
uint8_t ws_timeout;
|
385
|
+
/** Logging flag - set to TRUE to log HTTP requests. */
|
386
|
+
uint8_t log;
|
387
|
+
/** a read only flag set automatically to indicate the protocol's mode. */
|
388
|
+
uint8_t is_client;
|
389
|
+
} http_settings_s;
|
390
|
+
|
391
|
+
/**
|
392
|
+
* Listens to HTTP connections at the specified `port`.
|
393
|
+
*
|
394
|
+
* Leave as NULL to ignore IP binding.
|
395
|
+
*
|
396
|
+
* Returns -1 on error and 0 on success. the `on_finish` callback is always
|
397
|
+
* called.
|
398
|
+
*/
|
399
|
+
int http_listen(const char *port, const char *binding, struct http_settings_s);
|
400
|
+
/** Listens to HTTP connections at the specified `port` and `binding`. */
|
401
|
+
#define http_listen(port, binding, ...) \
|
402
|
+
http_listen((port), (binding), (struct http_settings_s){__VA_ARGS__})
|
403
|
+
|
404
|
+
/**
|
405
|
+
* Connects to an HTTP server as a client.
|
406
|
+
*
|
407
|
+
* Upon a successful connection, the `on_response` callback is called with an
|
408
|
+
* empty `http_s*` handler (status == 0). Use the same API to set it's content
|
409
|
+
* and send the request to the server. The next`on_response` will contain the
|
410
|
+
* response.
|
411
|
+
*
|
412
|
+
* `address` should contain a full URL style address for the server. i.e.:
|
413
|
+
*
|
414
|
+
* "http:/www.example.com:8080/"
|
415
|
+
*
|
416
|
+
* If an `address` includes a path or query data, they will be automatically
|
417
|
+
* attached (both of them) to the HTTP handl'es `path` property. i.e.
|
418
|
+
*
|
419
|
+
* "http:/www.example.com:8080/my_path?foo=bar"
|
420
|
+
* // will result in:
|
421
|
+
* fiobj_obj2cstr(h->path).data; //=> "/my_path?foo=bar"
|
422
|
+
*
|
423
|
+
* To open a Websocket connection, it's possible to use the `ws` protocol
|
424
|
+
* signature. However, it would be better to use the `websocket_connect`
|
425
|
+
* function instead.
|
426
|
+
*
|
427
|
+
* Returns -1 on error and 0 on success. the `on_finish` callback is always
|
428
|
+
* called.
|
429
|
+
*/
|
430
|
+
int http_connect(const char *address, struct http_settings_s);
|
431
|
+
#define http_connect(address, ...) \
|
432
|
+
http_connect((address), (struct http_settings_s){__VA_ARGS__})
|
433
|
+
|
434
|
+
/**
|
435
|
+
* Returns the settings used to setup the connection.
|
436
|
+
*
|
437
|
+
* Returns -1 on error and 0 on success.
|
438
|
+
*/
|
439
|
+
struct http_settings_s *http_settings(http_s *h);
|
440
|
+
|
441
|
+
/**
|
442
|
+
* Returns the direct address of the connected peer (likely an intermediary).
|
443
|
+
*/
|
444
|
+
sock_peer_addr_s http_peer_addr(http_s *h);
|
445
|
+
|
446
|
+
/**
|
447
|
+
* Hijacks the socket away from the HTTP protocol and away from facil.io.
|
448
|
+
*
|
449
|
+
* It's possible to hijack the socket and than reconnect it to a new protocol
|
450
|
+
* object.
|
451
|
+
*
|
452
|
+
* If any HTTP functions are called after the hijacking, the protocol object
|
453
|
+
* might attempt to continue reading data from the buffer.
|
454
|
+
*
|
455
|
+
* Returns the underlining socket connection's uuid. If `leftover` isn't NULL,
|
456
|
+
* it will be populated with any remaining data in the HTTP buffer (the data
|
457
|
+
* will be automatically deallocated, so copy the data if it's required).
|
458
|
+
*
|
459
|
+
* WARNING: this isn't a good was to handle HTTP connections, especially as
|
460
|
+
* HTTP/2 enters the picture.
|
461
|
+
*/
|
462
|
+
intptr_t http_hijack(http_s *h, fio_cstr_s *leftover);
|
463
|
+
|
464
|
+
/* *****************************************************************************
|
465
|
+
Websocket Upgrade (Server and Client connection establishment)
|
466
|
+
***************************************************************************** */
|
467
|
+
|
468
|
+
/**
|
469
|
+
* The type for a Websocket handle, used to identify a Websocket connection.
|
470
|
+
*
|
471
|
+
* Similar to an `http_s` handle, it is only valid within the scope of the
|
472
|
+
* specific connection (the callbacks / tasks) and shouldn't be stored or
|
473
|
+
* accessed otherwise.
|
474
|
+
*/
|
475
|
+
typedef struct ws_s ws_s;
|
476
|
+
|
477
|
+
/**
|
478
|
+
* This struct is used for the named agruments in the `http_upgrade2ws`
|
479
|
+
* function and macro.
|
480
|
+
*/
|
481
|
+
typedef struct {
|
482
|
+
/** REQUIRED: The `http_s` to be initiating the websocket connection.*/
|
483
|
+
http_s *http;
|
484
|
+
/**
|
485
|
+
* The (optional) on_message callback will be called whenever a websocket
|
486
|
+
* message is received for this connection.
|
487
|
+
*
|
488
|
+
* The data received points to the websocket's message buffer and it will be
|
489
|
+
* overwritten once the function exits (it cannot be saved for later, but it
|
490
|
+
* can be copied).
|
491
|
+
*/
|
492
|
+
void (*on_message)(ws_s *ws, char *data, size_t size, uint8_t is_text);
|
111
493
|
/**
|
112
|
-
|
113
|
-
|
114
|
-
|
494
|
+
* The (optional) on_open callback will be called once the websocket
|
495
|
+
* connection is established and before is is registered with `facil`, so no
|
496
|
+
* `on_message` events are raised before `on_open` returns.
|
497
|
+
*/
|
498
|
+
void (*on_open)(ws_s *ws);
|
499
|
+
/**
|
500
|
+
* The (optional) on_ready callback will be after a the underlying socket's
|
501
|
+
* buffer changes it's state from full to empty.
|
502
|
+
*
|
503
|
+
* If the socket's buffer is never used, the callback is never called.
|
504
|
+
*/
|
505
|
+
void (*on_ready)(ws_s *ws);
|
506
|
+
/**
|
507
|
+
* The (optional) on_shutdown callback will be called if a websocket
|
508
|
+
* connection is still open while the server is shutting down (called before
|
509
|
+
* `on_close`).
|
510
|
+
*/
|
511
|
+
void (*on_shutdown)(ws_s *ws);
|
512
|
+
/**
|
513
|
+
* The (optional) on_close callback will be called once a websocket connection
|
514
|
+
* is terminated or failed to be established.
|
515
|
+
*
|
516
|
+
* The `uuid` is the connection's unique ID that can identify the Websocket. A
|
517
|
+
* value of `uuid == 0` indicates the Websocket connection wasn't established
|
518
|
+
* (an error occured).
|
519
|
+
*
|
520
|
+
* The `udata` is the user data as set during the upgrade or using the
|
521
|
+
* `websocket_udata_set` function.
|
522
|
+
*/
|
523
|
+
void (*on_close)(intptr_t uuid, void *udata);
|
524
|
+
/** Opaque user data. */
|
525
|
+
void *udata;
|
526
|
+
} websocket_settings_s;
|
527
|
+
|
528
|
+
/**
|
529
|
+
* Upgrades an HTTP/1.1 connection to a Websocket connection.
|
530
|
+
*
|
531
|
+
* This function will end the HTTP stage of the connection and attempt to
|
532
|
+
* "upgrade" to a Websockets connection.
|
533
|
+
*
|
534
|
+
* Thie `http_s` handle will be invalid after this call and the `udata` will be
|
535
|
+
* set to the new Websocket `udata`.
|
536
|
+
*
|
537
|
+
* A client connection's `on_finish` callback will be called (since the HTTP
|
538
|
+
* stage has finished).
|
539
|
+
*/
|
540
|
+
int http_upgrade2ws(websocket_settings_s);
|
541
|
+
|
542
|
+
/** This macro allows easy access to the `http_upgrade2ws` function. The macro
|
543
|
+
* allows the use of named arguments, using the `websocket_settings_s` struct
|
544
|
+
* members. i.e.:
|
545
|
+
*
|
546
|
+
* on_message(ws_s * ws, char * data, size_t size, int is_text) {
|
547
|
+
* ; // ... this is the websocket on_message callback
|
548
|
+
* websocket_write(ws, data, size, is_text); // a simple echo example
|
549
|
+
* }
|
550
|
+
*
|
551
|
+
* on_upgrade(http_s* h) {
|
552
|
+
* http_upgrade2ws( .http = h, .on_message = on_message);
|
553
|
+
* }
|
554
|
+
*/
|
555
|
+
#define http_upgrade2ws(...) \
|
556
|
+
http_upgrade2ws((websocket_settings_s){__VA_ARGS__})
|
557
|
+
|
558
|
+
/**
|
559
|
+
* Connects to a Websocket service according to the provided address.
|
560
|
+
*
|
561
|
+
* This is a somewhat naive connector object, it doesn't perform any
|
562
|
+
* authentication or other logical handling. However, it's quire easy to author
|
563
|
+
* a complext authentication logic using a combination of `http_connect` and
|
564
|
+
* `http_upgrade2ws`.
|
565
|
+
*
|
566
|
+
* Returns the uuid for the future websocket on success.
|
567
|
+
*
|
568
|
+
* Returns -1 on error;
|
569
|
+
*/
|
570
|
+
int websocket_connect(const char *address, websocket_settings_s settings);
|
571
|
+
#define websocket_connect(address, ...) \
|
572
|
+
websocket_connect((address), (websocket_settings_s){__VA_ARGS__})
|
573
|
+
|
574
|
+
#include "websockets.h"
|
575
|
+
|
576
|
+
/* *****************************************************************************
|
577
|
+
EventSource Support (SSE)
|
578
|
+
***************************************************************************** */
|
579
|
+
|
580
|
+
/**
|
581
|
+
* The type for the EventSource (SSE) handle, used to identify an SSE
|
582
|
+
* connection.
|
583
|
+
*/
|
584
|
+
typedef struct http_sse_s http_sse_s;
|
585
|
+
|
586
|
+
/**
|
587
|
+
* This struct is used for the named agruments in the `http_upgrade2sse`
|
588
|
+
* function and macro.
|
589
|
+
*/
|
590
|
+
struct http_sse_s {
|
591
|
+
/**
|
592
|
+
* The (optional) on_open callback will be called once the EventSource
|
593
|
+
* connection is established.
|
594
|
+
*/
|
595
|
+
void (*on_open)(http_sse_s *sse);
|
596
|
+
/**
|
597
|
+
* The (optional) on_ready callback will be after a the underlying socket's
|
598
|
+
* buffer changes it's state to empty.
|
599
|
+
*
|
600
|
+
* If the socket's buffer is never used, the callback is never called.
|
601
|
+
*/
|
602
|
+
void (*on_ready)(http_sse_s *sse);
|
603
|
+
/**
|
604
|
+
* The (optional) on_shutdown callback will be called if a connection is still
|
605
|
+
* open while the server is shutting down (called before `on_close`).
|
606
|
+
*/
|
607
|
+
void (*on_shutdown)(http_sse_s *sse);
|
608
|
+
/**
|
609
|
+
* The (optional) on_close callback will be called once a connection is
|
610
|
+
* terminated or failed to be established.
|
611
|
+
*
|
612
|
+
* The `uuid` is the connection's unique ID that can identify the Websocket. A
|
613
|
+
* value of `uuid == 0` indicates the Websocket connection wasn't established
|
614
|
+
* (an error occured).
|
615
|
+
*
|
616
|
+
* The `udata` is the user data as set during the upgrade or using the
|
617
|
+
* `websocket_udata_set` function.
|
618
|
+
*/
|
619
|
+
void (*on_close)(http_sse_s *sse);
|
620
|
+
/** Opaque user data. */
|
621
|
+
void *udata;
|
115
622
|
};
|
116
623
|
|
117
|
-
typedef protocol_s *(*http_on_open_func)(intptr_t, void *);
|
118
|
-
typedef void (*http_on_finish_func)(void *);
|
119
624
|
/**
|
120
|
-
|
121
|
-
|
122
|
-
|
625
|
+
* Upgrades an HTTP connection to an EventSource (SSE) connection.
|
626
|
+
*
|
627
|
+
* Thie `http_s` handle will be invalid after this call.
|
628
|
+
*
|
629
|
+
* On HTTP/1.1 connections, this will preclude future requests using the same
|
630
|
+
* connection.
|
631
|
+
*/
|
632
|
+
int http_upgrade2sse(http_s *h, http_sse_s);
|
633
|
+
|
634
|
+
/** This macro allows easy access to the `http_upgrade2sse` function. The macro
|
635
|
+
* allows the use of named arguments, using the `websocket_settings_s` struct
|
636
|
+
* members. i.e.:
|
637
|
+
*
|
638
|
+
* on_open_sse(sse_s * sse) {
|
639
|
+
* ; // ... this is the websocket on_message callback
|
640
|
+
* FIOBJ ch = (FIOBJ)sse->udata;
|
641
|
+
* http_sse_subscribe(ch, NULL, NULL); // a simple echo example
|
642
|
+
* }
|
643
|
+
*
|
644
|
+
* on_upgrade(http_s* h) {
|
645
|
+
* http_upgrade2sse(h, .on_open = on_open_sse);
|
646
|
+
* }
|
647
|
+
*/
|
648
|
+
#define http_upgrade2sse(h, ...) \
|
649
|
+
http_upgrade2sse((h), (http_sse_s){__VA_ARGS__})
|
650
|
+
|
123
651
|
/**
|
124
|
-
|
125
|
-
*/
|
126
|
-
|
652
|
+
* Sets the ping interval for SSE connections.
|
653
|
+
*/
|
654
|
+
void http_sse_set_timout(http_sse_s *sse, uint8_t timeout);
|
655
|
+
|
656
|
+
struct http_sse_subscribe_args {
|
657
|
+
/** The channel namr used for the subscription. */
|
658
|
+
FIOBJ channel;
|
659
|
+
/** The optional on message callback. If missing, Data is directly writen. */
|
660
|
+
void (*on_message)(http_sse_s *sse, FIOBJ channel, FIOBJ msg, void *udata);
|
661
|
+
/** An optional callback for when a subscription is fully canceled. */
|
662
|
+
void (*on_unsubscribe)(void *udata);
|
663
|
+
/** Opaque user */
|
664
|
+
void *udata;
|
665
|
+
/** Use pattern matching for channel subscription. */
|
666
|
+
unsigned use_pattern : 1;
|
667
|
+
};
|
127
668
|
|
128
669
|
/**
|
129
|
-
|
130
|
-
|
670
|
+
* Subscribes to a channel. See {struct http_sse_subscribe_args} for possible
|
671
|
+
* arguments.
|
672
|
+
*
|
673
|
+
* Returns a subscription ID on success and 0 on failure.
|
674
|
+
*
|
675
|
+
* All subscriptions are automatically revoked once the connection is closed.
|
676
|
+
*
|
677
|
+
* If the connections subscribes to the same channel more than once, messages
|
678
|
+
* will be merged. However, another subscription ID will be assigned, and two
|
679
|
+
* calls to {http_sse_unsubscribe} will be required in order to unregister from
|
680
|
+
* the channel.
|
681
|
+
*/
|
682
|
+
uintptr_t http_sse_subscribe(http_sse_s *sse,
|
683
|
+
struct http_sse_subscribe_args args);
|
131
684
|
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
http_settings_s settings);
|
685
|
+
/** This macro allows easy access to the `http_sse_subscribe` function. */
|
686
|
+
#define http_sse_subscribe(sse, ...) \
|
687
|
+
http_sse_subscribe((sse), (struct http_sse_subscribe_args){__VA_ARGS__})
|
136
688
|
|
137
|
-
|
138
|
-
|
689
|
+
/**
|
690
|
+
* Cancels a subscription and invalidates the subscription object.
|
691
|
+
*/
|
692
|
+
void http_sse_unsubscribe(http_sse_s *sse, uintptr_t subscription);
|
693
|
+
|
694
|
+
/**
|
695
|
+
* Named arguments for the {http_sse_write} function.
|
696
|
+
*
|
697
|
+
* These arguments list the possible fields for the SSE event.
|
698
|
+
*
|
699
|
+
* Event fields listed here:
|
700
|
+
* https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events
|
701
|
+
*/
|
702
|
+
struct http_sse_write_args {
|
703
|
+
fio_cstr_s id; /* (optionl) sets the `id` event property. */
|
704
|
+
fio_cstr_s event; /* (optionl) sets the `event` event property. */
|
705
|
+
fio_cstr_s data; /* (optionl) sets the `data` event property. */
|
706
|
+
intptr_t retry; /* (optionl) sets the `retry` event property. */
|
707
|
+
};
|
708
|
+
|
709
|
+
/**
|
710
|
+
* Writes data to an EventSource (SSE) connection.
|
711
|
+
*
|
712
|
+
* See the {struct http_sse_write_args} for possible named arguments.
|
713
|
+
*/
|
714
|
+
int http_sse_write(http_sse_s *sse, struct http_sse_write_args);
|
715
|
+
#define http_sse_write(sse, ...) \
|
716
|
+
http_sse_write((sse), (struct http_sse_write_args){__VA_ARGS__})
|
717
|
+
|
718
|
+
/**
|
719
|
+
* Get the connection's UUID (for facil_defer and similar use cases).
|
720
|
+
*/
|
721
|
+
intptr_t http_sse2uuid(http_sse_s *sse);
|
722
|
+
|
723
|
+
/**
|
724
|
+
* Closes an EventSource (SSE) connection.
|
725
|
+
*/
|
726
|
+
int http_sse_close(http_sse_s *sse);
|
727
|
+
|
728
|
+
/**
|
729
|
+
* Duplicates an SSE handle by reference, remember to http_sse_free.
|
730
|
+
*
|
731
|
+
* Returns the same object (increases a reference count, no allocation is made).
|
732
|
+
*/
|
733
|
+
http_sse_s *http_sse_dup(http_sse_s *sse);
|
734
|
+
|
735
|
+
/**
|
736
|
+
* Frees an SSE handle by reference (decreases the reference count).
|
737
|
+
*/
|
738
|
+
void http_sse_free(http_sse_s *sse);
|
139
739
|
|
140
740
|
/* *****************************************************************************
|
141
|
-
HTTP
|
142
|
-
*/
|
741
|
+
HTTP GET and POST parsing helpers
|
742
|
+
***************************************************************************** */
|
743
|
+
|
744
|
+
/**
|
745
|
+
* Attempts to decode the request's body.
|
746
|
+
*
|
747
|
+
* Supported Types include:
|
748
|
+
* * application/x-www-form-urlencoded
|
749
|
+
* * application/json
|
750
|
+
* * multipart/form-data
|
751
|
+
*
|
752
|
+
* This should be called before `http_parse_query`, in order to support JSON
|
753
|
+
* data.
|
754
|
+
*
|
755
|
+
* If the JSON data isn't an object, it will be saved under the key "JSON" in
|
756
|
+
* the `params` hash.
|
757
|
+
*
|
758
|
+
* If the `multipart/form-data` type contains JSON files, they will NOT be
|
759
|
+
* parsed (they will behave like any other file, with `data`, `type` and
|
760
|
+
* `filename` keys assigned). This allows non-object JSON data (such as array)
|
761
|
+
* to be handled by the app.
|
762
|
+
*/
|
763
|
+
int http_parse_body(http_s *h);
|
764
|
+
|
765
|
+
/**
|
766
|
+
* Parses the query part of an HTTP request/response. Uses `http_add2hash`.
|
767
|
+
*
|
768
|
+
* This should be called after the `http_parse_body` function, just in case the
|
769
|
+
* body is JSON that doesn't have an object at it's root.
|
770
|
+
*/
|
771
|
+
void http_parse_query(http_s *h);
|
772
|
+
|
773
|
+
/** Parses any Cookie / Set-Cookie headers, using the `http_add2hash` scheme. */
|
774
|
+
void http_parse_cookies(http_s *h, uint8_t is_url_encoded);
|
775
|
+
|
776
|
+
/**
|
777
|
+
* Adds a named parameter to the hash, converting a string to an object and
|
778
|
+
* resolving nesting references and URL decoding if required.
|
779
|
+
*
|
780
|
+
* i.e.:
|
781
|
+
*
|
782
|
+
* * "name[]" references a nested Array (nested in the Hash).
|
783
|
+
* * "name[key]" references a nested Hash.
|
784
|
+
* * "name[][key]" references a nested Hash within an array. Hash keys will be
|
785
|
+
* unique (repeating a key advances the hash).
|
786
|
+
* * These rules can be nested (i.e. "name[][key1][][key2]...")
|
787
|
+
* * "name[][]" is an error (there's no way for the parser to analyse
|
788
|
+
* dimentions)
|
789
|
+
*
|
790
|
+
* Note: names can't begine with "[" or end with "]" as these are reserved
|
791
|
+
* characters.
|
792
|
+
*/
|
793
|
+
int http_add2hash(FIOBJ dest, char *name, size_t name_len, char *value,
|
794
|
+
size_t value_len, uint8_t encoded);
|
795
|
+
|
796
|
+
/**
|
797
|
+
* Adds a named parameter to the hash, using an existing object and resolving
|
798
|
+
* nesting references.
|
799
|
+
*
|
800
|
+
* i.e.:
|
801
|
+
*
|
802
|
+
* * "name[]" references a nested Array (nested in the Hash).
|
803
|
+
* * "name[key]" references a nested Hash.
|
804
|
+
* * "name[][key]" references a nested Hash within an array. Hash keys will be
|
805
|
+
* unique (repeating a key advances the hash).
|
806
|
+
* * These rules can be nested (i.e. "name[][key1][][key2]...")
|
807
|
+
* * "name[][]" is an error (there's no way for the parser to analyse
|
808
|
+
* dimentions)
|
809
|
+
*
|
810
|
+
* Note: names can't begine with "[" or end with "]" as these are reserved
|
811
|
+
* characters.
|
812
|
+
*/
|
813
|
+
int http_add2hash2(FIOBJ dest, char *name, size_t name_len, FIOBJ value,
|
814
|
+
uint8_t encoded);
|
815
|
+
|
816
|
+
/* *****************************************************************************
|
817
|
+
HTTP Status Strings and Mime-Type helpers
|
818
|
+
***************************************************************************** */
|
819
|
+
|
820
|
+
/** Returns a human readable string related to the HTTP status number. */
|
821
|
+
fio_cstr_s http_status2str(uintptr_t status);
|
822
|
+
|
823
|
+
/** Registers a Mime-Type to be associated with the file extension. */
|
824
|
+
void http_mimetype_register(char *file_ext, size_t file_ext_len,
|
825
|
+
FIOBJ mime_type_str);
|
826
|
+
|
827
|
+
/**
|
828
|
+
* Finds the mime-type associated with the file extension, returning a String on
|
829
|
+
* success and FIOBJ_INVALID on failure.
|
830
|
+
*
|
831
|
+
* Remember to call `fiobj_free`.
|
832
|
+
*/
|
833
|
+
FIOBJ http_mimetype_find(char *file_ext, size_t file_ext_len);
|
834
|
+
|
835
|
+
/**
|
836
|
+
* Returns the mime-type associated with the URL or the default mime-type for
|
837
|
+
* HTTP.
|
838
|
+
*
|
839
|
+
* Remember to call `fiobj_free`.
|
840
|
+
*/
|
841
|
+
FIOBJ http_mimetype_find2(FIOBJ url);
|
842
|
+
|
843
|
+
/** Clears the Mime-Type registry (it will be emoty afterthis call). */
|
844
|
+
void http_mimetype_clear(void);
|
845
|
+
|
846
|
+
/* *****************************************************************************
|
847
|
+
Commonly used headers (fiobj Symbol objects)
|
848
|
+
***************************************************************************** */
|
849
|
+
|
850
|
+
extern FIOBJ HTTP_HEADER_ACCEPT;
|
851
|
+
extern FIOBJ HTTP_HEADER_CACHE_CONTROL;
|
852
|
+
extern FIOBJ HTTP_HEADER_CONNECTION;
|
853
|
+
extern FIOBJ HTTP_HEADER_CONTENT_ENCODING;
|
854
|
+
extern FIOBJ HTTP_HEADER_CONTENT_LENGTH;
|
855
|
+
extern FIOBJ HTTP_HEADER_CONTENT_RANGE;
|
856
|
+
extern FIOBJ HTTP_HEADER_CONTENT_TYPE;
|
857
|
+
extern FIOBJ HTTP_HEADER_COOKIE;
|
858
|
+
extern FIOBJ HTTP_HEADER_DATE;
|
859
|
+
extern FIOBJ HTTP_HEADER_ETAG;
|
860
|
+
extern FIOBJ HTTP_HEADER_HOST;
|
861
|
+
extern FIOBJ HTTP_HEADER_LAST_MODIFIED;
|
862
|
+
extern FIOBJ HTTP_HEADER_ORIGIN;
|
863
|
+
extern FIOBJ HTTP_HEADER_SET_COOKIE;
|
864
|
+
extern FIOBJ HTTP_HEADER_UPGRADE;
|
865
|
+
|
866
|
+
/* *****************************************************************************
|
867
|
+
HTTP General Helper functions that could be used globally
|
868
|
+
***************************************************************************** */
|
869
|
+
|
870
|
+
/**
|
871
|
+
* Returns a String object representing the unparsed HTTP request (HTTP version
|
872
|
+
* is capped at HTTP/1.1). Mostly usable for proxy usage and debugging.
|
873
|
+
*/
|
874
|
+
FIOBJ http_req2str(http_s *h);
|
875
|
+
|
876
|
+
/**
|
877
|
+
* Writes a log line to `stderr` about the request / response object.
|
878
|
+
*
|
879
|
+
* This function is called automatically if the `.log` setting is enabled.
|
880
|
+
*/
|
881
|
+
void http_write_log(http_s *h);
|
882
|
+
/* *****************************************************************************
|
883
|
+
HTTP Time related helper functions that could be used globally
|
884
|
+
***************************************************************************** */
|
143
885
|
|
144
886
|
/**
|
145
887
|
A faster (yet less localized) alternative to `gmtime_r`.
|
@@ -148,7 +890,7 @@ See the libc `gmtime_r` documentation for details.
|
|
148
890
|
|
149
891
|
Falls back to `gmtime_r` for dates before epoch.
|
150
892
|
*/
|
151
|
-
struct tm *http_gmtime(
|
893
|
+
struct tm *http_gmtime(time_t timer, struct tm *tmbuf);
|
152
894
|
|
153
895
|
/**
|
154
896
|
Writes an HTTP date string to the `target` buffer.
|
@@ -172,36 +914,14 @@ size_t http_date2rfc2822(char *target, struct tm *tmbuf);
|
|
172
914
|
*/
|
173
915
|
size_t http_time2str(char *target, const time_t t);
|
174
916
|
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
Writes an **unsigned** number to a buffer, as a string. This is an unsafe
|
179
|
-
functions that assumes the buffer will have at least 21 bytes and isn't NULL.
|
180
|
-
|
181
|
-
A NULL terminating byte is written.
|
182
|
-
|
183
|
-
Returns the number of bytes actually written (excluding the NULL byte).
|
184
|
-
*/
|
185
|
-
static inline size_t http_ul2a(char *dest, size_t num) {
|
186
|
-
uint8_t digits = 1;
|
187
|
-
size_t tmp = num;
|
188
|
-
while ((tmp /= 10))
|
189
|
-
++digits;
|
190
|
-
|
191
|
-
dest += digits;
|
192
|
-
*(dest--) = 0;
|
193
|
-
for (size_t i = 0; i < digits; i++) {
|
194
|
-
num = num - (10 * (tmp = (num / 10)));
|
195
|
-
*(dest--) = '0' + num;
|
196
|
-
num = tmp;
|
197
|
-
}
|
198
|
-
return digits;
|
199
|
-
}
|
917
|
+
/* *****************************************************************************
|
918
|
+
HTTP URL decoding helper functions that might be used globally
|
919
|
+
***************************************************************************** */
|
200
920
|
|
201
921
|
/** Decodes a URL encoded string, no buffer overflow protection. */
|
202
922
|
ssize_t http_decode_url_unsafe(char *dest, const char *url_data);
|
203
923
|
|
204
|
-
/** Decodes a URL encoded string (
|
924
|
+
/** Decodes a URL encoded string (query / form data). */
|
205
925
|
ssize_t http_decode_url(char *dest, const char *url_data, size_t length);
|
206
926
|
|
207
927
|
/** Decodes the "path" part of a request, no buffer overflow protection. */
|
@@ -211,8 +931,9 @@ ssize_t http_decode_path_unsafe(char *dest, const char *url_data);
|
|
211
931
|
*/
|
212
932
|
ssize_t http_decode_path(char *dest, const char *url_data, size_t length);
|
213
933
|
|
934
|
+
/* support C++ */
|
214
935
|
#ifdef __cplusplus
|
215
|
-
}
|
936
|
+
}
|
216
937
|
#endif
|
217
938
|
|
218
|
-
#endif
|
939
|
+
#endif /* H_HTTP_H */
|