Igor Sysoev | 6de5c2c | 2002-08-06 16:39:45 +0000 | [diff] [blame] | 1 | |
| 2 | #include <ngx_config.h> |
Igor Sysoev | 0ad17c0 | 2002-08-26 15:18:19 +0000 | [diff] [blame] | 3 | #include <ngx_core.h> |
| 4 | #include <ngx_string.h> |
Igor Sysoev | a58e3ca | 2002-09-02 14:48:24 +0000 | [diff] [blame] | 5 | #include <ngx_files.h> |
Igor Sysoev | 6de5c2c | 2002-08-06 16:39:45 +0000 | [diff] [blame] | 6 | #include <ngx_log.h> |
| 7 | #include <ngx_alloc.h> |
Igor Sysoev | a0bb31f | 2002-12-02 16:09:40 +0000 | [diff] [blame] | 8 | #include <ngx_array.h> |
| 9 | #include <ngx_table.h> |
Igor Sysoev | 6de5c2c | 2002-08-06 16:39:45 +0000 | [diff] [blame] | 10 | #include <ngx_hunk.h> |
| 11 | #include <ngx_connection.h> |
Igor Sysoev | fcce8d5 | 2003-01-23 18:47:54 +0000 | [diff] [blame] | 12 | #include <ngx_event.h> |
| 13 | #include <ngx_event_timer.h> |
Igor Sysoev | 42feecb | 2002-12-15 06:25:09 +0000 | [diff] [blame] | 14 | #include <ngx_inet.h> |
Igor Sysoev | 6de5c2c | 2002-08-06 16:39:45 +0000 | [diff] [blame] | 15 | #include <ngx_http.h> |
Igor Sysoev | e0268b9 | 2002-09-11 15:18:33 +0000 | [diff] [blame] | 16 | #include <ngx_http_config.h> |
Igor Sysoev | 4e9393a | 2003-01-09 05:36:00 +0000 | [diff] [blame] | 17 | #include <ngx_http_core_module.h> |
Igor Sysoev | 7300977 | 2003-02-06 17:21:13 +0000 | [diff] [blame] | 18 | #include <ngx_http_output_filter.h> |
Igor Sysoev | 6de5c2c | 2002-08-06 16:39:45 +0000 | [diff] [blame] | 19 | |
Igor Sysoev | a58e3ca | 2002-09-02 14:48:24 +0000 | [diff] [blame] | 20 | |
Igor Sysoev | 6de5c2c | 2002-08-06 16:39:45 +0000 | [diff] [blame] | 21 | static int ngx_http_init_request(ngx_event_t *ev); |
Igor Sysoev | b086905 | 2002-12-10 18:05:12 +0000 | [diff] [blame] | 22 | static int ngx_http_process_request_header(ngx_event_t *ev); |
Igor Sysoev | 6de5c2c | 2002-08-06 16:39:45 +0000 | [diff] [blame] | 23 | |
Igor Sysoev | 016b852 | 2002-08-29 16:59:54 +0000 | [diff] [blame] | 24 | static int ngx_http_process_request_line(ngx_http_request_t *r); |
Igor Sysoev | b086905 | 2002-12-10 18:05:12 +0000 | [diff] [blame] | 25 | static int ngx_http_process_request_headers(ngx_http_request_t *r); |
Igor Sysoev | a58e3ca | 2002-09-02 14:48:24 +0000 | [diff] [blame] | 26 | static int ngx_http_process_request_header_line(ngx_http_request_t *r); |
Igor Sysoev | 6de5c2c | 2002-08-06 16:39:45 +0000 | [diff] [blame] | 27 | |
Igor Sysoev | 42feecb | 2002-12-15 06:25:09 +0000 | [diff] [blame] | 28 | static int ngx_http_event_request_handler(ngx_http_request_t *r); |
Igor Sysoev | a58e3ca | 2002-09-02 14:48:24 +0000 | [diff] [blame] | 29 | |
| 30 | static int ngx_http_writer(ngx_event_t *ev); |
Igor Sysoev | 42feecb | 2002-12-15 06:25:09 +0000 | [diff] [blame] | 31 | static int ngx_http_block_read(ngx_event_t *ev); |
| 32 | static int ngx_http_read_discarded_body(ngx_event_t *ev); |
Igor Sysoev | 1e7ec9d | 2003-02-11 07:14:40 +0000 | [diff] [blame] | 33 | static int ngx_http_set_keepalive(ngx_http_request_t *r); |
Igor Sysoev | 1af7c82 | 2002-09-13 14:47:42 +0000 | [diff] [blame] | 34 | static int ngx_http_keepalive_handler(ngx_event_t *ev); |
Igor Sysoev | 42feecb | 2002-12-15 06:25:09 +0000 | [diff] [blame] | 35 | static int ngx_http_set_lingering_close(ngx_http_request_t *r); |
| 36 | static int ngx_http_lingering_close_handler(ngx_event_t *ev); |
Igor Sysoev | 3a40d48 | 2002-09-12 14:42:29 +0000 | [diff] [blame] | 37 | |
Igor Sysoev | 2ba1ee0 | 2002-10-04 17:58:04 +0000 | [diff] [blame] | 38 | static int ngx_http_close_connection(ngx_event_t *ev); |
Igor Sysoev | 3d062ad | 2003-03-05 06:37:42 +0000 | [diff] [blame] | 39 | static int ngx_http_header_parse_error(ngx_http_request_t *r, |
| 40 | int parse_err, int err); |
Igor Sysoev | 0ad17c0 | 2002-08-26 15:18:19 +0000 | [diff] [blame] | 41 | static size_t ngx_http_log_error(void *data, char *buf, size_t len); |
| 42 | |
Igor Sysoev | 6de5c2c | 2002-08-06 16:39:45 +0000 | [diff] [blame] | 43 | |
Igor Sysoev | 0ad17c0 | 2002-08-26 15:18:19 +0000 | [diff] [blame] | 44 | |
Igor Sysoev | 016b852 | 2002-08-29 16:59:54 +0000 | [diff] [blame] | 45 | static char *header_errors[] = { |
| 46 | "client %s sent invalid method", |
| 47 | "client %s sent invalid request", |
Igor Sysoev | 1af7c82 | 2002-09-13 14:47:42 +0000 | [diff] [blame] | 48 | "client %s sent too long URI", |
Igor Sysoev | 6a644c6 | 2003-03-04 06:33:48 +0000 | [diff] [blame] | 49 | "client %s sent HEAD method in HTTP/0.9 request", |
| 50 | |
| 51 | "client %s sent invalid header, URL: %s", |
| 52 | "client %s sent too long header line, URL: %s", |
| 53 | "client %s sent HTTP/1.1 request without \"Host\" header, URL: %s" |
Igor Sysoev | 016b852 | 2002-08-29 16:59:54 +0000 | [diff] [blame] | 54 | }; |
| 55 | |
| 56 | |
Igor Sysoev | 6a644c6 | 2003-03-04 06:33:48 +0000 | [diff] [blame] | 57 | |
Igor Sysoev | a0bb31f | 2002-12-02 16:09:40 +0000 | [diff] [blame] | 58 | static ngx_http_header_t headers_in[] = { |
| 59 | { 4, "Host", offsetof(ngx_http_headers_in_t, host) }, |
| 60 | { 10, "Connection", offsetof(ngx_http_headers_in_t, connection) }, |
Igor Sysoev | 42feecb | 2002-12-15 06:25:09 +0000 | [diff] [blame] | 61 | { 17, "If-Modified-Since", |
| 62 | offsetof(ngx_http_headers_in_t,if_modified_since) }, |
Igor Sysoev | a0bb31f | 2002-12-02 16:09:40 +0000 | [diff] [blame] | 63 | |
| 64 | { 10, "User-Agent", offsetof(ngx_http_headers_in_t, user_agent) }, |
| 65 | |
| 66 | { 0, NULL, 0 } |
| 67 | }; |
| 68 | |
Igor Sysoev | 6de5c2c | 2002-08-06 16:39:45 +0000 | [diff] [blame] | 69 | |
| 70 | int ngx_http_init_connection(ngx_connection_t *c) |
| 71 | { |
Igor Sysoev | 0ad17c0 | 2002-08-26 15:18:19 +0000 | [diff] [blame] | 72 | ngx_event_t *ev; |
Igor Sysoev | 0ad17c0 | 2002-08-26 15:18:19 +0000 | [diff] [blame] | 73 | ngx_http_log_ctx_t *ctx; |
Igor Sysoev | 6de5c2c | 2002-08-06 16:39:45 +0000 | [diff] [blame] | 74 | |
| 75 | ev = c->read; |
Igor Sysoev | 6de5c2c | 2002-08-06 16:39:45 +0000 | [diff] [blame] | 76 | ev->event_handler = ngx_http_init_request; |
Igor Sysoev | 2ba1ee0 | 2002-10-04 17:58:04 +0000 | [diff] [blame] | 77 | |
Igor Sysoev | 2ba1ee0 | 2002-10-04 17:58:04 +0000 | [diff] [blame] | 78 | ev->close_handler = ngx_http_close_connection; |
| 79 | c->write->close_handler = ngx_http_close_connection; |
| 80 | |
Igor Sysoev | 4e9393a | 2003-01-09 05:36:00 +0000 | [diff] [blame] | 81 | ngx_test_null(c->addr_text.data, ngx_palloc(c->pool, c->addr_text_max_len), |
Igor Sysoev | 0ad17c0 | 2002-08-26 15:18:19 +0000 | [diff] [blame] | 82 | NGX_ERROR); |
Igor Sysoev | b086905 | 2002-12-10 18:05:12 +0000 | [diff] [blame] | 83 | |
Igor Sysoev | 86de4cb | 2003-01-30 07:28:09 +0000 | [diff] [blame] | 84 | c->addr_text.len = ngx_sock_ntop(c->family, c->sockaddr, |
Igor Sysoev | 4e9393a | 2003-01-09 05:36:00 +0000 | [diff] [blame] | 85 | c->addr_text.data, c->addr_text_max_len); |
Igor Sysoev | 86de4cb | 2003-01-30 07:28:09 +0000 | [diff] [blame] | 86 | |
| 87 | if (c->addr_text.len == 0) { |
| 88 | return NGX_ERROR; |
| 89 | } |
Igor Sysoev | 0ad17c0 | 2002-08-26 15:18:19 +0000 | [diff] [blame] | 90 | |
| 91 | ngx_test_null(ctx, ngx_pcalloc(c->pool, sizeof(ngx_http_log_ctx_t)), |
| 92 | NGX_ERROR); |
Igor Sysoev | b086905 | 2002-12-10 18:05:12 +0000 | [diff] [blame] | 93 | ctx->client = c->addr_text.data; |
Igor Sysoev | 0ad17c0 | 2002-08-26 15:18:19 +0000 | [diff] [blame] | 94 | ctx->action = "reading client request line"; |
| 95 | c->log->data = ctx; |
| 96 | c->log->handler = ngx_http_log_error; |
| 97 | |
Igor Sysoev | 6de5c2c | 2002-08-06 16:39:45 +0000 | [diff] [blame] | 98 | #if (HAVE_DEFERRED_ACCEPT) |
Igor Sysoev | 7300977 | 2003-02-06 17:21:13 +0000 | [diff] [blame] | 99 | |
Igor Sysoev | 016b852 | 2002-08-29 16:59:54 +0000 | [diff] [blame] | 100 | if (ev->ready) { |
Igor Sysoev | 6de5c2c | 2002-08-06 16:39:45 +0000 | [diff] [blame] | 101 | return ngx_http_init_request(ev); |
Igor Sysoev | 016b852 | 2002-08-29 16:59:54 +0000 | [diff] [blame] | 102 | } |
Igor Sysoev | 7300977 | 2003-02-06 17:21:13 +0000 | [diff] [blame] | 103 | |
Igor Sysoev | 6de5c2c | 2002-08-06 16:39:45 +0000 | [diff] [blame] | 104 | #endif |
Igor Sysoev | 9b25d69 | 2003-01-26 21:08:14 +0000 | [diff] [blame] | 105 | |
| 106 | ngx_add_timer(ev, c->post_accept_timeout); |
| 107 | ev->timer_set = 1; |
| 108 | |
| 109 | #if (USE_KQUEUE) |
| 110 | |
| 111 | return ngx_add_event(ev, NGX_READ_EVENT, NGX_CLEAR_EVENT); |
| 112 | |
| 113 | #else |
| 114 | |
Igor Sysoev | 7300977 | 2003-02-06 17:21:13 +0000 | [diff] [blame] | 115 | #if (HAVE_CLEAR_EVENT) /* kqueue */ |
| 116 | |
Igor Sysoev | 9b25d69 | 2003-01-26 21:08:14 +0000 | [diff] [blame] | 117 | if (ngx_event_flags & NGX_HAVE_CLEAR_EVENT) { |
| 118 | return ngx_add_event(ev, NGX_READ_EVENT, NGX_CLEAR_EVENT); |
| 119 | } |
Igor Sysoev | 7300977 | 2003-02-06 17:21:13 +0000 | [diff] [blame] | 120 | |
Igor Sysoev | 9b25d69 | 2003-01-26 21:08:14 +0000 | [diff] [blame] | 121 | #endif |
| 122 | |
Igor Sysoev | 6a644c6 | 2003-03-04 06:33:48 +0000 | [diff] [blame] | 123 | #if (HAVE_EDGE_EVENT) /* epoll */ || (HAVE_AIO_EVENT) /* aio, iocp */ |
Igor Sysoev | 7300977 | 2003-02-06 17:21:13 +0000 | [diff] [blame] | 124 | |
Igor Sysoev | 6a644c6 | 2003-03-04 06:33:48 +0000 | [diff] [blame] | 125 | if (ngx_event_flags & (NGX_HAVE_EDGE_EVENT|NGX_HAVE_AIO_EVENT)) { |
Igor Sysoev | 9b25d69 | 2003-01-26 21:08:14 +0000 | [diff] [blame] | 126 | return ngx_http_init_request(ev); |
| 127 | } |
Igor Sysoev | 7300977 | 2003-02-06 17:21:13 +0000 | [diff] [blame] | 128 | |
Igor Sysoev | 1e7ec9d | 2003-02-11 07:14:40 +0000 | [diff] [blame] | 129 | #endif |
Igor Sysoev | 7300977 | 2003-02-06 17:21:13 +0000 | [diff] [blame] | 130 | |
| 131 | /* select, poll, /dev/poll */ |
Igor Sysoev | 9b25d69 | 2003-01-26 21:08:14 +0000 | [diff] [blame] | 132 | |
| 133 | return ngx_add_event(ev, NGX_READ_EVENT, NGX_LEVEL_EVENT); |
| 134 | |
| 135 | #endif /* USE_KQUEUE */ |
Igor Sysoev | 6de5c2c | 2002-08-06 16:39:45 +0000 | [diff] [blame] | 136 | } |
| 137 | |
Igor Sysoev | 0ad17c0 | 2002-08-26 15:18:19 +0000 | [diff] [blame] | 138 | |
Igor Sysoev | 1af7c82 | 2002-09-13 14:47:42 +0000 | [diff] [blame] | 139 | static int ngx_http_init_request(ngx_event_t *ev) |
Igor Sysoev | 6de5c2c | 2002-08-06 16:39:45 +0000 | [diff] [blame] | 140 | { |
Igor Sysoev | 86de4cb | 2003-01-30 07:28:09 +0000 | [diff] [blame] | 141 | ngx_connection_t *c; |
| 142 | ngx_http_request_t *r; |
| 143 | ngx_http_conf_ctx_t *ctx; |
Igor Sysoev | 6de5c2c | 2002-08-06 16:39:45 +0000 | [diff] [blame] | 144 | |
Igor Sysoev | 0ad17c0 | 2002-08-26 15:18:19 +0000 | [diff] [blame] | 145 | c = (ngx_connection_t *) ev->data; |
Igor Sysoev | ad22e01 | 2003-01-15 07:02:27 +0000 | [diff] [blame] | 146 | c->sent = 0; |
Igor Sysoev | 6de5c2c | 2002-08-06 16:39:45 +0000 | [diff] [blame] | 147 | |
Igor Sysoev | 0ad17c0 | 2002-08-26 15:18:19 +0000 | [diff] [blame] | 148 | ngx_test_null(r, ngx_pcalloc(c->pool, sizeof(ngx_http_request_t)), |
| 149 | NGX_ERROR); |
Igor Sysoev | 6de5c2c | 2002-08-06 16:39:45 +0000 | [diff] [blame] | 150 | |
| 151 | c->data = r; |
| 152 | r->connection = c; |
Igor Sysoev | 42feecb | 2002-12-15 06:25:09 +0000 | [diff] [blame] | 153 | r->file.fd = NGX_INVALID_FILE; |
Igor Sysoev | 6de5c2c | 2002-08-06 16:39:45 +0000 | [diff] [blame] | 154 | |
Igor Sysoev | 682bf8e | 2002-09-16 15:01:44 +0000 | [diff] [blame] | 155 | if (c->buffer == NULL) { |
| 156 | ngx_test_null(c->buffer, |
Igor Sysoev | 4e9393a | 2003-01-09 05:36:00 +0000 | [diff] [blame] | 157 | ngx_create_temp_hunk(c->pool, |
| 158 | ngx_http_client_header_buffer_size, |
Igor Sysoev | 682bf8e | 2002-09-16 15:01:44 +0000 | [diff] [blame] | 159 | 0, 0), |
| 160 | NGX_ERROR); |
| 161 | } else { |
| 162 | r->header_read = 1; |
| 163 | } |
| 164 | |
Igor Sysoev | 3d062ad | 2003-03-05 06:37:42 +0000 | [diff] [blame] | 165 | r->pipeline = c->pipeline; |
Igor Sysoev | 682bf8e | 2002-09-16 15:01:44 +0000 | [diff] [blame] | 166 | r->header_in = c->buffer; |
| 167 | |
Igor Sysoev | 4e9393a | 2003-01-09 05:36:00 +0000 | [diff] [blame] | 168 | ngx_test_null(r->pool, ngx_create_pool(ngx_http_request_pool_size, ev->log), |
Igor Sysoev | 016b852 | 2002-08-29 16:59:54 +0000 | [diff] [blame] | 169 | ngx_http_close_request(r)); |
Igor Sysoev | 0ad17c0 | 2002-08-26 15:18:19 +0000 | [diff] [blame] | 170 | |
Igor Sysoev | 207ed5a | 2002-12-26 16:26:23 +0000 | [diff] [blame] | 171 | ngx_test_null(r->ctx, |
| 172 | ngx_pcalloc(r->pool, sizeof(void *) * ngx_http_max_module), |
Igor Sysoev | e0268b9 | 2002-09-11 15:18:33 +0000 | [diff] [blame] | 173 | ngx_http_close_request(r)); |
| 174 | |
Igor Sysoev | 86de4cb | 2003-01-30 07:28:09 +0000 | [diff] [blame] | 175 | ctx = (ngx_http_conf_ctx_t *) c->ctx; |
| 176 | r->srv_conf = ctx->srv_conf; |
| 177 | r->loc_conf = ctx->loc_conf; |
| 178 | |
Igor Sysoev | 42feecb | 2002-12-15 06:25:09 +0000 | [diff] [blame] | 179 | r->headers_out.headers = ngx_create_table(r->pool, 10); |
| 180 | r->headers_out.content_length = -1; |
| 181 | r->headers_out.last_modified_time = -1; |
| 182 | |
Igor Sysoev | b086905 | 2002-12-10 18:05:12 +0000 | [diff] [blame] | 183 | ev->event_handler = ngx_http_process_request_header; |
Igor Sysoev | 016b852 | 2002-08-29 16:59:54 +0000 | [diff] [blame] | 184 | r->state_handler = ngx_http_process_request_line; |
Igor Sysoev | 0ad17c0 | 2002-08-26 15:18:19 +0000 | [diff] [blame] | 185 | |
Igor Sysoev | b086905 | 2002-12-10 18:05:12 +0000 | [diff] [blame] | 186 | return ngx_http_process_request_header(ev); |
Igor Sysoev | 6de5c2c | 2002-08-06 16:39:45 +0000 | [diff] [blame] | 187 | } |
| 188 | |
Igor Sysoev | 0ad17c0 | 2002-08-26 15:18:19 +0000 | [diff] [blame] | 189 | |
Igor Sysoev | b086905 | 2002-12-10 18:05:12 +0000 | [diff] [blame] | 190 | static int ngx_http_process_request_header(ngx_event_t *ev) |
Igor Sysoev | 6de5c2c | 2002-08-06 16:39:45 +0000 | [diff] [blame] | 191 | { |
Igor Sysoev | b738757 | 2003-03-11 20:38:13 +0000 | [diff] [blame^] | 192 | int n, rc, again; |
Igor Sysoev | 9b25d69 | 2003-01-26 21:08:14 +0000 | [diff] [blame] | 193 | ngx_connection_t *c; |
| 194 | ngx_http_request_t *r; |
Igor Sysoev | 6a644c6 | 2003-03-04 06:33:48 +0000 | [diff] [blame] | 195 | ngx_http_log_ctx_t *ctx; |
Igor Sysoev | 0ad17c0 | 2002-08-26 15:18:19 +0000 | [diff] [blame] | 196 | |
| 197 | c = (ngx_connection_t *) ev->data; |
| 198 | r = (ngx_http_request_t *) c->data; |
Igor Sysoev | 6de5c2c | 2002-08-06 16:39:45 +0000 | [diff] [blame] | 199 | |
| 200 | ngx_log_debug(ev->log, "http process request"); |
| 201 | |
Igor Sysoev | 016b852 | 2002-08-29 16:59:54 +0000 | [diff] [blame] | 202 | do { |
Igor Sysoev | 016b852 | 2002-08-29 16:59:54 +0000 | [diff] [blame] | 203 | |
Igor Sysoev | 7300977 | 2003-02-06 17:21:13 +0000 | [diff] [blame] | 204 | if (r->header_read) { |
Igor Sysoev | b738757 | 2003-03-11 20:38:13 +0000 | [diff] [blame^] | 205 | if (r->header_in->end - r->header_in->last == 0) { |
| 206 | again = 1; |
| 207 | } else { |
| 208 | again = 0; |
| 209 | } |
| 210 | |
Igor Sysoev | 7300977 | 2003-02-06 17:21:13 +0000 | [diff] [blame] | 211 | r->header_read = 0; |
| 212 | ngx_log_debug(ev->log, "http preread %d" _ |
Igor Sysoev | b738757 | 2003-03-11 20:38:13 +0000 | [diff] [blame^] | 213 | r->header_in->last - r->header_in->pos); |
Igor Sysoev | 016b852 | 2002-08-29 16:59:54 +0000 | [diff] [blame] | 214 | |
Igor Sysoev | 7300977 | 2003-02-06 17:21:13 +0000 | [diff] [blame] | 215 | } else { |
Igor Sysoev | b738757 | 2003-03-11 20:38:13 +0000 | [diff] [blame^] | 216 | n = ngx_event_recv(c, r->header_in->last, |
| 217 | r->header_in->end - r->header_in->last); |
Igor Sysoev | 7300977 | 2003-02-06 17:21:13 +0000 | [diff] [blame] | 218 | |
| 219 | if (n == NGX_AGAIN) { |
| 220 | if (!r->header_timeout_set) { |
| 221 | |
| 222 | if (ev->timer_set) { |
| 223 | ngx_del_timer(ev); |
| 224 | } else { |
| 225 | ev->timer_set = 1; |
| 226 | } |
| 227 | |
| 228 | ngx_add_timer(ev, ngx_http_client_header_timeout); |
| 229 | r->header_timeout_set = 1; |
| 230 | } |
| 231 | return NGX_AGAIN; |
| 232 | } |
| 233 | |
Igor Sysoev | b738757 | 2003-03-11 20:38:13 +0000 | [diff] [blame^] | 234 | if (n == NGX_ERROR) { |
Igor Sysoev | 7300977 | 2003-02-06 17:21:13 +0000 | [diff] [blame] | 235 | return ngx_http_close_request(r); |
Igor Sysoev | b738757 | 2003-03-11 20:38:13 +0000 | [diff] [blame^] | 236 | } |
Igor Sysoev | 7300977 | 2003-02-06 17:21:13 +0000 | [diff] [blame] | 237 | |
| 238 | ngx_log_debug(ev->log, "http read %d" _ n); |
| 239 | |
| 240 | if (n == 0) { |
| 241 | ngx_log_error(NGX_LOG_INFO, c->log, 0, |
| 242 | "client has prematurely closed connection"); |
| 243 | return ngx_http_close_request(r); |
| 244 | } |
| 245 | |
Igor Sysoev | b738757 | 2003-03-11 20:38:13 +0000 | [diff] [blame^] | 246 | r->header_in->last += n; |
| 247 | |
| 248 | if (ngx_http_large_client_header |
| 249 | && r->header_in->end == r->header_in->last) { |
| 250 | again = 1; |
| 251 | } else { |
| 252 | again = 0; |
| 253 | } |
Igor Sysoev | 7300977 | 2003-02-06 17:21:13 +0000 | [diff] [blame] | 254 | } |
| 255 | |
Igor Sysoev | 0dad629 | 2003-03-05 17:30:51 +0000 | [diff] [blame] | 256 | /* the state_handlers are called in the following order: |
Igor Sysoev | 7300977 | 2003-02-06 17:21:13 +0000 | [diff] [blame] | 257 | ngx_http_process_request_line(r) |
| 258 | ngx_http_process_request_headers(r) */ |
| 259 | |
| 260 | do { |
Igor Sysoev | 0dad629 | 2003-03-05 17:30:51 +0000 | [diff] [blame] | 261 | /* state_handlers return NGX_OK when the whole header done */ |
Igor Sysoev | 7300977 | 2003-02-06 17:21:13 +0000 | [diff] [blame] | 262 | rc = (r->state_handler)(r); |
| 263 | |
Igor Sysoev | b738757 | 2003-03-11 20:38:13 +0000 | [diff] [blame^] | 264 | if (rc == NGX_ERROR) { |
Igor Sysoev | 7300977 | 2003-02-06 17:21:13 +0000 | [diff] [blame] | 265 | return rc; |
Igor Sysoev | b738757 | 2003-03-11 20:38:13 +0000 | [diff] [blame^] | 266 | } |
Igor Sysoev | 7300977 | 2003-02-06 17:21:13 +0000 | [diff] [blame] | 267 | |
Igor Sysoev | b738757 | 2003-03-11 20:38:13 +0000 | [diff] [blame^] | 268 | } while (rc == NGX_AGAIN && r->header_in->pos < r->header_in->last); |
Igor Sysoev | 7300977 | 2003-02-06 17:21:13 +0000 | [diff] [blame] | 269 | |
| 270 | #if (HAVE_AIO_EVENT) /* aio, iocp */ |
Igor Sysoev | b738757 | 2003-03-11 20:38:13 +0000 | [diff] [blame^] | 271 | |
| 272 | if (ngx_event_flags & NGX_HAVE_AIO_EVENT) { |
| 273 | again = 1; |
| 274 | } |
| 275 | |
Igor Sysoev | 7300977 | 2003-02-06 17:21:13 +0000 | [diff] [blame] | 276 | #endif |
Igor Sysoev | a58e3ca | 2002-09-02 14:48:24 +0000 | [diff] [blame] | 277 | |
Igor Sysoev | b738757 | 2003-03-11 20:38:13 +0000 | [diff] [blame^] | 278 | } while (rc == NGX_AGAIN && again); |
| 279 | |
Igor Sysoev | 830c4ce | 2003-01-24 16:09:40 +0000 | [diff] [blame] | 280 | if (rc == NGX_OK) { |
| 281 | /* HTTP header done */ |
Igor Sysoev | 016b852 | 2002-08-29 16:59:54 +0000 | [diff] [blame] | 282 | |
Igor Sysoev | 9b25d69 | 2003-01-26 21:08:14 +0000 | [diff] [blame] | 283 | if (ev->timer_set) { |
Igor Sysoev | 830c4ce | 2003-01-24 16:09:40 +0000 | [diff] [blame] | 284 | ngx_del_timer(ev); |
Igor Sysoev | 9b25d69 | 2003-01-26 21:08:14 +0000 | [diff] [blame] | 285 | ev->timer_set = 0; |
Igor Sysoev | 830c4ce | 2003-01-24 16:09:40 +0000 | [diff] [blame] | 286 | } |
| 287 | |
Igor Sysoev | 42feecb | 2002-12-15 06:25:09 +0000 | [diff] [blame] | 288 | return ngx_http_event_request_handler(r); |
Igor Sysoev | 830c4ce | 2003-01-24 16:09:40 +0000 | [diff] [blame] | 289 | |
Igor Sysoev | 9b25d69 | 2003-01-26 21:08:14 +0000 | [diff] [blame] | 290 | } else { /* NGX_AGAIN */ |
Igor Sysoev | 830c4ce | 2003-01-24 16:09:40 +0000 | [diff] [blame] | 291 | |
Igor Sysoev | 9b25d69 | 2003-01-26 21:08:14 +0000 | [diff] [blame] | 292 | if (!r->header_timeout_set) { |
| 293 | |
| 294 | if (ev->timer_set) { |
| 295 | ngx_del_timer(ev); |
| 296 | } else { |
| 297 | ev->timer_set = 1; |
| 298 | } |
| 299 | |
Igor Sysoev | 830c4ce | 2003-01-24 16:09:40 +0000 | [diff] [blame] | 300 | ngx_add_timer(ev, ngx_http_client_header_timeout); |
Igor Sysoev | 9b25d69 | 2003-01-26 21:08:14 +0000 | [diff] [blame] | 301 | r->header_timeout_set = 1; |
Igor Sysoev | 830c4ce | 2003-01-24 16:09:40 +0000 | [diff] [blame] | 302 | } |
| 303 | |
Igor Sysoev | b086905 | 2002-12-10 18:05:12 +0000 | [diff] [blame] | 304 | return rc; |
Igor Sysoev | 830c4ce | 2003-01-24 16:09:40 +0000 | [diff] [blame] | 305 | } |
Igor Sysoev | 016b852 | 2002-08-29 16:59:54 +0000 | [diff] [blame] | 306 | } |
| 307 | |
Igor Sysoev | 1af7c82 | 2002-09-13 14:47:42 +0000 | [diff] [blame] | 308 | |
Igor Sysoev | 016b852 | 2002-08-29 16:59:54 +0000 | [diff] [blame] | 309 | static int ngx_http_process_request_line(ngx_http_request_t *r) |
| 310 | { |
Igor Sysoev | 3d062ad | 2003-03-05 06:37:42 +0000 | [diff] [blame] | 311 | int rc, offset; |
Igor Sysoev | 2ba1ee0 | 2002-10-04 17:58:04 +0000 | [diff] [blame] | 312 | ngx_connection_t *c; |
Igor Sysoev | 016b852 | 2002-08-29 16:59:54 +0000 | [diff] [blame] | 313 | ngx_http_log_ctx_t *ctx; |
| 314 | |
| 315 | rc = ngx_read_http_request_line(r); |
| 316 | |
Igor Sysoev | 2ba1ee0 | 2002-10-04 17:58:04 +0000 | [diff] [blame] | 317 | c = r->connection; |
| 318 | |
Igor Sysoev | 0dad629 | 2003-03-05 17:30:51 +0000 | [diff] [blame] | 319 | /* a request line has been parsed successfully */ |
Igor Sysoev | 016b852 | 2002-08-29 16:59:54 +0000 | [diff] [blame] | 320 | if (rc == NGX_OK) { |
Igor Sysoev | 6a644c6 | 2003-03-04 06:33:48 +0000 | [diff] [blame] | 321 | /* copy URI */ |
Igor Sysoev | 42feecb | 2002-12-15 06:25:09 +0000 | [diff] [blame] | 322 | r->uri.len = (r->args_start ? r->args_start - 1 : r->uri_end) |
| 323 | - r->uri_start; |
Igor Sysoev | b086905 | 2002-12-10 18:05:12 +0000 | [diff] [blame] | 324 | ngx_test_null(r->uri.data, ngx_palloc(r->pool, r->uri.len + 1), |
Igor Sysoev | 016b852 | 2002-08-29 16:59:54 +0000 | [diff] [blame] | 325 | ngx_http_close_request(r)); |
Igor Sysoev | b086905 | 2002-12-10 18:05:12 +0000 | [diff] [blame] | 326 | ngx_cpystrn(r->uri.data, r->uri_start, r->uri.len + 1); |
Igor Sysoev | 016b852 | 2002-08-29 16:59:54 +0000 | [diff] [blame] | 327 | |
Igor Sysoev | b738757 | 2003-03-11 20:38:13 +0000 | [diff] [blame^] | 328 | /* if the large client headers are enabled then |
Igor Sysoev | 0dad629 | 2003-03-05 17:30:51 +0000 | [diff] [blame] | 329 | we need to copy a request line */ |
Igor Sysoev | 2d0d909 | 2002-12-03 15:45:38 +0000 | [diff] [blame] | 330 | |
Igor Sysoev | 3d062ad | 2003-03-05 06:37:42 +0000 | [diff] [blame] | 331 | r->request_line.len = r->request_end - r->request_start; |
Igor Sysoev | 6a644c6 | 2003-03-04 06:33:48 +0000 | [diff] [blame] | 332 | if (ngx_http_large_client_header) { |
| 333 | ngx_test_null(r->request_line.data, |
| 334 | ngx_palloc(r->pool, r->request_line.len + 1), |
| 335 | ngx_http_close_request(r)); |
Igor Sysoev | 3d062ad | 2003-03-05 06:37:42 +0000 | [diff] [blame] | 336 | ngx_cpystrn(r->request_line.data, r->request_start, |
Igor Sysoev | 6a644c6 | 2003-03-04 06:33:48 +0000 | [diff] [blame] | 337 | r->request_line.len + 1); |
| 338 | |
| 339 | } else { |
Igor Sysoev | 3d062ad | 2003-03-05 06:37:42 +0000 | [diff] [blame] | 340 | r->request_line.data = r->request_start; |
Igor Sysoev | 6a644c6 | 2003-03-04 06:33:48 +0000 | [diff] [blame] | 341 | r->request_line.data[r->request_line.len] = '\0'; |
| 342 | } |
| 343 | |
| 344 | /* copy URI extention if it exists */ |
Igor Sysoev | 682bf8e | 2002-09-16 15:01:44 +0000 | [diff] [blame] | 345 | if (r->uri_ext) { |
Igor Sysoev | 42feecb | 2002-12-15 06:25:09 +0000 | [diff] [blame] | 346 | r->exten.len = (r->args_start ? r->args_start - 1 : r->uri_end) |
| 347 | - r->uri_ext; |
Igor Sysoev | b086905 | 2002-12-10 18:05:12 +0000 | [diff] [blame] | 348 | ngx_test_null(r->exten.data, |
| 349 | ngx_palloc(r->pool, r->exten.len + 1), |
Igor Sysoev | 682bf8e | 2002-09-16 15:01:44 +0000 | [diff] [blame] | 350 | ngx_http_close_request(r)); |
Igor Sysoev | b086905 | 2002-12-10 18:05:12 +0000 | [diff] [blame] | 351 | ngx_cpystrn(r->exten.data, r->uri_ext, r->exten.len + 1); |
Igor Sysoev | 682bf8e | 2002-09-16 15:01:44 +0000 | [diff] [blame] | 352 | } |
| 353 | |
Igor Sysoev | 3d062ad | 2003-03-05 06:37:42 +0000 | [diff] [blame] | 354 | #if 1 |
| 355 | if (r->exten.data == NULL) { |
| 356 | r->exten.data = ""; |
| 357 | } |
| 358 | ngx_log_debug(r->connection->log, "HTTP: %d, %d, '%s', '%s'" _ |
Igor Sysoev | b086905 | 2002-12-10 18:05:12 +0000 | [diff] [blame] | 359 | r->method _ r->http_version _ |
| 360 | r->uri.data _ r->exten.data); |
Igor Sysoev | 3d062ad | 2003-03-05 06:37:42 +0000 | [diff] [blame] | 361 | if (r->exten.data[0] == '\0') { |
| 362 | r->exten.data = NULL; |
| 363 | } |
Igor Sysoev | 295bb63 | 2002-12-23 18:22:18 +0000 | [diff] [blame] | 364 | #endif |
Igor Sysoev | 016b852 | 2002-08-29 16:59:54 +0000 | [diff] [blame] | 365 | |
Igor Sysoev | 6a644c6 | 2003-03-04 06:33:48 +0000 | [diff] [blame] | 366 | ctx = r->connection->log->data; |
| 367 | if (ngx_http_url_in_error_log) { |
| 368 | ngx_test_null(ctx->url, |
| 369 | ngx_palloc(r->pool, r->uri_end - r->uri_start + 1), |
| 370 | ngx_http_close_request(r)); |
| 371 | ngx_cpystrn(ctx->url, r->uri_start, r->uri_end - r->uri_start + 1); |
| 372 | } |
Igor Sysoev | 6de5c2c | 2002-08-06 16:39:45 +0000 | [diff] [blame] | 373 | |
Igor Sysoev | 0dad629 | 2003-03-05 17:30:51 +0000 | [diff] [blame] | 374 | /* if we need to parse the headers then return NGX_AGAIN |
| 375 | becuase of HTTP/0.9 has no headers so return NGX_OK */ |
| 376 | |
| 377 | if (r->http_version == NGX_HTTP_VERSION_9) { |
| 378 | r->state_handler = NULL; |
Igor Sysoev | 6a644c6 | 2003-03-04 06:33:48 +0000 | [diff] [blame] | 379 | return NGX_OK; |
Igor Sysoev | 0dad629 | 2003-03-05 17:30:51 +0000 | [diff] [blame] | 380 | } |
Igor Sysoev | 1af7c82 | 2002-09-13 14:47:42 +0000 | [diff] [blame] | 381 | |
Igor Sysoev | a0bb31f | 2002-12-02 16:09:40 +0000 | [diff] [blame] | 382 | r->headers_in.headers = ngx_create_table(r->pool, 10); |
| 383 | |
Igor Sysoev | b086905 | 2002-12-10 18:05:12 +0000 | [diff] [blame] | 384 | r->state_handler = ngx_http_process_request_headers; |
Igor Sysoev | a58e3ca | 2002-09-02 14:48:24 +0000 | [diff] [blame] | 385 | ctx->action = "reading client request headers"; |
Igor Sysoev | 016b852 | 2002-08-29 16:59:54 +0000 | [diff] [blame] | 386 | |
Igor Sysoev | b086905 | 2002-12-10 18:05:12 +0000 | [diff] [blame] | 387 | return NGX_AGAIN; |
Igor Sysoev | 0dad629 | 2003-03-05 17:30:51 +0000 | [diff] [blame] | 388 | |
| 389 | /* there was error while a request line parsing */ |
| 390 | } else if (rc != NGX_AGAIN) { |
| 391 | return ngx_http_header_parse_error(r, rc, NGX_HTTP_BAD_REQUEST); |
Igor Sysoev | 6de5c2c | 2002-08-06 16:39:45 +0000 | [diff] [blame] | 392 | } |
| 393 | |
Igor Sysoev | 0dad629 | 2003-03-05 17:30:51 +0000 | [diff] [blame] | 394 | /* NGX_AGAIN: a request line parsing is still not complete */ |
| 395 | |
Igor Sysoev | b738757 | 2003-03-11 20:38:13 +0000 | [diff] [blame^] | 396 | if (r->header_in->last == r->header_in->end) { |
Igor Sysoev | 1af7c82 | 2002-09-13 14:47:42 +0000 | [diff] [blame] | 397 | |
Igor Sysoev | 0dad629 | 2003-03-05 17:30:51 +0000 | [diff] [blame] | 398 | /* If it's a pipelined request and a request line is not complete |
| 399 | then we need to copy it to the start of r->header_in hunk. |
Igor Sysoev | b738757 | 2003-03-11 20:38:13 +0000 | [diff] [blame^] | 400 | We need to copy it here only if the large client headers |
| 401 | are enabled otherwise a request line had been already copied |
Igor Sysoev | 0dad629 | 2003-03-05 17:30:51 +0000 | [diff] [blame] | 402 | to the start of r->header_in hunk in ngx_http_set_keepalive() */ |
| 403 | |
| 404 | if (ngx_http_large_client_header) { |
| 405 | offset = r->request_start - r->header_in->start; |
| 406 | |
| 407 | if (offset == 0) { |
| 408 | return ngx_http_header_parse_error(r, |
| 409 | NGX_HTTP_PARSE_TOO_LONG_URI, |
| 410 | NGX_HTTP_REQUEST_URI_TOO_LARGE); |
| 411 | } |
| 412 | |
| 413 | ngx_memcpy(r->header_in->start, r->request_start, |
Igor Sysoev | b738757 | 2003-03-11 20:38:13 +0000 | [diff] [blame^] | 414 | r->header_in->last - r->request_start); |
Igor Sysoev | 0dad629 | 2003-03-05 17:30:51 +0000 | [diff] [blame] | 415 | |
Igor Sysoev | b738757 | 2003-03-11 20:38:13 +0000 | [diff] [blame^] | 416 | r->header_in->pos -= offset; |
| 417 | r->header_in->last -= offset; |
Igor Sysoev | 0dad629 | 2003-03-05 17:30:51 +0000 | [diff] [blame] | 418 | r->request_start = r->header_in->start; |
| 419 | r->request_end -= offset; |
| 420 | r->uri_start -= offset; |
| 421 | r->uri_end -= offset; |
| 422 | if (r->uri_ext) { |
| 423 | r->uri_ext -= offset; |
| 424 | } |
| 425 | if (r->args_start) { |
| 426 | r->args_start -= offset; |
| 427 | } |
| 428 | |
| 429 | } else { |
| 430 | return ngx_http_header_parse_error(r, |
| 431 | NGX_HTTP_PARSE_TOO_LONG_URI, |
| 432 | NGX_HTTP_REQUEST_URI_TOO_LARGE); |
| 433 | } |
Igor Sysoev | 1af7c82 | 2002-09-13 14:47:42 +0000 | [diff] [blame] | 434 | } |
| 435 | |
Igor Sysoev | 0dad629 | 2003-03-05 17:30:51 +0000 | [diff] [blame] | 436 | return NGX_AGAIN; |
Igor Sysoev | 6de5c2c | 2002-08-06 16:39:45 +0000 | [diff] [blame] | 437 | } |
| 438 | |
Igor Sysoev | 1af7c82 | 2002-09-13 14:47:42 +0000 | [diff] [blame] | 439 | |
Igor Sysoev | b086905 | 2002-12-10 18:05:12 +0000 | [diff] [blame] | 440 | static int ngx_http_process_request_headers(ngx_http_request_t *r) |
Igor Sysoev | 6de5c2c | 2002-08-06 16:39:45 +0000 | [diff] [blame] | 441 | { |
Igor Sysoev | 3d062ad | 2003-03-05 06:37:42 +0000 | [diff] [blame] | 442 | int rc, offset; |
Igor Sysoev | 7300977 | 2003-02-06 17:21:13 +0000 | [diff] [blame] | 443 | size_t len; |
Igor Sysoev | 016b852 | 2002-08-29 16:59:54 +0000 | [diff] [blame] | 444 | ngx_http_log_ctx_t *ctx; |
Igor Sysoev | 6de5c2c | 2002-08-06 16:39:45 +0000 | [diff] [blame] | 445 | |
Igor Sysoev | 016b852 | 2002-08-29 16:59:54 +0000 | [diff] [blame] | 446 | for ( ;; ) { |
Igor Sysoev | b086905 | 2002-12-10 18:05:12 +0000 | [diff] [blame] | 447 | rc = ngx_read_http_header_line(r, r->header_in); |
Igor Sysoev | 016b852 | 2002-08-29 16:59:54 +0000 | [diff] [blame] | 448 | |
Igor Sysoev | 0dad629 | 2003-03-05 17:30:51 +0000 | [diff] [blame] | 449 | /* a header line has been parsed successfully */ |
| 450 | if (rc == NGX_OK) { |
Igor Sysoev | a19a85e | 2003-01-28 15:56:37 +0000 | [diff] [blame] | 451 | if (ngx_http_process_request_header_line(r) == NGX_ERROR) { |
Igor Sysoev | 6a644c6 | 2003-03-04 06:33:48 +0000 | [diff] [blame] | 452 | return ngx_http_error(r, NGX_HTTP_INTERNAL_SERVER_ERROR); |
Igor Sysoev | a19a85e | 2003-01-28 15:56:37 +0000 | [diff] [blame] | 453 | } |
| 454 | |
| 455 | return NGX_AGAIN; |
Igor Sysoev | a58e3ca | 2002-09-02 14:48:24 +0000 | [diff] [blame] | 456 | |
Igor Sysoev | b738757 | 2003-03-11 20:38:13 +0000 | [diff] [blame^] | 457 | /* a whole header has been parsed successfully */ |
Igor Sysoev | 1af7c82 | 2002-09-13 14:47:42 +0000 | [diff] [blame] | 458 | } else if (rc == NGX_HTTP_PARSE_HEADER_DONE) { |
Igor Sysoev | a58e3ca | 2002-09-02 14:48:24 +0000 | [diff] [blame] | 459 | ngx_log_debug(r->connection->log, "HTTP header done"); |
Igor Sysoev | 42feecb | 2002-12-15 06:25:09 +0000 | [diff] [blame] | 460 | |
Igor Sysoev | a19a85e | 2003-01-28 15:56:37 +0000 | [diff] [blame] | 461 | if (r->headers_in.host) { |
Igor Sysoev | 3d062ad | 2003-03-05 06:37:42 +0000 | [diff] [blame] | 462 | for (len = 0; len < r->headers_in.host->value.len; len++) { |
| 463 | if (r->headers_in.host->value.data[len] == ':') { |
| 464 | break; |
| 465 | } |
| 466 | } |
| 467 | r->headers_in.host_name_len = len; |
Igor Sysoev | a19a85e | 2003-01-28 15:56:37 +0000 | [diff] [blame] | 468 | |
Igor Sysoev | 42feecb | 2002-12-15 06:25:09 +0000 | [diff] [blame] | 469 | } else { |
Igor Sysoev | 3d062ad | 2003-03-05 06:37:42 +0000 | [diff] [blame] | 470 | if (r->http_version > NGX_HTTP_VERSION_10) { |
| 471 | return ngx_http_header_parse_error(r, |
| 472 | NGX_HTTP_PARSE_NO_HOST_HEADER, |
| 473 | NGX_HTTP_BAD_REQUEST); |
| 474 | } |
| 475 | r->headers_in.host_name_len = 0; |
Igor Sysoev | 42feecb | 2002-12-15 06:25:09 +0000 | [diff] [blame] | 476 | } |
Igor Sysoev | 016b852 | 2002-08-29 16:59:54 +0000 | [diff] [blame] | 477 | |
Igor Sysoev | 0dad629 | 2003-03-05 17:30:51 +0000 | [diff] [blame] | 478 | r->state_handler = NULL; |
Igor Sysoev | 3d062ad | 2003-03-05 06:37:42 +0000 | [diff] [blame] | 479 | return NGX_OK; |
Igor Sysoev | 6a644c6 | 2003-03-04 06:33:48 +0000 | [diff] [blame] | 480 | |
Igor Sysoev | 0dad629 | 2003-03-05 17:30:51 +0000 | [diff] [blame] | 481 | /* there was error while a header line parsing */ |
| 482 | } else if (rc != NGX_AGAIN) { |
| 483 | return ngx_http_header_parse_error(r, rc, NGX_HTTP_BAD_REQUEST); |
| 484 | } |
| 485 | |
| 486 | /* NGX_AGAIN: a header line parsing is still not complete */ |
| 487 | |
Igor Sysoev | b738757 | 2003-03-11 20:38:13 +0000 | [diff] [blame^] | 488 | if (r->header_in->last == r->header_in->end) { |
Igor Sysoev | 0dad629 | 2003-03-05 17:30:51 +0000 | [diff] [blame] | 489 | |
Igor Sysoev | b738757 | 2003-03-11 20:38:13 +0000 | [diff] [blame^] | 490 | /* if the large client headers are enabled then |
Igor Sysoev | 0dad629 | 2003-03-05 17:30:51 +0000 | [diff] [blame] | 491 | we need to compact r->header_in hunk */ |
| 492 | |
| 493 | if (ngx_http_large_client_header) { |
| 494 | offset = r->header_name_start - r->header_in->start; |
| 495 | |
| 496 | if (offset == 0) { |
| 497 | return ngx_http_header_parse_error(r, |
| 498 | NGX_HTTP_PARSE_TOO_LONG_HEADER, |
| 499 | NGX_HTTP_BAD_REQUEST); |
| 500 | } |
| 501 | |
| 502 | ngx_memcpy(r->header_in->start, r->header_name_start, |
Igor Sysoev | b738757 | 2003-03-11 20:38:13 +0000 | [diff] [blame^] | 503 | r->header_in->last - r->header_name_start); |
Igor Sysoev | 0dad629 | 2003-03-05 17:30:51 +0000 | [diff] [blame] | 504 | |
Igor Sysoev | b738757 | 2003-03-11 20:38:13 +0000 | [diff] [blame^] | 505 | r->header_in->last -= offset; |
| 506 | r->header_in->pos -= offset; |
Igor Sysoev | 0dad629 | 2003-03-05 17:30:51 +0000 | [diff] [blame] | 507 | r->header_name_start = r->header_in->start; |
| 508 | r->header_name_end -= offset; |
| 509 | r->header_start -= offset; |
| 510 | r->header_end -= offset; |
| 511 | |
| 512 | } else { |
| 513 | return ngx_http_header_parse_error(r, |
Igor Sysoev | 3d062ad | 2003-03-05 06:37:42 +0000 | [diff] [blame] | 514 | NGX_HTTP_PARSE_TOO_LONG_HEADER, |
| 515 | NGX_HTTP_BAD_REQUEST); |
Igor Sysoev | 0dad629 | 2003-03-05 17:30:51 +0000 | [diff] [blame] | 516 | } |
Igor Sysoev | a19a85e | 2003-01-28 15:56:37 +0000 | [diff] [blame] | 517 | |
Igor Sysoev | 016b852 | 2002-08-29 16:59:54 +0000 | [diff] [blame] | 518 | } |
Igor Sysoev | 0dad629 | 2003-03-05 17:30:51 +0000 | [diff] [blame] | 519 | |
| 520 | return NGX_AGAIN; |
Igor Sysoev | 6de5c2c | 2002-08-06 16:39:45 +0000 | [diff] [blame] | 521 | } |
Igor Sysoev | a58e3ca | 2002-09-02 14:48:24 +0000 | [diff] [blame] | 522 | } |
Igor Sysoev | 6de5c2c | 2002-08-06 16:39:45 +0000 | [diff] [blame] | 523 | |
Igor Sysoev | 1af7c82 | 2002-09-13 14:47:42 +0000 | [diff] [blame] | 524 | |
Igor Sysoev | a58e3ca | 2002-09-02 14:48:24 +0000 | [diff] [blame] | 525 | static int ngx_http_process_request_header_line(ngx_http_request_t *r) |
| 526 | { |
Igor Sysoev | a0bb31f | 2002-12-02 16:09:40 +0000 | [diff] [blame] | 527 | int i; |
| 528 | ngx_table_elt_t *h; |
| 529 | |
Igor Sysoev | 2d0d909 | 2002-12-03 15:45:38 +0000 | [diff] [blame] | 530 | ngx_test_null(h, ngx_push_table(r->headers_in.headers), NGX_ERROR); |
Igor Sysoev | a0bb31f | 2002-12-02 16:09:40 +0000 | [diff] [blame] | 531 | |
Igor Sysoev | b738757 | 2003-03-11 20:38:13 +0000 | [diff] [blame^] | 532 | /* if large client headers are enabled then |
Igor Sysoev | 6a644c6 | 2003-03-04 06:33:48 +0000 | [diff] [blame] | 533 | we need to copy header name and value */ |
Igor Sysoev | a0bb31f | 2002-12-02 16:09:40 +0000 | [diff] [blame] | 534 | |
Igor Sysoev | 6a644c6 | 2003-03-04 06:33:48 +0000 | [diff] [blame] | 535 | h->key.len = r->header_name_end - r->header_name_start; |
Igor Sysoev | a0bb31f | 2002-12-02 16:09:40 +0000 | [diff] [blame] | 536 | h->value.len = r->header_end - r->header_start; |
Igor Sysoev | 6a644c6 | 2003-03-04 06:33:48 +0000 | [diff] [blame] | 537 | |
| 538 | if (ngx_http_large_client_header) { |
| 539 | ngx_test_null(h->key.data, ngx_palloc(r->pool, h->key.len + 1), |
| 540 | NGX_ERROR); |
| 541 | ngx_test_null(h->value.data, ngx_palloc(r->pool, h->value.len + 1), |
| 542 | NGX_ERROR); |
| 543 | ngx_cpystrn(h->key.data, r->header_name_start, h->key.len + 1); |
| 544 | ngx_cpystrn(h->value.data, r->header_start, h->value.len + 1); |
| 545 | |
| 546 | } else { |
| 547 | h->key.data = r->header_name_start; |
| 548 | h->key.data[h->key.len] = '\0'; |
| 549 | h->value.data = r->header_start; |
| 550 | h->value.data[h->value.len] = '\0'; |
| 551 | } |
Igor Sysoev | a0bb31f | 2002-12-02 16:09:40 +0000 | [diff] [blame] | 552 | |
| 553 | for (i = 0; headers_in[i].len != 0; i++) { |
Igor Sysoev | a19a85e | 2003-01-28 15:56:37 +0000 | [diff] [blame] | 554 | if (headers_in[i].len != h->key.len) { |
| 555 | continue; |
| 556 | } |
| 557 | |
| 558 | if (ngx_strcasecmp(headers_in[i].data, h->key.data) == 0) { |
| 559 | *((ngx_table_elt_t **) |
| 560 | ((char *) &r->headers_in + headers_in[i].offset)) = h; |
Igor Sysoev | a0bb31f | 2002-12-02 16:09:40 +0000 | [diff] [blame] | 561 | } |
| 562 | } |
| 563 | |
Igor Sysoev | a58e3ca | 2002-09-02 14:48:24 +0000 | [diff] [blame] | 564 | ngx_log_debug(r->connection->log, "HTTP header: '%s: %s'" _ |
Igor Sysoev | a0bb31f | 2002-12-02 16:09:40 +0000 | [diff] [blame] | 565 | h->key.data _ h->value.data); |
Igor Sysoev | 6de5c2c | 2002-08-06 16:39:45 +0000 | [diff] [blame] | 566 | |
Igor Sysoev | a58e3ca | 2002-09-02 14:48:24 +0000 | [diff] [blame] | 567 | return NGX_OK; |
| 568 | } |
| 569 | |
Igor Sysoev | a58e3ca | 2002-09-02 14:48:24 +0000 | [diff] [blame] | 570 | |
Igor Sysoev | 42feecb | 2002-12-15 06:25:09 +0000 | [diff] [blame] | 571 | static int ngx_http_event_request_handler(ngx_http_request_t *r) |
Igor Sysoev | a58e3ca | 2002-09-02 14:48:24 +0000 | [diff] [blame] | 572 | { |
Igor Sysoev | 6a644c6 | 2003-03-04 06:33:48 +0000 | [diff] [blame] | 573 | int rc, event; |
| 574 | ngx_msec_t timeout; |
| 575 | ngx_event_t *rev, *wev; |
| 576 | ngx_http_log_ctx_t *ctx; |
Igor Sysoev | a58e3ca | 2002-09-02 14:48:24 +0000 | [diff] [blame] | 577 | |
Igor Sysoev | 9b25d69 | 2003-01-26 21:08:14 +0000 | [diff] [blame] | 578 | rev = r->connection->read; |
| 579 | wev = r->connection->write; |
| 580 | |
| 581 | if (rev->timer_set) { |
| 582 | ngx_del_timer(rev); |
| 583 | rev->timer_set = 0; |
| 584 | } |
Igor Sysoev | b086905 | 2002-12-10 18:05:12 +0000 | [diff] [blame] | 585 | |
Igor Sysoev | 9b25d69 | 2003-01-26 21:08:14 +0000 | [diff] [blame] | 586 | rev->event_handler = ngx_http_block_read; |
Igor Sysoev | a0bb31f | 2002-12-02 16:09:40 +0000 | [diff] [blame] | 587 | |
Igor Sysoev | 6a644c6 | 2003-03-04 06:33:48 +0000 | [diff] [blame] | 588 | ctx = r->connection->log->data; |
| 589 | ctx->action = "processing client request"; |
| 590 | |
Igor Sysoev | 682bf8e | 2002-09-16 15:01:44 +0000 | [diff] [blame] | 591 | rc = ngx_http_handler(r); |
Igor Sysoev | a58e3ca | 2002-09-02 14:48:24 +0000 | [diff] [blame] | 592 | |
Igor Sysoev | ef259d1 | 2002-12-06 16:32:33 +0000 | [diff] [blame] | 593 | /* handler is still busy */ |
Igor Sysoev | 6ed07e4 | 2002-12-05 16:21:24 +0000 | [diff] [blame] | 594 | if (rc == NGX_WAITING) |
| 595 | return rc; |
| 596 | |
Igor Sysoev | 7300977 | 2003-02-06 17:21:13 +0000 | [diff] [blame] | 597 | /* handler has done its work but transfer is still not completed */ |
Igor Sysoev | a58e3ca | 2002-09-02 14:48:24 +0000 | [diff] [blame] | 598 | if (rc == NGX_AGAIN) { |
Igor Sysoev | a58e3ca | 2002-09-02 14:48:24 +0000 | [diff] [blame] | 599 | |
Igor Sysoev | 6a644c6 | 2003-03-04 06:33:48 +0000 | [diff] [blame] | 600 | /* STUB: timeouts should be reworked */ |
Igor Sysoev | 96f8377 | 2002-09-07 10:14:25 +0000 | [diff] [blame] | 601 | if (r->connection->sent > 0) { |
Igor Sysoev | 7300977 | 2003-02-06 17:21:13 +0000 | [diff] [blame] | 602 | ngx_log_debug(r->connection->log, "sent: " OFF_FMT _ |
Igor Sysoev | 96f8377 | 2002-09-07 10:14:25 +0000 | [diff] [blame] | 603 | r->connection->sent); |
| 604 | timeout = (ngx_msec_t) (r->connection->sent * 10); |
| 605 | ngx_log_debug(r->connection->log, "timeout: %d" _ timeout); |
Igor Sysoev | 9b25d69 | 2003-01-26 21:08:14 +0000 | [diff] [blame] | 606 | ngx_add_timer(wev, timeout); |
Igor Sysoev | 96f8377 | 2002-09-07 10:14:25 +0000 | [diff] [blame] | 607 | |
| 608 | } else { |
Igor Sysoev | 9b25d69 | 2003-01-26 21:08:14 +0000 | [diff] [blame] | 609 | ngx_add_timer(wev, 10000); |
Igor Sysoev | 96f8377 | 2002-09-07 10:14:25 +0000 | [diff] [blame] | 610 | } |
Igor Sysoev | a58e3ca | 2002-09-02 14:48:24 +0000 | [diff] [blame] | 611 | |
Igor Sysoev | 9b25d69 | 2003-01-26 21:08:14 +0000 | [diff] [blame] | 612 | wev->event_handler = ngx_http_writer; |
Igor Sysoev | 7300977 | 2003-02-06 17:21:13 +0000 | [diff] [blame] | 613 | |
| 614 | #if (USE_KQUEUE) |
| 615 | |
Igor Sysoev | 6a644c6 | 2003-03-04 06:33:48 +0000 | [diff] [blame] | 616 | #if (HAVE_LOWAT_EVENT) /* kqueue's NOTE_LOWAT */ |
| 617 | wev->lowat = /* STUB */ NGX_LOWAT; |
| 618 | #endif |
| 619 | |
Igor Sysoev | 7300977 | 2003-02-06 17:21:13 +0000 | [diff] [blame] | 620 | if (ngx_add_event(wev, NGX_WRITE_EVENT, NGX_CLEAR_EVENT) == NGX_ERROR) { |
| 621 | return ngx_http_close_request(r); |
| 622 | } |
| 623 | |
Igor Sysoev | a58e3ca | 2002-09-02 14:48:24 +0000 | [diff] [blame] | 624 | return rc; |
Igor Sysoev | 7300977 | 2003-02-06 17:21:13 +0000 | [diff] [blame] | 625 | |
| 626 | #else |
| 627 | |
Igor Sysoev | 1e7ec9d | 2003-02-11 07:14:40 +0000 | [diff] [blame] | 628 | #if (HAVE_AIO_EVENT) || (HAVE_EDGE_EVENT) /* aio, iocp, epoll */ |
Igor Sysoev | 7300977 | 2003-02-06 17:21:13 +0000 | [diff] [blame] | 629 | |
Igor Sysoev | 1e7ec9d | 2003-02-11 07:14:40 +0000 | [diff] [blame] | 630 | if (ngx_event_flags & (NGX_HAVE_AIO_EVENT|NGX_HAVE_EDGE_EVENT)) { |
Igor Sysoev | 7300977 | 2003-02-06 17:21:13 +0000 | [diff] [blame] | 631 | return rc; |
| 632 | } |
| 633 | |
| 634 | #endif |
| 635 | |
Igor Sysoev | 6a644c6 | 2003-03-04 06:33:48 +0000 | [diff] [blame] | 636 | #if (HAVE_LOWAT_EVENT) /* kqueue's NOTE_LOWAT */ |
| 637 | |
| 638 | if (ngx_event_flags & NGX_HAVE_LOWAT_EVENT) { |
| 639 | wev->lowat = /* STUB */ NGX_LOWAT; |
| 640 | } |
| 641 | |
| 642 | #endif |
| 643 | |
Igor Sysoev | 7300977 | 2003-02-06 17:21:13 +0000 | [diff] [blame] | 644 | #if (HAVE_CLEAR_EVENT) /* kqueue */ |
| 645 | |
| 646 | if (ngx_event_flags & NGX_HAVE_CLEAR_EVENT) { |
| 647 | event = NGX_CLEAR_EVENT; |
| 648 | |
| 649 | } else { |
Igor Sysoev | 7300977 | 2003-02-06 17:21:13 +0000 | [diff] [blame] | 650 | event = NGX_LEVEL_EVENT; |
Igor Sysoev | 7300977 | 2003-02-06 17:21:13 +0000 | [diff] [blame] | 651 | } |
| 652 | |
Igor Sysoev | 1e7ec9d | 2003-02-11 07:14:40 +0000 | [diff] [blame] | 653 | #else /* select, poll, /dev/poll */ |
Igor Sysoev | 7300977 | 2003-02-06 17:21:13 +0000 | [diff] [blame] | 654 | |
Igor Sysoev | 1e7ec9d | 2003-02-11 07:14:40 +0000 | [diff] [blame] | 655 | event = NGX_LEVEL_EVENT; |
Igor Sysoev | 7300977 | 2003-02-06 17:21:13 +0000 | [diff] [blame] | 656 | |
| 657 | #endif |
| 658 | |
| 659 | if (ngx_add_event(wev, NGX_WRITE_EVENT, event) == NGX_ERROR) { |
| 660 | return ngx_http_close_request(r); |
| 661 | } |
| 662 | |
| 663 | return rc; |
| 664 | |
| 665 | |
| 666 | #endif /* USE_KQUEUE */ |
| 667 | |
Igor Sysoev | a58e3ca | 2002-09-02 14:48:24 +0000 | [diff] [blame] | 668 | } |
| 669 | |
| 670 | if (rc == NGX_ERROR) { |
| 671 | /* log http request */ |
| 672 | return ngx_http_close_request(r); |
| 673 | } |
| 674 | |
| 675 | if (rc >= NGX_HTTP_SPECIAL_RESPONSE) |
| 676 | return ngx_http_special_response(r, rc); |
| 677 | |
| 678 | /* rc == NGX_OK */ |
| 679 | |
Igor Sysoev | 6a644c6 | 2003-03-04 06:33:48 +0000 | [diff] [blame] | 680 | if (r->keepalive == 0) { |
Igor Sysoev | 3a40d48 | 2002-09-12 14:42:29 +0000 | [diff] [blame] | 681 | if (r->lingering_close) { |
Igor Sysoev | 682bf8e | 2002-09-16 15:01:44 +0000 | [diff] [blame] | 682 | return ngx_http_set_lingering_close(r); |
| 683 | |
Igor Sysoev | 3a40d48 | 2002-09-12 14:42:29 +0000 | [diff] [blame] | 684 | } else { |
| 685 | return ngx_http_close_request(r); |
| 686 | } |
| 687 | } |
Igor Sysoev | 682bf8e | 2002-09-16 15:01:44 +0000 | [diff] [blame] | 688 | |
| 689 | /* keepalive */ |
| 690 | |
Igor Sysoev | 1e7ec9d | 2003-02-11 07:14:40 +0000 | [diff] [blame] | 691 | return ngx_http_set_keepalive(r); |
Igor Sysoev | 682bf8e | 2002-09-16 15:01:44 +0000 | [diff] [blame] | 692 | } |
| 693 | |
Igor Sysoev | b086905 | 2002-12-10 18:05:12 +0000 | [diff] [blame] | 694 | |
Igor Sysoev | 0ad17c0 | 2002-08-26 15:18:19 +0000 | [diff] [blame] | 695 | static int ngx_http_writer(ngx_event_t *ev) |
| 696 | { |
| 697 | int rc; |
Igor Sysoev | a0bb31f | 2002-12-02 16:09:40 +0000 | [diff] [blame] | 698 | ngx_msec_t timeout; |
| 699 | ngx_connection_t *c; |
| 700 | ngx_http_request_t *r; |
| 701 | ngx_http_core_loc_conf_t *conf; |
Igor Sysoev | 0ad17c0 | 2002-08-26 15:18:19 +0000 | [diff] [blame] | 702 | |
Igor Sysoev | a58e3ca | 2002-09-02 14:48:24 +0000 | [diff] [blame] | 703 | c = (ngx_connection_t *) ev->data; |
| 704 | r = (ngx_http_request_t *) c->data; |
Igor Sysoev | 0ad17c0 | 2002-08-26 15:18:19 +0000 | [diff] [blame] | 705 | |
Igor Sysoev | a58e3ca | 2002-09-02 14:48:24 +0000 | [diff] [blame] | 706 | rc = ngx_http_output_filter(r, NULL); |
Igor Sysoev | 0ad17c0 | 2002-08-26 15:18:19 +0000 | [diff] [blame] | 707 | |
Igor Sysoev | 682bf8e | 2002-09-16 15:01:44 +0000 | [diff] [blame] | 708 | ngx_log_debug(ev->log, "output filter in writer: %d" _ rc); |
Igor Sysoev | a58e3ca | 2002-09-02 14:48:24 +0000 | [diff] [blame] | 709 | |
| 710 | if (rc == NGX_AGAIN) { |
| 711 | |
Igor Sysoev | 6a644c6 | 2003-03-04 06:33:48 +0000 | [diff] [blame] | 712 | /* STUB: timeouts should be reworked */ |
Igor Sysoev | a58e3ca | 2002-09-02 14:48:24 +0000 | [diff] [blame] | 713 | if (c->sent > 0) { |
Igor Sysoev | a0bb31f | 2002-12-02 16:09:40 +0000 | [diff] [blame] | 714 | conf = (ngx_http_core_loc_conf_t *) |
Igor Sysoev | 207ed5a | 2002-12-26 16:26:23 +0000 | [diff] [blame] | 715 | ngx_http_get_module_loc_conf(r->main ? r->main : r, |
| 716 | ngx_http_core_module_ctx); |
Igor Sysoev | 682bf8e | 2002-09-16 15:01:44 +0000 | [diff] [blame] | 717 | |
| 718 | timeout = (ngx_msec_t) (c->sent * conf->send_timeout); |
| 719 | |
Igor Sysoev | 7300977 | 2003-02-06 17:21:13 +0000 | [diff] [blame] | 720 | ngx_log_debug(ev->log, "sent: " OFF_FMT _ c->sent); |
Igor Sysoev | a58e3ca | 2002-09-02 14:48:24 +0000 | [diff] [blame] | 721 | ngx_log_debug(ev->log, "timeout: %d" _ timeout); |
Igor Sysoev | 682bf8e | 2002-09-16 15:01:44 +0000 | [diff] [blame] | 722 | |
Igor Sysoev | 9b25d69 | 2003-01-26 21:08:14 +0000 | [diff] [blame] | 723 | if (ev->timer_set) { |
| 724 | ngx_del_timer(ev); |
| 725 | } else { |
| 726 | ev->timer_set = 1; |
| 727 | } |
| 728 | |
Igor Sysoev | a58e3ca | 2002-09-02 14:48:24 +0000 | [diff] [blame] | 729 | ngx_add_timer(ev, timeout); |
| 730 | } |
| 731 | |
Igor Sysoev | 0ad17c0 | 2002-08-26 15:18:19 +0000 | [diff] [blame] | 732 | return rc; |
Igor Sysoev | a58e3ca | 2002-09-02 14:48:24 +0000 | [diff] [blame] | 733 | } |
Igor Sysoev | 0ad17c0 | 2002-08-26 15:18:19 +0000 | [diff] [blame] | 734 | |
| 735 | if (rc == NGX_ERROR) |
| 736 | return rc; |
| 737 | |
| 738 | /* rc == NGX_OK */ |
| 739 | |
Igor Sysoev | 682bf8e | 2002-09-16 15:01:44 +0000 | [diff] [blame] | 740 | ngx_log_debug(ev->log, "http writer done"); |
Igor Sysoev | 0ad17c0 | 2002-08-26 15:18:19 +0000 | [diff] [blame] | 741 | |
Igor Sysoev | 6a644c6 | 2003-03-04 06:33:48 +0000 | [diff] [blame] | 742 | if (r->keepalive == 0) { |
Igor Sysoev | 3a40d48 | 2002-09-12 14:42:29 +0000 | [diff] [blame] | 743 | if (r->lingering_close) { |
Igor Sysoev | 3a17f24 | 2002-12-24 17:30:59 +0000 | [diff] [blame] | 744 | return ngx_http_set_lingering_close(r); |
Igor Sysoev | 682bf8e | 2002-09-16 15:01:44 +0000 | [diff] [blame] | 745 | |
Igor Sysoev | 3a40d48 | 2002-09-12 14:42:29 +0000 | [diff] [blame] | 746 | } else { |
| 747 | return ngx_http_close_request(r); |
| 748 | } |
| 749 | } |
Igor Sysoev | 0ad17c0 | 2002-08-26 15:18:19 +0000 | [diff] [blame] | 750 | |
Igor Sysoev | 3a40d48 | 2002-09-12 14:42:29 +0000 | [diff] [blame] | 751 | /* keepalive */ |
Igor Sysoev | 682bf8e | 2002-09-16 15:01:44 +0000 | [diff] [blame] | 752 | |
Igor Sysoev | 1e7ec9d | 2003-02-11 07:14:40 +0000 | [diff] [blame] | 753 | return ngx_http_set_keepalive(r); |
Igor Sysoev | 0ad17c0 | 2002-08-26 15:18:19 +0000 | [diff] [blame] | 754 | } |
| 755 | |
Igor Sysoev | b086905 | 2002-12-10 18:05:12 +0000 | [diff] [blame] | 756 | |
Igor Sysoev | 42feecb | 2002-12-15 06:25:09 +0000 | [diff] [blame] | 757 | static int ngx_http_block_read(ngx_event_t *ev) |
Igor Sysoev | 682bf8e | 2002-09-16 15:01:44 +0000 | [diff] [blame] | 758 | { |
Igor Sysoev | 42feecb | 2002-12-15 06:25:09 +0000 | [diff] [blame] | 759 | ngx_log_debug(ev->log, "http read blocked"); |
| 760 | |
Igor Sysoev | 7300977 | 2003-02-06 17:21:13 +0000 | [diff] [blame] | 761 | /* aio does not call this handler */ |
| 762 | |
| 763 | #if (USE_KQUEUE) |
| 764 | |
| 765 | return NGX_OK; |
| 766 | |
| 767 | #else |
| 768 | |
Igor Sysoev | b738757 | 2003-03-11 20:38:13 +0000 | [diff] [blame^] | 769 | if (ngx_event_flags & NGX_USE_LEVEL_EVENT) { /* select, poll, /dev/poll */ |
Igor Sysoev | 3d062ad | 2003-03-05 06:37:42 +0000 | [diff] [blame] | 770 | ev->blocked = 1; |
| 771 | return ngx_del_event(ev, NGX_READ_EVENT, 0); |
Igor Sysoev | 7300977 | 2003-02-06 17:21:13 +0000 | [diff] [blame] | 772 | |
Igor Sysoev | b738757 | 2003-03-11 20:38:13 +0000 | [diff] [blame^] | 773 | } else { /* kqueue, epoll */ |
Igor Sysoev | 7300977 | 2003-02-06 17:21:13 +0000 | [diff] [blame] | 774 | return NGX_OK; |
| 775 | } |
| 776 | |
Igor Sysoev | 7300977 | 2003-02-06 17:21:13 +0000 | [diff] [blame] | 777 | #endif /* USE_KQUEUE */ |
Igor Sysoev | 42feecb | 2002-12-15 06:25:09 +0000 | [diff] [blame] | 778 | } |
| 779 | |
| 780 | |
Igor Sysoev | 1e7ec9d | 2003-02-11 07:14:40 +0000 | [diff] [blame] | 781 | /* TODO */ |
Igor Sysoev | 42feecb | 2002-12-15 06:25:09 +0000 | [diff] [blame] | 782 | int ngx_http_discard_body(ngx_http_request_t *r) |
| 783 | { |
Igor Sysoev | 9b25d69 | 2003-01-26 21:08:14 +0000 | [diff] [blame] | 784 | ngx_event_t *ev; |
| 785 | |
| 786 | ev = r->connection->read; |
| 787 | |
Igor Sysoev | 42feecb | 2002-12-15 06:25:09 +0000 | [diff] [blame] | 788 | ngx_log_debug(r->connection->log, "set discard body"); |
Igor Sysoev | 682bf8e | 2002-09-16 15:01:44 +0000 | [diff] [blame] | 789 | |
Igor Sysoev | 9b25d69 | 2003-01-26 21:08:14 +0000 | [diff] [blame] | 790 | if (ev->timer_set) { |
| 791 | ngx_del_timer(ev); |
| 792 | ev->timer_set = 0; |
| 793 | } |
Igor Sysoev | 682bf8e | 2002-09-16 15:01:44 +0000 | [diff] [blame] | 794 | |
Igor Sysoev | 7300977 | 2003-02-06 17:21:13 +0000 | [diff] [blame] | 795 | if (r->client_content_length) { |
Igor Sysoev | 9b25d69 | 2003-01-26 21:08:14 +0000 | [diff] [blame] | 796 | ev->event_handler = ngx_http_read_discarded_body; |
Igor Sysoev | 7300977 | 2003-02-06 17:21:13 +0000 | [diff] [blame] | 797 | /* if blocked - read */ |
| 798 | /* else add timer */ |
| 799 | } |
Igor Sysoev | 682bf8e | 2002-09-16 15:01:44 +0000 | [diff] [blame] | 800 | |
| 801 | return NGX_OK; |
| 802 | } |
| 803 | |
Igor Sysoev | 0ad17c0 | 2002-08-26 15:18:19 +0000 | [diff] [blame] | 804 | |
Igor Sysoev | 1e7ec9d | 2003-02-11 07:14:40 +0000 | [diff] [blame] | 805 | /* TODO */ |
Igor Sysoev | 42feecb | 2002-12-15 06:25:09 +0000 | [diff] [blame] | 806 | static int ngx_http_read_discarded_body(ngx_event_t *ev) |
| 807 | { |
| 808 | size_t size; |
| 809 | ssize_t n; |
Igor Sysoev | 4e9393a | 2003-01-09 05:36:00 +0000 | [diff] [blame] | 810 | ngx_connection_t *c; |
| 811 | ngx_http_request_t *r; |
| 812 | ngx_http_core_loc_conf_t *lcf; |
Igor Sysoev | 42feecb | 2002-12-15 06:25:09 +0000 | [diff] [blame] | 813 | |
| 814 | ngx_log_debug(ev->log, "http read discarded body"); |
| 815 | |
| 816 | if (ev->timedout) |
| 817 | return NGX_ERROR; |
| 818 | |
Igor Sysoev | 4e9393a | 2003-01-09 05:36:00 +0000 | [diff] [blame] | 819 | c = (ngx_connection_t *) ev->data; |
| 820 | r = (ngx_http_request_t *) c->data; |
| 821 | |
| 822 | lcf = (ngx_http_core_loc_conf_t *) |
| 823 | ngx_http_get_module_loc_conf(r, ngx_http_core_module_ctx); |
| 824 | |
Igor Sysoev | 42feecb | 2002-12-15 06:25:09 +0000 | [diff] [blame] | 825 | if (r->discarded_buffer == NULL) |
| 826 | ngx_test_null(r->discarded_buffer, |
Igor Sysoev | 4e9393a | 2003-01-09 05:36:00 +0000 | [diff] [blame] | 827 | ngx_palloc(r->pool, lcf->discarded_buffer_size), |
Igor Sysoev | 42feecb | 2002-12-15 06:25:09 +0000 | [diff] [blame] | 828 | NGX_ERROR); |
| 829 | |
| 830 | size = r->client_content_length; |
Igor Sysoev | 4e9393a | 2003-01-09 05:36:00 +0000 | [diff] [blame] | 831 | if (size > lcf->discarded_buffer_size) |
| 832 | size = lcf->discarded_buffer_size; |
Igor Sysoev | 42feecb | 2002-12-15 06:25:09 +0000 | [diff] [blame] | 833 | |
| 834 | n = ngx_event_recv(c, r->discarded_buffer, size); |
| 835 | if (n == NGX_ERROR) |
| 836 | return NGX_ERROR; |
| 837 | |
| 838 | if (n == NGX_AGAIN) |
| 839 | return NGX_OK; |
| 840 | |
| 841 | r->client_content_length -= n; |
| 842 | /* XXX: what if r->client_content_length == 0 ? */ |
| 843 | return NGX_OK; |
| 844 | } |
| 845 | |
| 846 | |
Igor Sysoev | 1e7ec9d | 2003-02-11 07:14:40 +0000 | [diff] [blame] | 847 | static int ngx_http_set_keepalive(ngx_http_request_t *r) |
| 848 | { |
Igor Sysoev | b738757 | 2003-03-11 20:38:13 +0000 | [diff] [blame^] | 849 | int len, blocked; |
Igor Sysoev | 3d062ad | 2003-03-05 06:37:42 +0000 | [diff] [blame] | 850 | ngx_hunk_t *h; |
| 851 | ngx_event_t *rev, *wev; |
Igor Sysoev | 1e7ec9d | 2003-02-11 07:14:40 +0000 | [diff] [blame] | 852 | ngx_connection_t *c; |
Igor Sysoev | 6a644c6 | 2003-03-04 06:33:48 +0000 | [diff] [blame] | 853 | ngx_http_log_ctx_t *ctx; |
Igor Sysoev | 1e7ec9d | 2003-02-11 07:14:40 +0000 | [diff] [blame] | 854 | |
| 855 | c = (ngx_connection_t *) r->connection; |
Igor Sysoev | 3d062ad | 2003-03-05 06:37:42 +0000 | [diff] [blame] | 856 | rev = c->read; |
| 857 | wev = c->write; |
Igor Sysoev | 1e7ec9d | 2003-02-11 07:14:40 +0000 | [diff] [blame] | 858 | |
Igor Sysoev | 6a644c6 | 2003-03-04 06:33:48 +0000 | [diff] [blame] | 859 | ctx = (ngx_http_log_ctx_t *) c->log->data; |
| 860 | ctx->action = "closing request"; |
Igor Sysoev | 1e7ec9d | 2003-02-11 07:14:40 +0000 | [diff] [blame] | 861 | ngx_http_close_request(r); |
| 862 | |
Igor Sysoev | b738757 | 2003-03-11 20:38:13 +0000 | [diff] [blame^] | 863 | if (rev->blocked && (ngx_event_flags & NGX_USE_LEVEL_EVENT)) { |
| 864 | if (ngx_add_event(rev, NGX_READ_EVENT, NGX_LEVEL_EVENT) == NGX_ERROR) { |
| 865 | return NGX_ERROR; |
| 866 | } |
| 867 | blocked = 1; |
| 868 | rev->blocked = 0; |
| 869 | |
| 870 | } else { |
| 871 | blocked = 0; |
| 872 | } |
| 873 | |
Igor Sysoev | 3d062ad | 2003-03-05 06:37:42 +0000 | [diff] [blame] | 874 | h = c->buffer; |
| 875 | |
| 876 | /* pipelined request */ |
Igor Sysoev | b738757 | 2003-03-11 20:38:13 +0000 | [diff] [blame^] | 877 | if (h->pos < h->last) { |
Igor Sysoev | 3d062ad | 2003-03-05 06:37:42 +0000 | [diff] [blame] | 878 | |
Igor Sysoev | 0dad629 | 2003-03-05 17:30:51 +0000 | [diff] [blame] | 879 | /* We do not know here whether pipelined request is complete |
Igor Sysoev | b738757 | 2003-03-11 20:38:13 +0000 | [diff] [blame^] | 880 | so if large client headers are not enabled |
| 881 | we need to copy the data to the start of c->buffer. |
| 882 | This copy should be rare because clients that support |
| 883 | pipelined requests (Mozilla 1.x, Opera 6.x) are still rare */ |
Igor Sysoev | 3d062ad | 2003-03-05 06:37:42 +0000 | [diff] [blame] | 884 | |
| 885 | if (!ngx_http_large_client_header) { |
Igor Sysoev | b738757 | 2003-03-11 20:38:13 +0000 | [diff] [blame^] | 886 | len = h->last - h->pos; |
| 887 | ngx_memcpy(h->start, h->pos, len); |
| 888 | h->pos = h->start; |
| 889 | h->last = h->start + len; |
Igor Sysoev | 3d062ad | 2003-03-05 06:37:42 +0000 | [diff] [blame] | 890 | } |
| 891 | |
| 892 | c->pipeline = 1; |
| 893 | ctx->action = "reading client pipelined request line"; |
| 894 | return ngx_http_init_request(rev); |
| 895 | } |
| 896 | |
| 897 | c->pipeline = 0; |
| 898 | |
Igor Sysoev | b738757 | 2003-03-11 20:38:13 +0000 | [diff] [blame^] | 899 | h->pos = h->last = h->start; |
Igor Sysoev | 3d062ad | 2003-03-05 06:37:42 +0000 | [diff] [blame] | 900 | rev->event_handler = ngx_http_keepalive_handler; |
| 901 | |
Igor Sysoev | b738757 | 2003-03-11 20:38:13 +0000 | [diff] [blame^] | 902 | if (wev->active && (ngx_event_flags & NGX_USE_LEVEL_EVENT)) { |
Igor Sysoev | 3d062ad | 2003-03-05 06:37:42 +0000 | [diff] [blame] | 903 | if (ngx_del_event(wev, NGX_WRITE_EVENT, 0) == NGX_ERROR) { |
| 904 | return NGX_ERROR; |
| 905 | } |
| 906 | } |
| 907 | |
Igor Sysoev | 6a644c6 | 2003-03-04 06:33:48 +0000 | [diff] [blame] | 908 | ctx->action = "keepalive"; |
| 909 | |
Igor Sysoev | 1e7ec9d | 2003-02-11 07:14:40 +0000 | [diff] [blame] | 910 | #if (HAVE_AIO_EVENT) /* aio, iocp */ |
Igor Sysoev | 3d062ad | 2003-03-05 06:37:42 +0000 | [diff] [blame] | 911 | |
Igor Sysoev | b738757 | 2003-03-11 20:38:13 +0000 | [diff] [blame^] | 912 | if ((ngx_event_flags & NGX_HAVE_AIO_EVENT) || blocked) { |
| 913 | return ngx_http_keepalive_handler(rev); |
| 914 | } |
| 915 | |
| 916 | #else |
| 917 | |
| 918 | if (blocked) { |
Igor Sysoev | 3d062ad | 2003-03-05 06:37:42 +0000 | [diff] [blame] | 919 | return ngx_http_keepalive_handler(rev); |
Igor Sysoev | 1e7ec9d | 2003-02-11 07:14:40 +0000 | [diff] [blame] | 920 | } |
Igor Sysoev | 3d062ad | 2003-03-05 06:37:42 +0000 | [diff] [blame] | 921 | |
Igor Sysoev | 1e7ec9d | 2003-02-11 07:14:40 +0000 | [diff] [blame] | 922 | #endif |
| 923 | |
| 924 | return NGX_OK; |
| 925 | } |
| 926 | |
| 927 | |
Igor Sysoev | 0ad17c0 | 2002-08-26 15:18:19 +0000 | [diff] [blame] | 928 | static int ngx_http_keepalive_handler(ngx_event_t *ev) |
| 929 | { |
Igor Sysoev | 682bf8e | 2002-09-16 15:01:44 +0000 | [diff] [blame] | 930 | ssize_t n; |
Igor Sysoev | 0ad17c0 | 2002-08-26 15:18:19 +0000 | [diff] [blame] | 931 | ngx_connection_t *c; |
| 932 | ngx_http_log_ctx_t *ctx; |
| 933 | |
Igor Sysoev | 682bf8e | 2002-09-16 15:01:44 +0000 | [diff] [blame] | 934 | c = (ngx_connection_t *) ev->data; |
| 935 | |
Igor Sysoev | 42feecb | 2002-12-15 06:25:09 +0000 | [diff] [blame] | 936 | ngx_log_debug(ev->log, "http keepalive handler"); |
Igor Sysoev | 1af7c82 | 2002-09-13 14:47:42 +0000 | [diff] [blame] | 937 | |
| 938 | if (ev->timedout) |
| 939 | return NGX_DONE; |
| 940 | |
Igor Sysoev | b738757 | 2003-03-11 20:38:13 +0000 | [diff] [blame^] | 941 | /* MSIE closes keepalive connection with RST flag |
| 942 | so we ignore ECONNRESET here */ |
| 943 | |
| 944 | ev->ignore_econnreset = 1; |
| 945 | ngx_set_socket_errno(0); |
| 946 | n = ngx_event_recv(c, c->buffer->last, c->buffer->end - c->buffer->last); |
| 947 | ev->ignore_econnreset = 0; |
Igor Sysoev | 0ad17c0 | 2002-08-26 15:18:19 +0000 | [diff] [blame] | 948 | |
Igor Sysoev | 682bf8e | 2002-09-16 15:01:44 +0000 | [diff] [blame] | 949 | if (n == NGX_AGAIN || n == NGX_ERROR) |
| 950 | return n; |
Igor Sysoev | 0ad17c0 | 2002-08-26 15:18:19 +0000 | [diff] [blame] | 951 | |
Igor Sysoev | 682bf8e | 2002-09-16 15:01:44 +0000 | [diff] [blame] | 952 | ctx = (ngx_http_log_ctx_t *) ev->log->data; |
| 953 | ev->log->handler = NULL; |
| 954 | |
| 955 | if (n == 0) { |
Igor Sysoev | b738757 | 2003-03-11 20:38:13 +0000 | [diff] [blame^] | 956 | ngx_log_error(NGX_LOG_INFO, ev->log, ngx_socket_errno, |
Igor Sysoev | 682bf8e | 2002-09-16 15:01:44 +0000 | [diff] [blame] | 957 | "client %s closed keepalive connection", ctx->client); |
| 958 | return NGX_DONE; |
| 959 | } |
| 960 | |
Igor Sysoev | b738757 | 2003-03-11 20:38:13 +0000 | [diff] [blame^] | 961 | c->buffer->last += n; |
Igor Sysoev | 682bf8e | 2002-09-16 15:01:44 +0000 | [diff] [blame] | 962 | ev->log->handler = ngx_http_log_error; |
Igor Sysoev | 0ad17c0 | 2002-08-26 15:18:19 +0000 | [diff] [blame] | 963 | ctx->action = "reading client request line"; |
Igor Sysoev | 0ad17c0 | 2002-08-26 15:18:19 +0000 | [diff] [blame] | 964 | |
| 965 | return ngx_http_init_request(ev); |
| 966 | } |
| 967 | |
Igor Sysoev | 0ad17c0 | 2002-08-26 15:18:19 +0000 | [diff] [blame] | 968 | |
Igor Sysoev | 42feecb | 2002-12-15 06:25:09 +0000 | [diff] [blame] | 969 | static int ngx_http_set_lingering_close(ngx_http_request_t *r) |
Igor Sysoev | 1af7c82 | 2002-09-13 14:47:42 +0000 | [diff] [blame] | 970 | { |
Igor Sysoev | b738757 | 2003-03-11 20:38:13 +0000 | [diff] [blame^] | 971 | int blocked; |
| 972 | ngx_event_t *rev, *wev; |
| 973 | ngx_connection_t *c; |
Igor Sysoev | 4e9393a | 2003-01-09 05:36:00 +0000 | [diff] [blame] | 974 | ngx_http_core_loc_conf_t *lcf; |
| 975 | |
Igor Sysoev | 1e7ec9d | 2003-02-11 07:14:40 +0000 | [diff] [blame] | 976 | c = r->connection; |
Igor Sysoev | b738757 | 2003-03-11 20:38:13 +0000 | [diff] [blame^] | 977 | rev = c->read; |
| 978 | wev = c->write; |
Igor Sysoev | 9b25d69 | 2003-01-26 21:08:14 +0000 | [diff] [blame] | 979 | |
Igor Sysoev | 4e9393a | 2003-01-09 05:36:00 +0000 | [diff] [blame] | 980 | lcf = (ngx_http_core_loc_conf_t *) |
| 981 | ngx_http_get_module_loc_conf(r, ngx_http_core_module_ctx); |
| 982 | |
Igor Sysoev | b738757 | 2003-03-11 20:38:13 +0000 | [diff] [blame^] | 983 | r->lingering_time = ngx_time() + lcf->lingering_time / 1000; |
Igor Sysoev | 42feecb | 2002-12-15 06:25:09 +0000 | [diff] [blame] | 984 | r->connection->read->event_handler = ngx_http_lingering_close_handler; |
| 985 | |
Igor Sysoev | b738757 | 2003-03-11 20:38:13 +0000 | [diff] [blame^] | 986 | if (rev->timer_set) { |
| 987 | ngx_del_timer(rev); |
Igor Sysoev | 9b25d69 | 2003-01-26 21:08:14 +0000 | [diff] [blame] | 988 | } else { |
Igor Sysoev | b738757 | 2003-03-11 20:38:13 +0000 | [diff] [blame^] | 989 | rev->timer_set = 1; |
Igor Sysoev | 9b25d69 | 2003-01-26 21:08:14 +0000 | [diff] [blame] | 990 | } |
Igor Sysoev | 42feecb | 2002-12-15 06:25:09 +0000 | [diff] [blame] | 991 | |
Igor Sysoev | b738757 | 2003-03-11 20:38:13 +0000 | [diff] [blame^] | 992 | ngx_add_timer(rev, lcf->lingering_timeout); |
Igor Sysoev | 9b25d69 | 2003-01-26 21:08:14 +0000 | [diff] [blame] | 993 | |
Igor Sysoev | b738757 | 2003-03-11 20:38:13 +0000 | [diff] [blame^] | 994 | if (rev->blocked && (ngx_event_flags & NGX_USE_LEVEL_EVENT)) { |
| 995 | if (ngx_add_event(rev, NGX_READ_EVENT, NGX_LEVEL_EVENT) == NGX_ERROR) { |
| 996 | return ngx_http_close_request(r); |
| 997 | } |
| 998 | blocked = 1; |
| 999 | rev->blocked = 0; |
| 1000 | |
| 1001 | } else { |
| 1002 | blocked = 0; |
| 1003 | } |
| 1004 | |
| 1005 | if (wev->active && (ngx_event_flags & NGX_USE_LEVEL_EVENT)) { |
| 1006 | if (ngx_del_event(wev, NGX_WRITE_EVENT, 0) == NGX_ERROR) { |
| 1007 | return ngx_http_close_request(r); |
Igor Sysoev | 0d2bda5 | 2002-12-24 07:09:57 +0000 | [diff] [blame] | 1008 | } |
Igor Sysoev | 42feecb | 2002-12-15 06:25:09 +0000 | [diff] [blame] | 1009 | } |
| 1010 | |
Igor Sysoev | b738757 | 2003-03-11 20:38:13 +0000 | [diff] [blame^] | 1011 | if (ngx_shutdown_socket(c->fd, NGX_WRITE_SHUTDOWN) == -1) { |
| 1012 | ngx_log_error(NGX_LOG_CRIT, c->log, ngx_socket_errno, |
Igor Sysoev | 42feecb | 2002-12-15 06:25:09 +0000 | [diff] [blame] | 1013 | ngx_shutdown_socket_n " failed"); |
| 1014 | return ngx_http_close_request(r); |
| 1015 | } |
| 1016 | |
Igor Sysoev | 1e7ec9d | 2003-02-11 07:14:40 +0000 | [diff] [blame] | 1017 | #if (HAVE_AIO_EVENT) /* aio, iocp */ |
Igor Sysoev | b738757 | 2003-03-11 20:38:13 +0000 | [diff] [blame^] | 1018 | |
| 1019 | if ((ngx_event_flags & NGX_HAVE_AIO_EVENT) || blocked) { |
| 1020 | return ngx_http_lingering_close_handler(rev); |
Igor Sysoev | 1e7ec9d | 2003-02-11 07:14:40 +0000 | [diff] [blame] | 1021 | } |
Igor Sysoev | b738757 | 2003-03-11 20:38:13 +0000 | [diff] [blame^] | 1022 | |
| 1023 | #else |
| 1024 | |
| 1025 | if (blocked) { |
| 1026 | return ngx_http_lingering_close_handler(rev); |
| 1027 | } |
| 1028 | |
Igor Sysoev | 1e7ec9d | 2003-02-11 07:14:40 +0000 | [diff] [blame] | 1029 | #endif |
| 1030 | |
Igor Sysoev | b738757 | 2003-03-11 20:38:13 +0000 | [diff] [blame^] | 1031 | return NGX_OK; |
Igor Sysoev | 42feecb | 2002-12-15 06:25:09 +0000 | [diff] [blame] | 1032 | } |
| 1033 | |
| 1034 | |
| 1035 | static int ngx_http_lingering_close_handler(ngx_event_t *ev) |
| 1036 | { |
| 1037 | ssize_t n; |
| 1038 | ngx_msec_t timer; |
Igor Sysoev | 1af7c82 | 2002-09-13 14:47:42 +0000 | [diff] [blame] | 1039 | ngx_connection_t *c; |
| 1040 | ngx_http_request_t *r; |
Igor Sysoev | 4e9393a | 2003-01-09 05:36:00 +0000 | [diff] [blame] | 1041 | ngx_http_core_loc_conf_t *lcf; |
Igor Sysoev | 1af7c82 | 2002-09-13 14:47:42 +0000 | [diff] [blame] | 1042 | |
Igor Sysoev | 42feecb | 2002-12-15 06:25:09 +0000 | [diff] [blame] | 1043 | ngx_log_debug(ev->log, "http lingering close handler"); |
Igor Sysoev | 1af7c82 | 2002-09-13 14:47:42 +0000 | [diff] [blame] | 1044 | |
Igor Sysoev | 86de4cb | 2003-01-30 07:28:09 +0000 | [diff] [blame] | 1045 | c = (ngx_connection_t *) ev->data; |
| 1046 | r = (ngx_http_request_t *) c->data; |
| 1047 | |
Igor Sysoev | 0d2bda5 | 2002-12-24 07:09:57 +0000 | [diff] [blame] | 1048 | if (ev->timedout) { |
| 1049 | return ngx_http_close_request(r); |
| 1050 | } |
Igor Sysoev | 1af7c82 | 2002-09-13 14:47:42 +0000 | [diff] [blame] | 1051 | |
Igor Sysoev | 1af7c82 | 2002-09-13 14:47:42 +0000 | [diff] [blame] | 1052 | timer = r->lingering_time - ngx_time(); |
Igor Sysoev | 0d2bda5 | 2002-12-24 07:09:57 +0000 | [diff] [blame] | 1053 | if (timer <= 0) { |
| 1054 | return ngx_http_close_request(r); |
| 1055 | } |
Igor Sysoev | 1af7c82 | 2002-09-13 14:47:42 +0000 | [diff] [blame] | 1056 | |
Igor Sysoev | 4e9393a | 2003-01-09 05:36:00 +0000 | [diff] [blame] | 1057 | lcf = (ngx_http_core_loc_conf_t *) |
| 1058 | ngx_http_get_module_loc_conf(r, ngx_http_core_module_ctx); |
| 1059 | |
Igor Sysoev | 682bf8e | 2002-09-16 15:01:44 +0000 | [diff] [blame] | 1060 | if (r->discarded_buffer == NULL) { |
Igor Sysoev | b738757 | 2003-03-11 20:38:13 +0000 | [diff] [blame^] | 1061 | |
| 1062 | /* TODO: r->header_in->start (if large headers are enabled) |
| 1063 | or the end of parsed header (otherwise) |
| 1064 | instead of r->header_in->last */ |
| 1065 | |
| 1066 | if ((size_t)(r->header_in->end - r->header_in->last) |
Igor Sysoev | 4e9393a | 2003-01-09 05:36:00 +0000 | [diff] [blame] | 1067 | >= lcf->discarded_buffer_size) { |
Igor Sysoev | b738757 | 2003-03-11 20:38:13 +0000 | [diff] [blame^] | 1068 | r->discarded_buffer = r->header_in->last; |
Igor Sysoev | 682bf8e | 2002-09-16 15:01:44 +0000 | [diff] [blame] | 1069 | |
| 1070 | } else { |
| 1071 | ngx_test_null(r->discarded_buffer, |
Igor Sysoev | 4e9393a | 2003-01-09 05:36:00 +0000 | [diff] [blame] | 1072 | ngx_palloc(c->pool, lcf->discarded_buffer_size), |
Igor Sysoev | 0d2bda5 | 2002-12-24 07:09:57 +0000 | [diff] [blame] | 1073 | ngx_http_close_request(r)); |
Igor Sysoev | 682bf8e | 2002-09-16 15:01:44 +0000 | [diff] [blame] | 1074 | } |
| 1075 | } |
Igor Sysoev | 1af7c82 | 2002-09-13 14:47:42 +0000 | [diff] [blame] | 1076 | |
Igor Sysoev | 4e9393a | 2003-01-09 05:36:00 +0000 | [diff] [blame] | 1077 | n = ngx_event_recv(c, r->discarded_buffer, lcf->discarded_buffer_size); |
Igor Sysoev | 1af7c82 | 2002-09-13 14:47:42 +0000 | [diff] [blame] | 1078 | |
Igor Sysoev | 0d2bda5 | 2002-12-24 07:09:57 +0000 | [diff] [blame] | 1079 | ngx_log_debug(ev->log, "lingering read: %d" _ n); |
Igor Sysoev | 1af7c82 | 2002-09-13 14:47:42 +0000 | [diff] [blame] | 1080 | |
Igor Sysoev | 0d2bda5 | 2002-12-24 07:09:57 +0000 | [diff] [blame] | 1081 | if (n == NGX_ERROR || n == 0) { |
| 1082 | return ngx_http_close_request(r); |
| 1083 | } |
Igor Sysoev | 1af7c82 | 2002-09-13 14:47:42 +0000 | [diff] [blame] | 1084 | |
Igor Sysoev | 682bf8e | 2002-09-16 15:01:44 +0000 | [diff] [blame] | 1085 | timer *= 1000; |
Igor Sysoev | 4e9393a | 2003-01-09 05:36:00 +0000 | [diff] [blame] | 1086 | if (timer > lcf->lingering_timeout) { |
| 1087 | timer = lcf->lingering_timeout; |
Igor Sysoev | 0d2bda5 | 2002-12-24 07:09:57 +0000 | [diff] [blame] | 1088 | } |
Igor Sysoev | 1af7c82 | 2002-09-13 14:47:42 +0000 | [diff] [blame] | 1089 | |
Igor Sysoev | 9b25d69 | 2003-01-26 21:08:14 +0000 | [diff] [blame] | 1090 | if (ev->timer_set) { |
| 1091 | ngx_del_timer(ev); |
| 1092 | } else { |
| 1093 | ev->timer_set = 1; |
| 1094 | } |
Igor Sysoev | 682bf8e | 2002-09-16 15:01:44 +0000 | [diff] [blame] | 1095 | ngx_add_timer(ev, timer); |
Igor Sysoev | 1af7c82 | 2002-09-13 14:47:42 +0000 | [diff] [blame] | 1096 | |
| 1097 | return NGX_OK; |
| 1098 | } |
| 1099 | |
Igor Sysoev | 2b54238 | 2002-08-20 14:48:28 +0000 | [diff] [blame] | 1100 | |
Igor Sysoev | 2ba1ee0 | 2002-10-04 17:58:04 +0000 | [diff] [blame] | 1101 | static int ngx_http_close_connection(ngx_event_t *ev) |
| 1102 | { |
Igor Sysoev | 2ba1ee0 | 2002-10-04 17:58:04 +0000 | [diff] [blame] | 1103 | return ngx_event_close_connection(ev); |
| 1104 | } |
| 1105 | |
| 1106 | |
Igor Sysoev | 3d062ad | 2003-03-05 06:37:42 +0000 | [diff] [blame] | 1107 | static int ngx_http_header_parse_error(ngx_http_request_t *r, |
| 1108 | int parse_err, int err) |
| 1109 | { |
| 1110 | ngx_http_log_ctx_t *ctx; |
| 1111 | |
| 1112 | ctx = r->connection->log->data; |
| 1113 | r->connection->log->handler = NULL; |
| 1114 | |
| 1115 | if (ctx->url) { |
| 1116 | ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, |
| 1117 | header_errors[parse_err - NGX_HTTP_PARSE_INVALID_METHOD], |
| 1118 | ctx->client, ctx->url); |
| 1119 | |
| 1120 | } else { |
| 1121 | ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, |
| 1122 | header_errors[parse_err - NGX_HTTP_PARSE_INVALID_METHOD], |
| 1123 | ctx->client); |
| 1124 | } |
| 1125 | |
| 1126 | r->connection->log->handler = ngx_http_log_error; |
| 1127 | |
| 1128 | return ngx_http_error(r, err); |
| 1129 | } |
| 1130 | |
| 1131 | |
Igor Sysoev | 0ad17c0 | 2002-08-26 15:18:19 +0000 | [diff] [blame] | 1132 | static size_t ngx_http_log_error(void *data, char *buf, size_t len) |
| 1133 | { |
| 1134 | ngx_http_log_ctx_t *ctx = (ngx_http_log_ctx_t *) data; |
Igor Sysoev | a58e3ca | 2002-09-02 14:48:24 +0000 | [diff] [blame] | 1135 | |
Igor Sysoev | 0ad17c0 | 2002-08-26 15:18:19 +0000 | [diff] [blame] | 1136 | if (ctx->url) |
| 1137 | return ngx_snprintf(buf, len, " while %s, client: %s, URL: %s", |
| 1138 | ctx->action, ctx->client, ctx->url); |
| 1139 | else |
| 1140 | return ngx_snprintf(buf, len, " while %s, client: %s", |
| 1141 | ctx->action, ctx->client); |
Igor Sysoev | 6de5c2c | 2002-08-06 16:39:45 +0000 | [diff] [blame] | 1142 | } |