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