xref: /unit/src/nxt_http.h (revision 1561:4dae2fd8e02a)
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 
11 typedef enum {
12     NXT_HTTP_UNSET = -1,
13     NXT_HTTP_INVALID = 0,
14 
15     NXT_HTTP_CONTINUE = 100,
16     NXT_HTTP_SWITCHING_PROTOCOLS = 101,
17 
18     NXT_HTTP_OK = 200,
19     NXT_HTTP_NO_CONTENT = 204,
20 
21     NXT_HTTP_MULTIPLE_CHOICES = 300,
22     NXT_HTTP_MOVED_PERMANENTLY = 301,
23     NXT_HTTP_FOUND = 302,
24     NXT_HTTP_SEE_OTHER = 303,
25     NXT_HTTP_NOT_MODIFIED = 304,
26     NXT_HTTP_TEMPORARY_REDIRECT = 307,
27     NXT_HTTP_PERMANENT_REDIRECT = 308,
28 
29     NXT_HTTP_BAD_REQUEST = 400,
30     NXT_HTTP_FORBIDDEN = 403,
31     NXT_HTTP_NOT_FOUND = 404,
32     NXT_HTTP_METHOD_NOT_ALLOWED = 405,
33     NXT_HTTP_REQUEST_TIMEOUT = 408,
34     NXT_HTTP_LENGTH_REQUIRED = 411,
35     NXT_HTTP_PAYLOAD_TOO_LARGE = 413,
36     NXT_HTTP_URI_TOO_LONG = 414,
37     NXT_HTTP_UPGRADE_REQUIRED = 426,
38     NXT_HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE = 431,
39 
40     NXT_HTTP_TO_HTTPS = 497,
41 
42     NXT_HTTP_INTERNAL_SERVER_ERROR = 500,
43     NXT_HTTP_NOT_IMPLEMENTED = 501,
44     NXT_HTTP_BAD_GATEWAY = 502,
45     NXT_HTTP_SERVICE_UNAVAILABLE = 503,
46     NXT_HTTP_GATEWAY_TIMEOUT = 504,
47     NXT_HTTP_VERSION_NOT_SUPPORTED = 505,
48     NXT_HTTP_SERVER_ERROR_MAX = 599,
49 
50     NXT_HTTP_STATUS_MAX = 999,
51 } nxt_http_status_t;
52 
53 
54 typedef enum {
55     NXT_HTTP_TE_NONE = 0,
56     NXT_HTTP_TE_CHUNKED = 1,
57     NXT_HTTP_TE_UNSUPPORTED = 2,
58 } nxt_http_te_t;
59 
60 
61 typedef enum {
62     NXT_HTTP_PROTO_H1 = 0,
63     NXT_HTTP_PROTO_H2,
64     NXT_HTTP_PROTO_DEVNULL,
65 } nxt_http_protocol_t;
66 
67 
68 typedef struct {
69     nxt_work_handler_t              ready_handler;
70     nxt_work_handler_t              error_handler;
71 } nxt_http_request_state_t;
72 
73 
74 typedef struct nxt_h1proto_s        nxt_h1proto_t;
75 
76 struct nxt_h1p_websocket_timer_s {
77     nxt_timer_t                     timer;
78     nxt_h1proto_t                   *h1p;
79     nxt_msec_t                      keepalive_interval;
80 };
81 
82 
83 typedef union {
84     void                            *any;
85     nxt_h1proto_t                   *h1;
86 } nxt_http_proto_t;
87 
88 
89 #define nxt_http_field_name_set(_field, _name)                                \
90     do {                                                                      \
91          (_field)->name_length = nxt_length(_name);                           \
92          (_field)->name = (u_char *) _name;                                   \
93     } while (0)
94 
95 
96 #define nxt_http_field_set(_field, _name, _value)                             \
97     do {                                                                      \
98          (_field)->name_length = nxt_length(_name);                           \
99          (_field)->value_length = nxt_length(_value);                         \
100          (_field)->name = (u_char *) _name;                                   \
101          (_field)->value = (u_char *) _value;                                 \
102     } while (0)
103 
104 
105 typedef struct {
106     nxt_list_t                      *fields;
107     nxt_http_field_t                *date;
108     nxt_http_field_t                *content_type;
109     nxt_http_field_t                *content_length;
110     nxt_off_t                       content_length_n;
111 } nxt_http_response_t;
112 
113 
114 typedef struct nxt_upstream_server_s  nxt_upstream_server_t;
115 
116 typedef struct {
117     nxt_http_proto_t                proto;
118     nxt_http_request_t              *request;
119     nxt_upstream_server_t           *server;
120     nxt_list_t                      *fields;
121     nxt_buf_t                       *body;
122 
123     nxt_http_status_t               status:16;
124     nxt_http_protocol_t             protocol:8;       /* 2 bits */
125     uint8_t                         header_received;  /* 1 bit  */
126     uint8_t                         closed;           /* 1 bit  */
127 } nxt_http_peer_t;
128 
129 
130 struct nxt_http_request_s {
131     nxt_http_proto_t                proto;
132     nxt_socket_conf_joint_t         *conf;
133 
134     nxt_mp_t                        *mem_pool;
135 
136     nxt_buf_t                       *body;
137     nxt_buf_t                       *ws_frame;
138     nxt_buf_t                       *out;
139     const nxt_http_request_state_t  *state;
140 
141     nxt_str_t                       host;
142     nxt_str_t                       server_name;
143     nxt_str_t                       target;
144     nxt_str_t                       version;
145     nxt_str_t                       *method;
146     nxt_str_t                       *path;
147     nxt_str_t                       *args;
148 
149     nxt_array_t                     *arguments;  /* of nxt_http_name_value_t */
150     nxt_array_t                     *cookies;    /* of nxt_http_name_value_t */
151     nxt_list_t                      *fields;
152     nxt_http_field_t                *content_type;
153     nxt_http_field_t                *content_length;
154     nxt_http_field_t                *cookie;
155     nxt_http_field_t                *referer;
156     nxt_http_field_t                *user_agent;
157     nxt_off_t                       content_length_n;
158 
159     nxt_sockaddr_t                  *remote;
160     nxt_sockaddr_t                  *local;
161     void                            *tls;
162     nxt_task_t                      task;
163 
164     nxt_timer_t                     timer;
165     void                            *timer_data;
166 
167     void                            *req_rpc_data;
168 
169     nxt_http_peer_t                 *peer;
170     nxt_buf_t                       *last;
171 
172     nxt_queue_link_t                app_link;   /* nxt_app_t.ack_waiting_req */
173     nxt_event_engine_t              *engine;
174     nxt_work_t                      err_work;
175 
176     nxt_http_response_t             resp;
177 
178     nxt_http_status_t               status:16;
179 
180     uint8_t                         pass_count;   /* 8 bits */
181     uint8_t                         app_target;
182     nxt_http_protocol_t             protocol:8;   /* 2 bits */
183     uint8_t                         logged;       /* 1 bit  */
184     uint8_t                         header_sent;  /* 1 bit  */
185     uint8_t                         inconsistent; /* 1 bit  */
186     uint8_t                         error;        /* 1 bit  */
187     uint8_t                         websocket_handshake;  /* 1 bit */
188 };
189 
190 
191 typedef struct nxt_http_route_s     nxt_http_route_t;
192 
193 
194 struct nxt_http_action_s {
195     nxt_http_action_t               *(*handler)(nxt_task_t *task,
196                                         nxt_http_request_t *r,
197                                         nxt_http_action_t *action);
198     union {
199         nxt_http_route_t            *route;
200         nxt_app_t                   *application;
201         nxt_http_action_t           *fallback;
202         nxt_upstream_t              *upstream;
203         uint32_t                    upstream_number;
204         nxt_http_status_t           return_code;
205     } u;
206 
207     nxt_str_t                       name;
208     nxt_int_t                       target;
209 };
210 
211 
212 typedef struct {
213     void (*body_read)(nxt_task_t *task, nxt_http_request_t *r);
214     void (*local_addr)(nxt_task_t *task, nxt_http_request_t *r);
215     void (*header_send)(nxt_task_t *task, nxt_http_request_t *r,
216          nxt_work_handler_t body_handler, void *data);
217     void (*send)(nxt_task_t *task, nxt_http_request_t *r, nxt_buf_t *out);
218     nxt_off_t (*body_bytes_sent)(nxt_task_t *task, nxt_http_proto_t proto);
219     void (*discard)(nxt_task_t *task, nxt_http_request_t *r, nxt_buf_t *last);
220     void (*close)(nxt_task_t *task, nxt_http_proto_t proto,
221         nxt_socket_conf_joint_t *joint);
222 
223     void (*peer_connect)(nxt_task_t *task, nxt_http_peer_t *peer);
224     void (*peer_header_send)(nxt_task_t *task, nxt_http_peer_t *peer);
225     void (*peer_header_read)(nxt_task_t *task, nxt_http_peer_t *peer);
226     void (*peer_read)(nxt_task_t *task, nxt_http_peer_t *peer);
227     void (*peer_close)(nxt_task_t *task, nxt_http_peer_t *peer);
228 
229     void (*ws_frame_start)(nxt_task_t *task, nxt_http_request_t *r,
230         nxt_buf_t *ws_frame);
231 } nxt_http_proto_table_t;
232 
233 
234 #define NXT_HTTP_DATE_LEN  nxt_length("Wed, 31 Dec 1986 16:40:00 GMT")
235 
236 nxt_inline u_char *
237 nxt_http_date(u_char *buf, struct tm *tm)
238 {
239     static const char  *week[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri",
240                                    "Sat" };
241 
242     static const char  *month[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
243                                     "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
244 
245     return nxt_sprintf(buf, buf + NXT_HTTP_DATE_LEN,
246                        "%s, %02d %s %4d %02d:%02d:%02d GMT",
247                        week[tm->tm_wday], tm->tm_mday,
248                        month[tm->tm_mon], tm->tm_year + 1900,
249                        tm->tm_hour, tm->tm_min, tm->tm_sec);
250 }
251 
252 
253 nxt_int_t nxt_http_init(nxt_task_t *task);
254 nxt_int_t nxt_h1p_init(nxt_task_t *task);
255 nxt_int_t nxt_http_response_hash_init(nxt_task_t *task);
256 
257 void nxt_http_conn_init(nxt_task_t *task, void *obj, void *data);
258 nxt_http_request_t *nxt_http_request_create(nxt_task_t *task);
259 void nxt_http_request_error(nxt_task_t *task, nxt_http_request_t *r,
260     nxt_http_status_t status);
261 void nxt_http_request_read_body(nxt_task_t *task, nxt_http_request_t *r);
262 void nxt_http_request_header_send(nxt_task_t *task, nxt_http_request_t *r,
263     nxt_work_handler_t body_handler, void *data);
264 void nxt_http_request_ws_frame_start(nxt_task_t *task, nxt_http_request_t *r,
265     nxt_buf_t *ws_frame);
266 void nxt_http_request_send(nxt_task_t *task, nxt_http_request_t *r,
267     nxt_buf_t *out);
268 nxt_buf_t *nxt_http_buf_mem(nxt_task_t *task, nxt_http_request_t *r,
269     size_t size);
270 nxt_buf_t *nxt_http_buf_last(nxt_http_request_t *r);
271 void nxt_http_request_error_handler(nxt_task_t *task, void *obj, void *data);
272 void nxt_http_request_close_handler(nxt_task_t *task, void *obj, void *data);
273 
274 nxt_int_t nxt_http_request_host(void *ctx, nxt_http_field_t *field,
275     uintptr_t data);
276 nxt_int_t nxt_http_request_field(void *ctx, nxt_http_field_t *field,
277     uintptr_t offset);
278 nxt_int_t nxt_http_request_content_length(void *ctx, nxt_http_field_t *field,
279     uintptr_t data);
280 
281 nxt_http_routes_t *nxt_http_routes_create(nxt_task_t *task,
282     nxt_router_temp_conf_t *tmcf, nxt_conf_value_t *routes_conf);
283 nxt_http_action_t *nxt_http_action_create(nxt_task_t *task,
284     nxt_router_temp_conf_t *tmcf, nxt_str_t *name);
285 nxt_int_t nxt_http_routes_resolve(nxt_task_t *task,
286     nxt_router_temp_conf_t *tmcf);
287 nxt_int_t nxt_http_pass_segments(nxt_mp_t *mp, nxt_str_t *pass,
288     nxt_str_t *segments, nxt_uint_t n);
289 nxt_http_action_t *nxt_http_pass_application(nxt_task_t *task,
290     nxt_router_temp_conf_t *tmcf, nxt_str_t *name);
291 void nxt_http_routes_cleanup(nxt_task_t *task, nxt_http_routes_t *routes);
292 void nxt_http_action_cleanup(nxt_task_t *task, nxt_http_action_t *action);
293 
294 nxt_int_t nxt_upstreams_create(nxt_task_t *task, nxt_router_temp_conf_t *tmcf,
295     nxt_conf_value_t *conf);
296 nxt_int_t nxt_upstreams_joint_create(nxt_router_temp_conf_t *tmcf,
297     nxt_upstream_t ***upstream_joint);
298 
299 nxt_http_action_t *nxt_http_return_handler(nxt_task_t *task,
300     nxt_http_request_t *r, nxt_http_action_t *action);
301 
302 nxt_http_action_t *nxt_http_static_handler(nxt_task_t *task,
303     nxt_http_request_t *r, nxt_http_action_t *action);
304 nxt_int_t nxt_http_static_mtypes_init(nxt_mp_t *mp, nxt_lvlhsh_t *hash);
305 nxt_int_t nxt_http_static_mtypes_hash_add(nxt_mp_t *mp, nxt_lvlhsh_t *hash,
306     nxt_str_t *extension, nxt_str_t *type);
307 nxt_str_t *nxt_http_static_mtypes_hash_find(nxt_lvlhsh_t *hash,
308     nxt_str_t *extension);
309 
310 nxt_http_action_t *nxt_http_application_handler(nxt_task_t *task,
311     nxt_http_request_t *r, nxt_http_action_t *action);
312 void nxt_upstream_find(nxt_upstreams_t *upstreams, nxt_str_t *name,
313     nxt_http_action_t *action);
314 nxt_http_action_t *nxt_upstream_proxy_handler(nxt_task_t *task,
315     nxt_http_request_t *r, nxt_upstream_t *upstream);
316 
317 
318 nxt_int_t nxt_http_proxy_create(nxt_mp_t *mp, nxt_http_action_t *action);
319 nxt_int_t nxt_http_proxy_date(void *ctx, nxt_http_field_t *field,
320     uintptr_t data);
321 nxt_int_t nxt_http_proxy_content_length(void *ctx, nxt_http_field_t *field,
322     uintptr_t data);
323 nxt_int_t nxt_http_proxy_skip(void *ctx, nxt_http_field_t *field,
324     uintptr_t data);
325 nxt_buf_t *nxt_http_proxy_buf_mem_alloc(nxt_task_t *task, nxt_http_request_t *r,
326     size_t size);
327 void nxt_http_proxy_buf_mem_free(nxt_task_t *task, nxt_http_request_t *r,
328     nxt_buf_t *b);
329 
330 extern nxt_time_string_t  nxt_http_date_cache;
331 
332 extern nxt_lvlhsh_t                        nxt_response_fields_hash;
333 
334 extern const nxt_http_proto_table_t  nxt_http_proto[];
335 
336 void nxt_h1p_websocket_first_frame_start(nxt_task_t *task,
337     nxt_http_request_t *r, nxt_buf_t *ws_frame);
338 void nxt_h1p_websocket_frame_start(nxt_task_t *task, nxt_http_request_t *r,
339     nxt_buf_t *ws_frame);
340 void nxt_h1p_complete_buffers(nxt_task_t *task, nxt_h1proto_t *h1p,
341     nxt_bool_t all);
342 nxt_msec_t nxt_h1p_conn_request_timer_value(nxt_conn_t *c, uintptr_t data);
343 
344 extern const nxt_conn_state_t  nxt_h1p_idle_close_state;
345 
346 #endif  /* _NXT_HTTP_H_INCLUDED_ */
347