Coverage Report

Created: 2025-07-18 06:06

/src/unit/src/nxt_http.h
Line
Count
Source (jump to first uncovered line)
1
2
/*
3
 * Copyright (C) Igor Sysoev
4
 * Copyright (C) NGINX, Inc.
5
 */
6
7
#ifndef _NXT_HTTP_H_INCLUDED_
8
#define _NXT_HTTP_H_INCLUDED_
9
10
#include <nxt_regex.h>
11
#include <nxt_otel.h>
12
13
14
typedef enum {
15
    NXT_HTTP_UNSET = -1,
16
    NXT_HTTP_INVALID = 0,
17
18
    NXT_HTTP_CONTINUE = 100,
19
    NXT_HTTP_SWITCHING_PROTOCOLS = 101,
20
21
    NXT_HTTP_OK = 200,
22
    NXT_HTTP_NO_CONTENT = 204,
23
24
    NXT_HTTP_MULTIPLE_CHOICES = 300,
25
    NXT_HTTP_MOVED_PERMANENTLY = 301,
26
    NXT_HTTP_FOUND = 302,
27
    NXT_HTTP_SEE_OTHER = 303,
28
    NXT_HTTP_NOT_MODIFIED = 304,
29
    NXT_HTTP_TEMPORARY_REDIRECT = 307,
30
    NXT_HTTP_PERMANENT_REDIRECT = 308,
31
32
    NXT_HTTP_BAD_REQUEST = 400,
33
    NXT_HTTP_FORBIDDEN = 403,
34
    NXT_HTTP_NOT_FOUND = 404,
35
    NXT_HTTP_METHOD_NOT_ALLOWED = 405,
36
    NXT_HTTP_NOT_ACCEPTABLE = 406,
37
    NXT_HTTP_REQUEST_TIMEOUT = 408,
38
    NXT_HTTP_LENGTH_REQUIRED = 411,
39
    NXT_HTTP_PAYLOAD_TOO_LARGE = 413,
40
    NXT_HTTP_URI_TOO_LONG = 414,
41
    NXT_HTTP_UPGRADE_REQUIRED = 426,
42
    NXT_HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE = 431,
43
44
    NXT_HTTP_TO_HTTPS = 497,
45
46
    NXT_HTTP_INTERNAL_SERVER_ERROR = 500,
47
    NXT_HTTP_NOT_IMPLEMENTED = 501,
48
    NXT_HTTP_BAD_GATEWAY = 502,
49
    NXT_HTTP_SERVICE_UNAVAILABLE = 503,
50
    NXT_HTTP_GATEWAY_TIMEOUT = 504,
51
    NXT_HTTP_VERSION_NOT_SUPPORTED = 505,
52
    NXT_HTTP_SERVER_ERROR_MAX = 599,
53
54
    NXT_HTTP_STATUS_MAX = 999,
55
} nxt_http_status_t;
56
57
58
typedef enum {
59
    NXT_HTTP_TE_NONE = 0,
60
    NXT_HTTP_TE_CHUNKED = 1,
61
    NXT_HTTP_TE_UNSUPPORTED = 2,
62
} nxt_http_te_t;
63
64
65
typedef enum {
66
    NXT_HTTP_PROTO_H1 = 0,
67
    NXT_HTTP_PROTO_H2,
68
    NXT_HTTP_PROTO_DEVNULL,
69
} nxt_http_protocol_t;
70
71
72
typedef struct {
73
    nxt_work_handler_t              ready_handler;
74
    nxt_work_handler_t              error_handler;
75
} nxt_http_request_state_t;
76
77
78
typedef struct nxt_h1proto_s        nxt_h1proto_t;
79
80
struct nxt_h1p_websocket_timer_s {
81
    nxt_timer_t                     timer;
82
    nxt_h1proto_t                   *h1p;
83
    nxt_msec_t                      keepalive_interval;
84
};
85
86
87
typedef union {
88
    void                            *any;
89
    nxt_h1proto_t                   *h1;
90
} nxt_http_proto_t;
91
92
93
#define nxt_http_field_name_set(_field, _name)                                \
94
0
    do {                                                                      \
95
0
        (_field)->name_length = nxt_length(_name);                            \
96
0
        (_field)->name = (u_char *) _name;                                    \
97
0
    } while (0)
