-
Notifications
You must be signed in to change notification settings - Fork 4
/
iwn_http_server.h
359 lines (295 loc) · 14.3 KB
/
iwn_http_server.h
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
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
#pragma once
/// Low level HTTP server.
#include "iwn_poller_adapter.h"
#include "iwn_pairs.h"
#include <iowow/iwxstr.h>
#include <iowow/iwjson.h>
#include <pthread.h>
#include <stdarg.h>
IW_EXTERN_C_START;
struct iwn_http_server {
const char *listen;
void *user_data;
int fd;
int port;
};
struct iwn_http_req {
void *user_data; ///< Arbitrary user defined data.
int64_t user_id; ///< Application controlled user id.
pthread_mutex_t user_mtx; ///< Mutex associated with request, can be used by user code.
uint64_t user_flags; ///< Arbitrary user defined flags
void *server_user_data; ///< User data specified in `iwn_http_server_spec`
const char *session_cookie_params; ///< Optional params used to store session cookie. Default: lax
void (*on_request_dispose)(struct iwn_http_req*); ///< Request dispose handler.
void (*on_response_headers_write)(struct iwn_http_req*);
bool (*on_response_completed)(struct iwn_http_req*);
struct iwn_poller_adapter *poller_adapter;
int session_cookie_max_age_sec; ///< Max age of session cookies sec.
};
typedef void (*iwn_http_server_on_dispose)(const struct iwn_http_server*);
/// Request handler.
/// Returns `false` if client connection should be removed from poller (terminated).
///
typedef bool (*iwn_http_server_request_handler)(struct iwn_http_req*);
typedef bool (*iwn_http_server_chunk_handler)(struct iwn_http_req*, bool *again);
/// Handler responsible for establishing a new HTTP proxy session.
///
/// Returns true if a new proxy session should be started.
/// Use `iwn_http_proxy_xxx_set` methods to set specific procy configuration
/// @note At least iwn_http_proxy_url_set() must be called.
///
typedef bool (*iwn_http_server_proxy_handler)(struct iwn_http_req*);
/// Server TLS 1.2 config.
struct iwn_http_server_ssl_spec {
const char *certs; ///< PEM certificates text data or path to PEM file.
const char *private_key; ///< PEM private key text data or path to PEM file.
ssize_t certs_len; ///< -1 If `certs` data is a file path.
ssize_t private_key_len; ///< -1 If `private_key` data is a file path.
bool private_key_in_buffer; ///< true if `certs_data` specified as data buffer rather a file name.
bool certs_in_buffer; ///< true if `private_key_in_buffer` specified as data buffer rather a file name.
};
struct iwn_http_server_spec {
iwn_http_server_request_handler request_handler; ///< Request handler (Required).
iwn_http_server_proxy_handler proxy_handler; ///< HTTP proxy session setup handler.
struct iwn_poller *poller; ///< Poller reference (Required).
/// IP/Host/Socket file HTTP server will listen on.
/// If listen starts with: `socket://` it will be treated as Unix domain socket file.
const char *listen;
void *user_data; ///< Arbitrary user data propagated into struct
/// iwn_http_req::user_data
iwn_http_server_on_dispose on_server_dispose; ///< Server dispose callback handler.
struct iwn_http_server_ssl_spec ssl; ///< TLS 1.2 parameters.
int port; ///< If -1 listen attribute treated as a Unix socket file.
/// Default: 8080 http, 8443 https
int socket_queue_size; ///< Default: 64
int request_buf_max_size; ///< Default: 8Mb
int request_buf_size; ///< Default: 1023, Min: 1023
int request_timeout_keepalive_sec; ///< -1 Disable timeout, 0 Use default timeout: 120sec
int request_timeout_sec; ///< -1 Disable timeout, 0 Use default timeout: 20sec
int request_token_max_len; ///< Default: 8191, Min: 8191
int request_max_headers_count; ///< Default: 127
};
/// Creates an instance of http server.
///
/// Registers server in the poller provider by struct iwn_http_server_spec.
///
/// @param[out] out_fd File descriptor of the server listener socket
///
IW_EXPORT WUR iwrc iwn_http_server_create(
const struct iwn_http_server_spec*,
int *out_fd);
/// Upgrade server accept routine configuration to use
/// SSL parameters provider by `ssl`.
///
/// @param poller Poller where server accept socket resides.
/// @param server_fd Server accept connection fd provided by iwn_http_server_create().
/// @param ssl SSL configuration.
///
IW_EXPORT bool iwn_http_server_ssl_set(
struct iwn_poller *poller,
int server_fd,
const struct iwn_http_server_ssl_spec *ssl);
/// Start reading the next chunk of data from request body.
IW_EXPORT void iwn_http_request_chunk_next(struct iwn_http_req*, iwn_http_server_chunk_handler);
/// Gets the current chunk of request data currently available.
/// Used by @ref iwn_http_server_chunk_handler
///
IW_EXPORT struct iwn_val iwn_http_request_chunk_get(struct iwn_http_req*);
/// Returns `true` when request in the streamed mode where `iwn_http_request_chunk_next()` calls in use.
/// Streamed mode is activated for chunked requests or when request body greater than 8Mb (defined by
/// @ref iwn_http_server_spec::request_buf_max_size)
///
IW_EXPORT bool iwn_http_request_is_streamed(struct iwn_http_req*);
/// Returns `true` when SSL(TLS) user i request transport connection.
IW_EXPORT bool iwn_http_request_is_secure(struct iwn_http_req*);
/// Returns remote ip address of request client.
IW_EXPORT const char* iwn_http_request_remote_ip(struct iwn_http_req*);
/// Get HTTP Target path for given request.
/// @note @ref iwn_val::buf "buf" value is not null terminated.
///
IW_EXPORT struct iwn_val iwn_http_request_target(struct iwn_http_req*);
/// Returns `true` if request target is matched to the given `target`
IW_EXPORT bool iwn_http_request_target_is(struct iwn_http_req*, const char *target, ssize_t target_len);
/// Get HTTP request method name.
/// @note @ref iwn_val::buf "buf" value is not null terminated.
///
IW_EXPORT struct iwn_val iwn_http_request_method(struct iwn_http_req*);
/// Get the body of HTTP request.
/// @warning This method works only when `iwn_http_request_is_streamed()` is false.
///
IW_EXPORT struct iwn_val iwn_http_request_body(struct iwn_http_req*);
/// Take a lock on generic user mutex associated with givene request.
IW_EXPORT void iwn_http_request_user_lock(struct iwn_http_req*);
/// Unlock generic user
IW_EXPORT void iwn_http_request_user_unlock(struct iwn_http_req*);
/// Get the first occurrence of request heade`r value with given `header_name`.
/// If no header is found the zero `iwn_val` structure will be returned.
///
IW_EXPORT struct iwn_val iwn_http_request_header_get(
struct iwn_http_req*,
const char *header_name,
ssize_t header_name_len);
/// Create an iterator over request header values.
/// Returns `true` until iterator has next value.
///
/// @param[out] key Header name
/// @param[out] val Header value
/// @param[in,out] Iterator step. Must be zero on first run.
///
IW_EXPORT bool iwn_http_request_headers_iterate(
struct iwn_http_req*,
struct iwn_val *key,
struct iwn_val *val,
int *iter);
/// Sets automatic keep-alive detection for request connection. Active by default.
IW_EXPORT void iwn_http_connection_set_automatic(struct iwn_http_req *request);
/// Force request connection to be in keep-alive mode.
IW_EXPORT void iwn_http_connection_set_keep_alive(struct iwn_http_req*, bool keep_alive);
/// Sets connection in `upgrade` mode. User by websocket server.
IW_EXPORT void iwn_http_connection_set_upgrade(struct iwn_http_req*);
/// Returns true if connection is in upgrade mode.
IW_EXPORT bool iwn_http_connection_is_upgrade(struct iwn_http_req*);
/// Returns an error code associated with http proxy.
IW_EXPORT iwrc iwn_http_proxy_is_error(struct iwn_http_req*);
/// Is http proxy enabled for given request.
IW_EXPORT bool iwn_http_proxy_is_enabled(struct iwn_http_req*);
/// Sets HTTP URL for proxied endpoint.
/// @note This method must be called by `iwn_http_server_proxy_handler` in order
/// to establish a proxy session.
IW_EXPORT bool iwn_http_proxy_url_set(struct iwn_http_req*, const char *url, ssize_t url_len);
/// Set a request header to the proxied endpoint.
IW_EXPORT bool iwn_http_proxy_header_set(
struct iwn_http_req*,
const char *header_name,
const char *header_value,
ssize_t header_value_len);
/// Sets a maximum size of IO buffer between client and proxy endpoint in bytes.
/// Zero value means unlimited buffer.
IW_EXPORT bool iwn_http_proxy_channel_buf_max_size_set(struct iwn_http_req*, size_t max_size);
/// Sets timeout in seconds for connection to proxied endpoint.
/// ~7 seconds on Linux by default.
IW_EXPORT bool iwn_http_proxy_timeout_connect_set(struct iwn_http_req*, uint32_t timeout_sec);
/// Sets timeout for socket data inactivity. Default: 0 (unlimited)
IW_EXPORT bool iwn_http_proxy_timeout_data_set(struct iwn_http_req*, uint32_t timeout_sec);
/// Sets HTTP response status code for given request object.
IW_EXPORT iwrc iwn_http_response_code_set(struct iwn_http_req*, int code);
/// Returns current HTTP status code set by `iwn_http_response_code_set()`
IW_EXPORT int iwn_http_response_code_get(struct iwn_http_req*);
/// Sets HTTP response header.
/// @note If header with the same `header_name` was set previously its value will be updated.
IW_EXPORT iwrc iwn_http_response_header_set(
struct iwn_http_req*,
const char *header_name,
const char *header_value,
ssize_t header_value_len);
/// Sets HTTP response header with header value given as integer.
/// @note If header with the same `header_name` was set previously its value will be updated.
///
IW_EXPORT iwrc iwn_http_response_header_i64_set(
struct iwn_http_req*,
const char *header_name,
int64_t header_value);
/// Sets HTTP response header with printf formatted value.
/// @note If header with the same `header_name` was set previously its value will be updated.
///
IW_EXPORT iwrc iwn_http_response_header_printf_va(
struct iwn_http_req *req,
const char *header_name,
const char *format,
va_list va);
/// Set HTTP response header with printf formatted value.
/// @note If header with the same `header_name` was set previously its value will be updated.
///
IW_EXPORT iwrc iwn_http_response_header_printf(
struct iwn_http_req *req,
const char *header_name,
const char *format,
...) __attribute__((format(__printf__, 3, 4)));
/// Added HTTP response header.
IW_EXPORT iwrc iwn_http_response_header_add(
struct iwn_http_req*,
const char *header_name,
const char *header_value,
ssize_t header_value_len);
/// Gets value of HTTP response header.
/// If no header is found the zero `iwn_val` structure will be returned.
///
IW_EXPORT struct iwn_val iwn_http_response_header_get(struct iwn_http_req*, const char *header_name);
/// Dispose response body.
IW_EXPORT void iwn_http_response_body_clear(struct iwn_http_req*);
/// Set response body.
/// @param body Body data buffer
/// @param body_len Body data length
/// @param body_free Optional body dispose callback.
///
IW_EXPORT void iwn_http_response_body_set(
struct iwn_http_req*,
const char *body,
ssize_t body_len,
void (*body_free)(void*));
/// Completes a response for given request.
/// All response headers, body will be transferred to the client peer.
///
IW_EXPORT iwrc iwn_http_response_end(struct iwn_http_req*);
/// Generate a minimal HTTP response according to the given HTTP response `code`.
IW_EXPORT bool iwn_http_response_by_code(struct iwn_http_req*, int code);
/// Writes a given response `body` and completes response for specified request.
IW_EXPORT bool iwn_http_response_write(
struct iwn_http_req*,
int status_code,
const char *content_type,
const char *body,
ssize_t body_len);
/// Writes a given JSON object and completes response for specified request.
IW_EXPORT bool iwn_http_response_write_jbl(
struct iwn_http_req*,
int status_code,
struct jbl *jbl);
/// Writes a given JSON object and completes response for specified request.
IW_EXPORT bool iwn_http_response_write_jbn(
struct iwn_http_req*,
int status_code,
JBL_NODE n);
/// Writes a given response as prinf formatted value and completes response for specified request.
IW_EXPORT bool iwn_http_response_printf(
struct iwn_http_req*,
int status_code, const char *content_type,
const char *body_fmt, ...)
__attribute__((format(__printf__, 4, 5)));
/// Writes a given response as prinf formatted value and completes response for specified request.
IW_EXPORT bool iwn_http_response_printf_va(
struct iwn_http_req*,
int status_code, const char *content_type,
const char *body_fmt, va_list va);
/// Starts/continues writing a chunked response.
/// `chunk_cb` used to fill the next chunk of data.
/// Set `again` to true if you want to repeat chunk writing iteration instead of recursive calling
/// `iwn_http_response_chunk_write()` for next chunk.
///
IW_EXPORT iwrc iwn_http_response_chunk_write(
struct iwn_http_req*,
char *body,
ssize_t body_len,
iwn_http_server_chunk_handler chunk_cb,
bool *again);
/// Finishes a chunked response.
IW_EXPORT iwrc iwn_http_response_chunk_end(struct iwn_http_req*);
/// Starts writing of streamed response.
/// `chunk_cb` will be called later for fill next stream chunk.
IW_EXPORT iwrc iwn_http_response_stream_start(struct iwn_http_req*, iwn_http_server_chunk_handler chunk_cb);
/// Continues writing a streamed response.
/// `chunk_cb` used to fill the next chunk of data.
/// Set `again` to true if you want to repeat chunk writing iteration instead of recursive calling
/// `iwn_http_response_stream_write()` for next chunk.
///
IW_EXPORT void iwn_http_response_stream_write(
struct iwn_http_req*,
char *buf,
ssize_t buf_len,
void ( *buf_free )(void*),
iwn_http_server_chunk_handler chunk_cb,
bool *again);
/// Finishes a streamed response.
IW_EXPORT void iwn_http_response_stream_end(struct iwn_http_req*);
IW_EXPORT void iwn_http_inject_poller_events_handler(struct iwn_http_req*, iwn_on_poller_adapter_event eh);
IW_EXTERN_C_END;