98
99
100
#define nxt_http_field_set(_field, _name, _value)                             \
101
0
    do {                                                                      \
102
0
        (_field)->name_length = nxt_length(_name);                            \
103
0
        (_field)->value_length = nxt_length(_value);                          \
104
0
        (_field)->name = (u_char *) _name;                                    \
105
0
        (_field)->value = (u_char *) _value;                                  \
106
0
    } while (0)
107
108
109
typedef struct {
110
    nxt_list_t                      *fields;
111
    nxt_http_field_t                *date;
112
    nxt_http_field_t                *content_type;
113
    nxt_http_field_t                *content_length;
114
    nxt_off_t                       content_length_n;
115
    const nxt_str_t                 *mime_type;
116
} nxt_http_response_t;
117
118
119
typedef struct nxt_upstream_server_s  nxt_upstream_server_t;
120
121
typedef struct {
122
    nxt_http_proto_t                proto;
123
    nxt_http_request_t              *request;
124
    nxt_upstream_server_t           *server;
125
    nxt_list_t                      *fields;
126
    nxt_buf_t                       *body;
127
128
    nxt_http_status_t               status:16;
129
    nxt_http_protocol_t             protocol:8;       /* 2 bits */
130
    uint8_t                         header_received;  /* 1 bit  */
131
    uint8_t                         closed;           /* 1 bit  */
132
} nxt_http_peer_t;
133
134
135
struct nxt_http_request_s {
136
    nxt_http_proto_t                proto;
137
    nxt_socket_conf_joint_t         *conf;
138
139
    nxt_mp_t                        *mem_pool;
140
141
    nxt_buf_t                       *body;
142
    nxt_buf_t                       *ws_frame;
143
    nxt_buf_t                       *out;
144
    const nxt_http_request_state_t  *state;
145
146
    nxt_nsec_t                      start_time;
147
148
    nxt_str_t                       host;
149
    nxt_str_t                       server_name;
150
    nxt_str_t                       request_line;
151
    nxt_str_t                       target;
152
    nxt_str_t                       version;
153
    nxt_str_t                       *method;
154
    nxt_str_t                       *path;
155
    nxt_str_t                       *args;
156
157
    nxt_str_t                       args_decoded;
158
    nxt_array_t                     *arguments;  /* of nxt_http_name_value_t */
159
    nxt_array_t                     *cookies;    /* of nxt_http_name_value_t */
160
    nxt_list_t                      *fields;
161
    nxt_http_field_t                *content_type;
162
    nxt_http_field_t                *content_length;
163
    nxt_http_field_t                *chunked_field;
164
    nxt_http_field_t                *cookie;
165
    nxt_http_field_t                *referer;
166
    nxt_http_field_t                *user_agent;
167
    nxt_http_field_t                *authorization;
168
    nxt_off_t                       content_length_n;
169
170
    nxt_sockaddr_t                  *remote;
171
    nxt_sockaddr_t                  *local;
172
    nxt_task_t                      task;
173
174
    nxt_timer_t                     timer;
175
    void                            *timer_data;
176
177
    nxt_tstr_query_t                *tstr_query;
178
    nxt_tstr_cache_t                tstr_cache;
179
180
    nxt_http_action_t               *action;
181
    void                            *req_rpc_data;
182
183
#if (NXT_HAVE_REGEX)
184
    nxt_regex_match_t               *regex_match;
185
#endif
186
187
    nxt_http_peer_t                 *peer;
188
    nxt_buf_t                       *last;
189
190
    nxt_queue_link_t                app_link;   /* nxt_app_t.ack_waiting_req */
191
    nxt_event_engine_t              *engine;
192
    nxt_work_t                      err_work;
193
194
    nxt_http_response_t             resp;
195
196
#if (NXT_HAVE_OTEL)
197
    nxt_otel_state_t                *otel;
198
#endif
199
200
    nxt_http_status_t               status:16;
201
202
    uint8_t                         log_route;    /* 1 bit */
203
    uint8_t                         quoted_target;  /* 1 bit */
204
    uint8_t                         uri_changed;  /* 1 bit */
205
206
    uint8_t                         pass_count;   /* 8 bits */
207
    uint8_t                         app_target;
208
    nxt_http_protocol_t             protocol:8;   /* 2 bits */
209
    uint8_t                         tls;          /* 1 bit  */
210
    uint8_t                         logged;       /* 1 bit  */
211
    uint8_t                         header_sent;  /* 1 bit  */
212
    uint8_t                         inconsistent; /* 1 bit  */
213
    uint8_t                         error;        /* 1 bit  */
214
    uint8_t                         websocket_handshake;  /* 1 bit */
215
    uint8_t                         chunked;  /* 1 bit */
216
};
217
218
219
typedef struct {
220
    uint16_t                        hash;
221
    uint16_t                        name_length;
222
    uint32_t                        value_length;
223
    u_char                          *name;
224
    u_char                          *value;
225
} nxt_http_name_value_t;
226
227
228
typedef enum {
229
    NXT_HTTP_URI_ENCODING_NONE = 0,
230
    NXT_HTTP_URI_ENCODING,
231
    NXT_HTTP_URI_ENCODING_PLUS
232
} nxt_http_uri_encoding_t;
233
234
235
typedef struct nxt_http_route_s            nxt_http_route_t;
236
typedef struct nxt_http_route_rule_s       nxt_http_route_rule_t;
237
typedef struct nxt_http_route_addr_rule_s  nxt_http_route_addr_rule_t;
238
239
240
typedef struct {
241
    nxt_conf_value_t                *rewrite;
242
    nxt_conf_value_t                *set_headers;
243
    nxt_conf_value_t                *pass;
244
    nxt_conf_value_t                *ret;
245
    nxt_conf_value_t                *location;
246
    nxt_conf_value_t                *proxy;
247
    nxt_conf_value_t                *share;
248
    nxt_conf_value_t                *index;
249
    nxt_str_t                       chroot;
250
    nxt_conf_value_t                *follow_symlinks;
251
    nxt_conf_value_t                *traverse_mounts;
252
    nxt_conf_value_t                *types;
253
    nxt_conf_value_t                *fallback;
254
} nxt_http_action_conf_t;
255
256
257
struct nxt_http_action_s {
258
    nxt_http_action_t               *(*handler)(nxt_task_t *task,
259
                                        nxt_http_request_t *r,
260
                                        nxt_http_action_t *action);
261
    union {
262
        void                        *conf;
263
        nxt_http_route_t            *route;
264
        nxt_upstream_t              *upstream;
265
        uint32_t                    upstream_number;
266
        nxt_tstr_t                  *tstr;
267
        nxt_str_t                   *pass;
268
    } u;
269
270
    nxt_tstr_t                      *rewrite;
271
    nxt_array_t                     *set_headers;  /* of nxt_http_field_t */
272
    nxt_http_action_t               *fallback;
273
};
274
275
276
typedef struct {
277
    void (*body_read)(nxt_task_t *task, nxt_http_request_t *r);
278
    void (*local_addr)(nxt_task_t *task, nxt_http_request_t *r);
279
    void (*header_send)(nxt_task_t *task, nxt_http_request_t *r,
280
        nxt_work_handler_t body_handler, void *data);
281
    void (*send)(nxt_task_t *task, nxt_http_request_t *r, nxt_buf_t *out);
282
    nxt_off_t (*body_bytes_sent)(nxt_task_t *task, nxt_http_proto_t proto);
283
    void (*discard)(nxt_task_t *task, nxt_http_request_t *r, nxt_buf_t *last);
284
    void (*close)(nxt_task_t *task, nxt_http_proto_t proto,
285
        nxt_socket_conf_joint_t *joint);
286
287
    void (*peer_connect)(nxt_task_t *task, nxt_http_peer_t *peer);
288
    void (*peer_header_send)(nxt_task_t *task, nxt_http_peer_t *peer);
289
    void (*peer_header_read)(nxt_task_t *task, nxt_http_peer_t *peer);
290
    void (*peer_read)(nxt_task_t *task, nxt_http_peer_t *peer);
291
    void (*peer_close)(nxt_task_t *task, nxt_http_peer_t *peer);
292
293
    void (*ws_frame_start)(nxt_task_t *task, nxt_http_request_t *r,
294
        nxt_buf_t *ws_frame);
295
} nxt_http_proto_table_t;
296
297
298
typedef struct {
299
    nxt_str_t                   *header;
300
    uint32_t                    header_hash;
301
} nxt_http_forward_header_t;
302
303
304
struct nxt_http_forward_s {
305
    nxt_http_forward_header_t   client_ip;
306
    nxt_http_forward_header_t   protocol;
307
    nxt_http_route_addr_rule_t  *source;
308
    uint8_t                     recursive;    /* 1 bit */
309
};
310
311
312
0
#define NXT_HTTP_DATE_LEN  nxt_length("Wed, 31 Dec 1986 16:40:00 GMT")
313
314
nxt_inline u_char *
315
nxt_http_date(u_char *buf, struct tm *tm)
316
0
{
317
0
    static const char * const  week[] = { "Sun", "Mon", "Tue", "Wed", "Thu",
318
0
                                          "Fri", "Sat" };
319
320
0
    static const char * const  month[] = { "Jan", "Feb", "Mar", "Apr", "May",
321
0
                                           "Jun", "Jul", "Aug", "Sep", "Oct",
322
0
                                           "Nov", "Dec" };
323
324
0
    return nxt_sprintf(buf, buf + NXT_HTTP_DATE_LEN,
325
0
                       "%s, %02d %s %4d %02d:%02d:%02d GMT",
326
0
                       week[tm->tm_wday], tm->tm_mday,
327
0
                       month[tm->tm_mon], tm->tm_year + 1900,
328
0
                       tm->tm_hour, tm->tm_min, tm->tm_sec);
329
0
}
Unexecuted instantiation: nxt_http_h1p_fuzz.c:nxt_http_date
Unexecuted instantiation: nxt_router.c:nxt_http_date
Unexecuted instantiation: nxt_router_access_log.c:nxt_http_date
Unexecuted instantiation: nxt_http_request.c:nxt_http_date
Unexecuted instantiation: nxt_http_response.c:nxt_http_date
Unexecuted instantiation: nxt_http_error.c:nxt_http_date
Unexecuted instantiation: nxt_http_route.c:nxt_http_date
Unexecuted instantiation: nxt_http_rewrite.c:nxt_http_date
Unexecuted instantiation: nxt_http_set_headers.c:nxt_http_date
Unexecuted instantiation: nxt_http_return.c:nxt_http_date
Unexecuted instantiation: nxt_http_static.c:nxt_http_date
Unexecuted instantiation: nxt_http_proxy.c:nxt_http_date
Unexecuted instantiation: nxt_http_variables.c:nxt_http_date
Unexecuted instantiation: nxt_application.c:nxt_http_date
Unexecuted instantiation: nxt_http_websocket.c:nxt_http_date
Unexecuted instantiation: nxt_h1proto_websocket.c:nxt_http_date
Unexecuted instantiation: nxt_http_compression.c:nxt_http_date
Unexecuted instantiation: nxt_upstream.c:nxt_http_date
Unexecuted instantiation: nxt_upstream_round_robin.c:nxt_http_date
Unexecuted instantiation: nxt_conf_validation.c:nxt_http_date
330
331
332
nxt_int_t nxt_http_init(nxt_task_t *task);
333
nxt_int_t nxt_h1p_init(nxt_task_t *task);
334
nxt_int_t nxt_http_response_hash_init(nxt_task_t *task);
335
336
void nxt_http_conn_init(nxt_task_t *task, void *obj, void *data);
337
nxt_http_request_t *nxt_http_request_create(nxt_task_t *task);
338
void nxt_http_request_error(nxt_task_t *task, nxt_http_request_t *r,
339
    nxt_http_status_t status);
340
void nxt_http_request_read_body(nxt_task_t *task, nxt_http_request_t *r);
341
void nxt_http_request_header_send(nxt_task_t *task, nxt_http_request_t *r,
342
    nxt_work_handler_t body_handler, void *data);
343
void nxt_http_request_ws_frame_start(nxt_task_t *task, nxt_http_request_t *r,
344
    nxt_buf_t *ws_frame);
345
void nxt_http_request_send(nxt_task_t *task, nxt_http_request_t *r,
346
    nxt_buf_t *out);
347
nxt_buf_t *nxt_http_buf_mem(nxt_task_t *task, nxt_http_request_t *r,
348
    size_t size);
349
nxt_buf_t *nxt_http_buf_last(nxt_http_request_t *r);
350
void nxt_http_request_error_handler(nxt_task_t *task, void *obj, void *data);
351
void nxt_http_request_close_handler(nxt_task_t *task, void *obj, void *data);
352
353
nxt_int_t nxt_http_request_host(void *ctx, nxt_http_field_t *field,
354
    uintptr_t data);
355
nxt_int_t nxt_http_request_field(void *ctx, nxt_http_field_t *field,
356
    uintptr_t offset);
357
nxt_int_t nxt_http_request_content_length(void *ctx, nxt_http_field_t *field,
358
    uintptr_t data);
359
360
nxt_array_t *nxt_http_arguments_parse(nxt_http_request_t *r);
361
nxt_array_t *nxt_http_cookies_parse(nxt_http_request_t *r);
362
363
int64_t nxt_http_field_hash(nxt_mp_t *mp, nxt_str_t *name,
364
    nxt_bool_t case_sensitive, uint8_t encoding);
365
int64_t nxt_http_argument_hash(nxt_mp_t *mp, nxt_str_t *name);
366
int64_t nxt_http_header_hash(nxt_mp_t *mp, nxt_str_t *name);
367
int64_t nxt_http_cookie_hash(nxt_mp_t *mp, nxt_str_t *name);
368
369
nxt_http_routes_t *nxt_http_routes_create(nxt_task_t *task,
370
    nxt_router_temp_conf_t *tmcf, nxt_conf_value_t *routes_conf);
371
nxt_http_action_t *nxt_http_action_create(nxt_task_t *task,
372
    nxt_router_temp_conf_t *tmcf, nxt_str_t *pass);
373
nxt_int_t nxt_http_routes_resolve(nxt_task_t *task,
374
    nxt_router_temp_conf_t *tmcf);
375
nxt_int_t nxt_http_pass_segments(nxt_mp_t *mp, nxt_str_t *pass,
376
    nxt_str_t *segments, nxt_uint_t n);
377
nxt_http_action_t *nxt_http_pass_application(nxt_task_t *task,
378
    nxt_router_conf_t *rtcf, nxt_str_t *name);
379
nxt_http_route_addr_rule_t *nxt_http_route_addr_rule_create(
380
    nxt_task_t *task, nxt_mp_t *mp, nxt_conf_value_t *cv);
381
nxt_int_t nxt_http_route_addr_rule(nxt_http_request_t *r,
382
    nxt_http_route_addr_rule_t *addr_rule, nxt_sockaddr_t *sockaddr);
383
nxt_http_route_rule_t *nxt_http_route_types_rule_create(nxt_task_t *task,
384
    nxt_mp_t *mp, nxt_conf_value_t *types);
385
nxt_int_t nxt_http_route_test_rule(nxt_http_request_t *r,
386
    nxt_http_route_rule_t *rule, u_char *start, size_t length);
387
388
nxt_int_t nxt_http_action_init(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
389
    nxt_conf_value_t *cv, nxt_http_action_t *action);
390
void nxt_http_request_action(nxt_task_t *task, nxt_http_request_t *r,
391
    nxt_http_action_t *action);
392
393
nxt_int_t nxt_upstreams_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
394
    nxt_conf_value_t *conf);
395
nxt_int_t nxt_upstreams_joint_create(nxt_router_temp_conf_t *tmcf,
396
    nxt_upstream_t ***upstream_joint);
397
398
nxt_int_t nxt_http_rewrite_init(nxt_router_conf_t *rtcf,
399
    nxt_http_action_t *action, nxt_http_action_conf_t *acf);
400
nxt_int_t nxt_http_rewrite(nxt_task_t *task, nxt_http_request_t *r);
401
402
nxt_int_t nxt_http_set_headers_init(nxt_router_conf_t *rtcf,
403
    nxt_http_action_t *action, nxt_http_action_conf_t *acf);
404
nxt_int_t nxt_http_set_headers(nxt_http_request_t *r);
405
406
nxt_int_t nxt_http_return_init(nxt_router_conf_t *rtcf,
407
    nxt_http_action_t *action, nxt_http_action_conf_t *acf);
408
409
nxt_int_t nxt_http_static_init(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
410
    nxt_http_action_t *action, nxt_http_action_conf_t *acf);
411
nxt_int_t nxt_http_static_mtypes_init(nxt_mp_t *mp, nxt_lvlhsh_t *hash);
412
nxt_int_t nxt_http_static_mtypes_hash_add(nxt_mp_t *mp, nxt_lvlhsh_t *hash,
413
    const nxt_str_t *exten, nxt_str_t *type);
414
nxt_str_t *nxt_http_static_mtype_get(nxt_lvlhsh_t *hash,
415
    const nxt_str_t *exten);
416
417
nxt_http_action_t *nxt_http_application_handler(nxt_task_t *task,
418
    nxt_http_request_t *r, nxt_http_action_t *action);
419
nxt_int_t nxt_upstream_find(nxt_upstreams_t *upstreams, nxt_str_t *name,
420
    nxt_http_action_t *action);
421
nxt_http_action_t *nxt_upstream_proxy_handler(nxt_task_t *task,
422
    nxt_http_request_t *r, nxt_upstream_t *upstream);
423
424
nxt_int_t nxt_http_proxy_init(nxt_mp_t *mp, nxt_http_action_t *action,
425
    nxt_http_action_conf_t *acf);
426
nxt_int_t nxt_http_proxy_date(void *ctx, nxt_http_field_t *field,
427
    uintptr_t data);
428
nxt_int_t nxt_http_proxy_content_length(void *ctx, nxt_http_field_t *field,
429
    uintptr_t data);
430
nxt_int_t nxt_http_proxy_skip(void *ctx, nxt_http_field_t *field,
431
    uintptr_t data);
432
nxt_buf_t *nxt_http_proxy_buf_mem_alloc(nxt_task_t *task, nxt_http_request_t *r,
433
    size_t size);
434
void nxt_http_proxy_buf_mem_free(nxt_task_t *task, nxt_http_request_t *r,
435
    nxt_buf_t *b);
436
437
extern nxt_time_string_t  nxt_http_date_cache;
438
439
extern nxt_lvlhsh_t                        nxt_response_fields_hash;
440
441
extern const nxt_http_proto_table_t  nxt_http_proto[];
442
443
void nxt_h1p_websocket_first_frame_start(nxt_task_t *task,
444
    nxt_http_request_t *r, nxt_buf_t *ws_frame);
445
void nxt_h1p_websocket_frame_start(nxt_task_t *task, nxt_http_request_t *r,
446
    nxt_buf_t *ws_frame);
447
void nxt_h1p_complete_buffers(nxt_task_t *task, nxt_h1proto_t *h1p,
448
    nxt_bool_t all);
449
nxt_msec_t nxt_h1p_conn_request_timer_value(nxt_conn_t *c, uintptr_t data);
450
451
int nxt_http_cond_value(nxt_task_t *task, nxt_http_request_t *r,
452
    nxt_tstr_cond_t *cond);
453
454
extern const nxt_conn_state_t  nxt_h1p_idle_close_state;
455
456
#endif  /* _NXT_HTTP_H_INCLUDED_ */