blob: 5783b35b4fb3098b540c8adb41665a203b790637 [file] [log] [blame]
Igor Sysoev6de5c2c2002-08-06 16:39:45 +00001
2#include <ngx_config.h>
Igor Sysoev0ad17c02002-08-26 15:18:19 +00003#include <ngx_core.h>
4#include <ngx_string.h>
Igor Sysoeva58e3ca2002-09-02 14:48:24 +00005#include <ngx_files.h>
Igor Sysoev6de5c2c2002-08-06 16:39:45 +00006#include <ngx_log.h>
7#include <ngx_alloc.h>
8#include <ngx_hunk.h>
9#include <ngx_connection.h>
Igor Sysoev6de5c2c2002-08-06 16:39:45 +000010#include <ngx_http.h>
Igor Sysoeve0268b92002-09-11 15:18:33 +000011#include <ngx_http_config.h>
Igor Sysoev6de5c2c2002-08-06 16:39:45 +000012
Igor Sysoeva58e3ca2002-09-02 14:48:24 +000013/* STUB */
14#include <ngx_http_output_filter.h>
Igor Sysoeva58e3ca2002-09-02 14:48:24 +000015int ngx_http_static_handler(ngx_http_request_t *r);
Igor Sysoeve0268b92002-09-11 15:18:33 +000016int ngx_http_index_handler(ngx_http_request_t *r);
17/* */
Igor Sysoeva58e3ca2002-09-02 14:48:24 +000018
19
Igor Sysoev0ad17c02002-08-26 15:18:19 +000020int ngx_http_init_connection(ngx_connection_t *c);
Igor Sysoev6de5c2c2002-08-06 16:39:45 +000021
Igor Sysoev6de5c2c2002-08-06 16:39:45 +000022static int ngx_http_init_request(ngx_event_t *ev);
23static int ngx_http_process_request(ngx_event_t *ev);
24
Igor Sysoev016b8522002-08-29 16:59:54 +000025static int ngx_http_process_request_line(ngx_http_request_t *r);
26static int ngx_http_process_request_header(ngx_http_request_t *r);
Igor Sysoeva58e3ca2002-09-02 14:48:24 +000027static int ngx_http_process_request_header_line(ngx_http_request_t *r);
Igor Sysoev6de5c2c2002-08-06 16:39:45 +000028
Igor Sysoeva58e3ca2002-09-02 14:48:24 +000029static int ngx_http_block_read(ngx_event_t *ev);
30static int ngx_http_read_discarded_body(ngx_event_t *ev);
31
32static int ngx_http_handler(ngx_http_request_t *r);
33static int ngx_http_set_default_handler(ngx_http_request_t *r);
34
35static int ngx_http_writer(ngx_event_t *ev);
36
37static int ngx_http_special_response(ngx_http_request_t *r, int error);
38static int ngx_http_redirect(ngx_http_request_t *r, int redirect);
39static int ngx_http_error(ngx_http_request_t *r, int error);
Igor Sysoev6de5c2c2002-08-06 16:39:45 +000040
Igor Sysoev016b8522002-08-29 16:59:54 +000041static int ngx_http_close_request(ngx_http_request_t *r);
Igor Sysoev0ad17c02002-08-26 15:18:19 +000042static size_t ngx_http_log_error(void *data, char *buf, size_t len);
43
Igor Sysoev6de5c2c2002-08-06 16:39:45 +000044
Igor Sysoev2b542382002-08-20 14:48:28 +000045/* STUB */
46static int ngx_http_writer(ngx_event_t *ev);
47
Igor Sysoev0ad17c02002-08-26 15:18:19 +000048
Igor Sysoev016b8522002-08-29 16:59:54 +000049static char *header_errors[] = {
50 "client %s sent invalid method",
51 "client %s sent invalid request",
52 "client %s sent HEAD method in HTTP/0.9 request"
53};
54
55
Igor Sysoev6de5c2c2002-08-06 16:39:45 +000056
57int ngx_http_init_connection(ngx_connection_t *c)
58{
Igor Sysoev0ad17c02002-08-26 15:18:19 +000059 ngx_event_t *ev;
60 struct sockaddr *addr;
61 ngx_http_log_ctx_t *ctx;
Igor Sysoev6de5c2c2002-08-06 16:39:45 +000062
63 ev = c->read;
Igor Sysoev6de5c2c2002-08-06 16:39:45 +000064 ev->event_handler = ngx_http_init_request;
Igor Sysoev6de5c2c2002-08-06 16:39:45 +000065
Igor Sysoev0ad17c02002-08-26 15:18:19 +000066 /* TODO: connection's pool size */
67 ngx_test_null(c->pool, ngx_create_pool(1024, ev->log), NGX_ERROR);
Igor Sysoev6de5c2c2002-08-06 16:39:45 +000068
Igor Sysoev0ad17c02002-08-26 15:18:19 +000069 ngx_test_null(addr, ngx_palloc(c->pool, c->socklen), NGX_ERROR);
70 ngx_memcpy(addr, c->sockaddr, c->socklen);
71 c->sockaddr = addr;
72
73 ngx_test_null(c->addr_text, ngx_palloc(c->pool, c->addr_textlen),
74 NGX_ERROR);
Igor Sysoeva58e3ca2002-09-02 14:48:24 +000075#if (WIN32)
76/*
77 c->addr_text = inet_ntoa((struct in_addr) ((char *)c->sockaddr + c->addr));
78*/
79 c->addr_text = NULL;
80#else
Igor Sysoev0ad17c02002-08-26 15:18:19 +000081 inet_ntop(c->family, (char *)c->sockaddr + c->addr,
82 c->addr_text, c->addr_textlen);
Igor Sysoeva58e3ca2002-09-02 14:48:24 +000083#endif
Igor Sysoev0ad17c02002-08-26 15:18:19 +000084
85 ngx_test_null(ctx, ngx_pcalloc(c->pool, sizeof(ngx_http_log_ctx_t)),
86 NGX_ERROR);
87 ctx->client = c->addr_text;
88 ctx->action = "reading client request line";
89 c->log->data = ctx;
90 c->log->handler = ngx_http_log_error;
91
Igor Sysoev6de5c2c2002-08-06 16:39:45 +000092#if (HAVE_DEFERRED_ACCEPT)
Igor Sysoev016b8522002-08-29 16:59:54 +000093 if (ev->ready) {
Igor Sysoev6de5c2c2002-08-06 16:39:45 +000094 return ngx_http_init_request(ev);
Igor Sysoev016b8522002-08-29 16:59:54 +000095 } else {
Igor Sysoev6de5c2c2002-08-06 16:39:45 +000096#endif
Igor Sysoev016b8522002-08-29 16:59:54 +000097 ngx_add_timer(ev, c->post_accept_timeout);
Igor Sysoev0ad17c02002-08-26 15:18:19 +000098#if (USE_KQUEUE)
Igor Sysoev6de5c2c2002-08-06 16:39:45 +000099 return ngx_add_event(ev, NGX_READ_EVENT, NGX_CLEAR_EVENT);
100#else
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000101#if (HAVE_AIO_EVENT)
102 if (ngx_event_type == NGX_AIO_EVENT)
103 return ngx_http_init_request(ev);
104 else
105#endif
106#if (HAVE_CLEAR_EVENT)
107 if (ngx_event_type == NGX_KQUEUE_EVENT)
108 return ngx_add_event(ev, NGX_READ_EVENT, NGX_CLEAR_EVENT);
109 else
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000110#endif
Igor Sysoev016b8522002-08-29 16:59:54 +0000111 return ngx_add_event(ev, NGX_READ_EVENT, NGX_LEVEL_EVENT);
112#endif /* USE_KQUEUE */
113#if (HAVE_DEFERRED_ACCEPT)
114 }
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000115#endif
116}
117
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000118
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000119int ngx_http_init_request(ngx_event_t *ev)
120{
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000121 ngx_connection_t *c;
122 ngx_http_server_t *srv;
123 ngx_http_request_t *r;
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000124
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000125 c = (ngx_connection_t *) ev->data;
126 srv = (ngx_http_server_t *) c->server;
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000127
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000128 ngx_test_null(r, ngx_pcalloc(c->pool, sizeof(ngx_http_request_t)),
129 NGX_ERROR);
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000130
131 c->data = r;
132 r->connection = c;
Igor Sysoev2b542382002-08-20 14:48:28 +0000133 r->server = srv;
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000134
Igor Sysoeve0268b92002-09-11 15:18:33 +0000135 r->srv_conf = ngx_srv_conf;
136 r->loc_conf = ngx_loc_conf;
137
Igor Sysoeva58e3ca2002-09-02 14:48:24 +0000138 ngx_test_null(r->pool, ngx_create_pool(srv->request_pool_size, ev->log),
Igor Sysoev016b8522002-08-29 16:59:54 +0000139 ngx_http_close_request(r));
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000140
Igor Sysoeve0268b92002-09-11 15:18:33 +0000141 ngx_test_null(r->ctx, ngx_pcalloc(r->pool, sizeof(void *) * ngx_max_module),
142 ngx_http_close_request(r));
143
Igor Sysoev016b8522002-08-29 16:59:54 +0000144 ngx_test_null(r->header_in,
Igor Sysoeva58e3ca2002-09-02 14:48:24 +0000145 ngx_create_temp_hunk(r->pool, srv->header_buffer_size, 0, 0),
Igor Sysoev016b8522002-08-29 16:59:54 +0000146 ngx_http_close_request(r));
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000147
148 ev->event_handler = ngx_http_process_request;
Igor Sysoev016b8522002-08-29 16:59:54 +0000149 r->state_handler = ngx_http_process_request_line;
Igor Sysoeva58e3ca2002-09-02 14:48:24 +0000150 r->process_header = 1;
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000151
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000152 return ngx_http_process_request(ev);
153}
154
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000155
Igor Sysoeva58e3ca2002-09-02 14:48:24 +0000156static int ngx_http_process_request(ngx_event_t *ev)
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000157{
Igor Sysoev016b8522002-08-29 16:59:54 +0000158 int n, rc;
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000159 ngx_connection_t *c ;
160 ngx_http_request_t *r;
161
162 c = (ngx_connection_t *) ev->data;
163 r = (ngx_http_request_t *) c->data;
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000164
165 ngx_log_debug(ev->log, "http process request");
166
Igor Sysoev016b8522002-08-29 16:59:54 +0000167 n = ngx_event_recv(c, r->header_in->last.mem,
168 r->header_in->end - r->header_in->last.mem);
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000169
Igor Sysoev016b8522002-08-29 16:59:54 +0000170 if (n == NGX_AGAIN) {
171 if (!r->header_timeout) {
172 r->header_timeout = 1;
173 ngx_del_timer(ev);
174 ngx_add_timer(ev, r->server->header_timeout);
175 }
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000176 return NGX_AGAIN;
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000177 }
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000178
Igor Sysoev016b8522002-08-29 16:59:54 +0000179 if (n == NGX_ERROR)
180 return ngx_http_close_request(r);
181
Igor Sysoev0c331d92002-08-15 17:20:26 +0000182 ngx_log_debug(ev->log, "http read %d" _ n);
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000183
184 if (n == 0) {
Igor Sysoeva58e3ca2002-09-02 14:48:24 +0000185 if (c->unexpected_eof)
Igor Sysoev016b8522002-08-29 16:59:54 +0000186 ngx_log_error(NGX_LOG_INFO, c->log, 0,
187 "client prematurely closed connection");
Igor Sysoev016b8522002-08-29 16:59:54 +0000188 return ngx_http_close_request(r);
189 }
190
191 r->header_in->last.mem += n;
192
193 /* state_handlers are called in following order:
194 ngx_http_process_request_line(r)
195 ngx_http_process_request_header(r) */
196
197 do {
198 rc = (r->state_handler)(r);
199
200 if (rc == NGX_ERROR)
201 return rc;
202
203 /* rc == NGX_OK || rc == NGX_AGAIN */
204
Igor Sysoeva58e3ca2002-09-02 14:48:24 +0000205 } while (r->process_header
206 && r->header_in->pos.mem < r->header_in->last.mem);
207
Igor Sysoev016b8522002-08-29 16:59:54 +0000208 if (!r->header_timeout) {
209 r->header_timeout = 1;
210 ngx_del_timer(ev);
211 ngx_add_timer(ev, r->server->header_timeout);
212 }
213
214 return rc;
215}
216
217static int ngx_http_process_request_line(ngx_http_request_t *r)
218{
219 int rc;
220 ngx_http_log_ctx_t *ctx;
221
222 rc = ngx_read_http_request_line(r);
223
224 if (rc == NGX_OK) {
225 ngx_test_null(r->uri,
226 ngx_palloc(r->pool, r->uri_end - r->uri_start + 1),
227 ngx_http_close_request(r));
228 ngx_cpystrn(r->uri, r->uri_start, r->uri_end - r->uri_start + 1);
229
230 ngx_log_debug(r->connection->log, "HTTP: %d, %d, %s" _
231 r->method _ r->http_version _ r->uri);
232
Igor Sysoeva58e3ca2002-09-02 14:48:24 +0000233 if (r->http_version == 9)
234 return ngx_http_handler(r);
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000235
Igor Sysoev016b8522002-08-29 16:59:54 +0000236 r->state_handler = ngx_http_process_request_header;
Igor Sysoeva58e3ca2002-09-02 14:48:24 +0000237 ctx = r->connection->log->data;
238 ctx->action = "reading client request headers";
Igor Sysoev016b8522002-08-29 16:59:54 +0000239
240 return NGX_OK;
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000241 }
242
Igor Sysoev016b8522002-08-29 16:59:54 +0000243 ctx = r->connection->log->data;
Igor Sysoeva58e3ca2002-09-02 14:48:24 +0000244 r->connection->log->handler = NULL;
Igor Sysoev016b8522002-08-29 16:59:54 +0000245 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
246 header_errors[rc - NGX_HTTP_INVALID_METHOD], ctx->client);
Igor Sysoev016b8522002-08-29 16:59:54 +0000247 r->connection->log->handler = ngx_http_log_error;
248
Igor Sysoeva58e3ca2002-09-02 14:48:24 +0000249 return ngx_http_error(r, NGX_HTTP_BAD_REQUEST);
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000250}
251
Igor Sysoev016b8522002-08-29 16:59:54 +0000252static int ngx_http_process_request_header(ngx_http_request_t *r)
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000253{
Igor Sysoev016b8522002-08-29 16:59:54 +0000254 int rc;
255 ngx_http_log_ctx_t *ctx;
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000256
Igor Sysoev016b8522002-08-29 16:59:54 +0000257 for ( ;; ) {
258 rc = ngx_read_http_header_line(r);
259
260 if (rc == NGX_OK) {
Igor Sysoeva58e3ca2002-09-02 14:48:24 +0000261 if (ngx_http_process_request_header_line(r) == NGX_ERROR)
262 return ngx_http_error(r, NGX_HTTP_BAD_REQUEST);
263
264 } else if (rc == NGX_HTTP_HEADER_DONE) {
265 ngx_log_debug(r->connection->log, "HTTP header done");
266 return ngx_http_handler(r);
Igor Sysoev016b8522002-08-29 16:59:54 +0000267
268 } else if (rc == NGX_AGAIN) {
269 return NGX_AGAIN;
270
Igor Sysoev016b8522002-08-29 16:59:54 +0000271 } else if (rc == NGX_HTTP_INVALID_HEADER) {
Igor Sysoev016b8522002-08-29 16:59:54 +0000272 ctx = r->connection->log->data;
Igor Sysoeva58e3ca2002-09-02 14:48:24 +0000273 r->connection->log->handler = NULL;
Igor Sysoev016b8522002-08-29 16:59:54 +0000274 ngx_log_error(NGX_LOG_INFO, r->connection->log, 0,
275 "client %s sent invalid header", ctx->client);
276 r->connection->log->handler = ngx_http_log_error;
277
Igor Sysoeva58e3ca2002-09-02 14:48:24 +0000278 return ngx_http_error(r, NGX_HTTP_BAD_REQUEST);
Igor Sysoev016b8522002-08-29 16:59:54 +0000279 }
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000280 }
Igor Sysoeva58e3ca2002-09-02 14:48:24 +0000281}
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000282
Igor Sysoeva58e3ca2002-09-02 14:48:24 +0000283static int ngx_http_process_request_header_line(ngx_http_request_t *r)
284{
285 /* STUB */
286 *r->header_name_end = '\0';
287 *r->header_end = '\0';
288 ngx_log_debug(r->connection->log, "HTTP header: '%s: %s'" _
289 r->header_name_start _ r->header_start);
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000290
Igor Sysoeva58e3ca2002-09-02 14:48:24 +0000291 return NGX_OK;
292}
293
294static int ngx_http_block_read(ngx_event_t *ev)
295{
296 ngx_log_debug(ev->log, "http read blocked");
297
298 ngx_del_event(ev, NGX_READ_EVENT);
299 ev->blocked = 1;
300}
301
302void ngx_http_discard_body(ngx_http_request_t *r)
303{
304 ngx_log_debug(r->connection->log, "set discard body");
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000305
Igor Sysoev016b8522002-08-29 16:59:54 +0000306 ngx_del_timer(r->connection->read);
307
Igor Sysoeva58e3ca2002-09-02 14:48:24 +0000308 if (r->client_content_length)
309 r->connection->read->event_handler = ngx_http_read_discarded_body;
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000310}
311
Igor Sysoeva58e3ca2002-09-02 14:48:24 +0000312static int ngx_http_read_discarded_body(ngx_event_t *ev)
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000313{
Igor Sysoeva58e3ca2002-09-02 14:48:24 +0000314 size_t size;
315 ssize_t n;
316 ngx_connection_t *c;
317 ngx_http_request_t *r;
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000318
Igor Sysoeva58e3ca2002-09-02 14:48:24 +0000319 c = (ngx_connection_t *) ev->data;
320 r = (ngx_http_request_t *) c->data;
321
322 ngx_log_debug(ev->log, "http read discarded body");
323
324 if (ev->timedout)
325 return NGX_ERROR;
326
327 if (r->discarded_buffer == NULL)
328 ngx_test_null(r->discarded_buffer,
329 ngx_palloc(r->pool, r->server->discarded_buffer_size),
330 NGX_ERROR);
331
332 size = r->client_content_length;
333 if (size > r->server->discarded_buffer_size)
334 size = r->server->discarded_buffer_size;
335
336 n = ngx_event_recv(c, r->discarded_buffer, size);
337 if (n > 0)
338 r->client_content_length -= n;
339
340 return n;
341}
342
343static int ngx_http_discarded_read(ngx_event_t *ev)
344{
345 ssize_t n;
346 ngx_connection_t *c;
347 ngx_http_request_t *r;
348
349 c = (ngx_connection_t *) ev->data;
350 r = (ngx_http_request_t *) c->data;
351
352 ngx_log_debug(ev->log, "http discarded read");
353
354 if (ev->timedout)
355 return NGX_ERROR;
356
357 if (r->discarded_buffer == NULL)
358 ngx_test_null(r->discarded_buffer,
359 ngx_palloc(r->pool, r->server->discarded_buffer_size),
360 NGX_ERROR);
361
362 n = ngx_event_recv(c, r->discarded_buffer,
363 r->server->discarded_buffer_size);
364
365 return n;
366}
367
368static int ngx_http_handler(ngx_http_request_t *r)
369{
370 int rc;
Igor Sysoev96f83772002-09-07 10:14:25 +0000371 ngx_msec_t timeout;
Igor Sysoeva58e3ca2002-09-02 14:48:24 +0000372
373 ngx_del_timer(r->connection->read);
374 r->header_timeout = 1;
375
376 r->process_header = 0;
377 r->state_handler = NULL;
378 r->connection->unexpected_eof = 0;
379
380 r->connection->read->event_handler = ngx_http_block_read;
381
382 /* STUB: should find handler */
383 r->filter = NGX_HTTP_FILTER_NEED_IN_MEMORY;
384 rc = ngx_http_set_default_handler(r);
385
386 if (rc >= NGX_HTTP_SPECIAL_RESPONSE)
387 return ngx_http_special_response(r, rc);
388
389 rc = r->handler(r);
390
391 /* transfer not completed */
392 if (rc == NGX_AGAIN) {
393#if (HAVE_CLEAR_EVENT)
394 if (ngx_add_event(r->connection->write, NGX_WRITE_EVENT,
395 NGX_CLEAR_EVENT) == NGX_ERROR) {
396#else
397 if (ngx_add_event(r->connection->write, NGX_WRITE_EVENT,
398 NGX_ONESHOT_EVENT) == NGX_ERROR) {
399#endif
400 /* log http request */
401 return ngx_http_close_request(r);
402 }
403
Igor Sysoev96f83772002-09-07 10:14:25 +0000404 if (r->connection->sent > 0) {
405 ngx_log_debug(r->connection->log, "sent: " QD_FMT _
406 r->connection->sent);
407 timeout = (ngx_msec_t) (r->connection->sent * 10);
408 ngx_log_debug(r->connection->log, "timeout: %d" _ timeout);
409 ngx_add_timer(r->connection->write, timeout);
410
411 } else {
412 ngx_add_timer(r->connection->write, 10000);
413 }
Igor Sysoeva58e3ca2002-09-02 14:48:24 +0000414
415 r->connection->write->event_handler = ngx_http_writer;
416 return rc;
417 }
418
419 if (rc == NGX_ERROR) {
420 /* log http request */
421 return ngx_http_close_request(r);
422 }
423
424 if (rc >= NGX_HTTP_SPECIAL_RESPONSE)
425 return ngx_http_special_response(r, rc);
426
427 /* rc == NGX_OK */
428
429 /* STUB */
430 return ngx_http_close_request(r);
431
432/*
433 if (!keepalive)
434 if (linger)
435 set linger timeout on read
436 shutdown socket
437 else
438 close socket
439*/
440}
441
Igor Sysoeve0268b92002-09-11 15:18:33 +0000442int ngx_http_internal_redirect(ngx_http_request_t *r, char *uri)
443{
444 ngx_log_debug(r->connection->log, "internal redirect: '%s'" _ uri);
445
446 r->uri = uri;
447 r->uri_start = uri;
448 r->uri_end = uri + strlen(uri);
449 return ngx_http_handler(r);
450}
451
Igor Sysoeva58e3ca2002-09-02 14:48:24 +0000452static int ngx_http_set_default_handler(ngx_http_request_t *r)
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000453{
Igor Sysoev2b542382002-08-20 14:48:28 +0000454 int err, rc;
Igor Sysoeve0af1b82002-08-16 15:27:03 +0000455 char *name, *loc, *file;
456
Igor Sysoev2b542382002-08-20 14:48:28 +0000457 ngx_test_null(r->headers_out,
458 ngx_pcalloc(r->pool, sizeof(ngx_http_headers_out_t)),
Igor Sysoeva58e3ca2002-09-02 14:48:24 +0000459 NGX_HTTP_INTERNAL_SERVER_ERROR);
Igor Sysoev2b542382002-08-20 14:48:28 +0000460
Igor Sysoeve0af1b82002-08-16 15:27:03 +0000461 if (*(r->uri_end - 1) == '/') {
Igor Sysoeva58e3ca2002-09-02 14:48:24 +0000462 r->handler = ngx_http_index_handler;
Igor Sysoeve0af1b82002-08-16 15:27:03 +0000463 return NGX_OK;
464 }
465
466 /* 20 bytes is spare space for some index name, i.e. index.html */
467 r->filename_len = r->uri_end - r->uri_start + r->server->doc_root_len + 20;
468
469 ngx_test_null(r->filename,
470 ngx_palloc(r->pool, r->filename_len),
Igor Sysoeva58e3ca2002-09-02 14:48:24 +0000471 NGX_HTTP_INTERNAL_SERVER_ERROR);
Igor Sysoeve0af1b82002-08-16 15:27:03 +0000472
473 r->location = ngx_cpystrn(r->filename, r->server->doc_root,
474 r->server->doc_root_len);
475 file = ngx_cpystrn(r->location, r->uri_start,
476 r->uri_end - r->uri_start + 1);
477
478 ngx_log_debug(r->connection->log, "HTTP filename: '%s'" _ r->filename);
479
Igor Sysoeva58e3ca2002-09-02 14:48:24 +0000480 if (ngx_file_type(r->filename, &r->fileinfo) == -1) {
Igor Sysoeve0af1b82002-08-16 15:27:03 +0000481 err = ngx_errno;
Igor Sysoev2b542382002-08-20 14:48:28 +0000482 ngx_log_error(NGX_LOG_ERR, r->connection->log, err,
Igor Sysoev2b542382002-08-20 14:48:28 +0000483 ngx_file_type_n " %s failed", r->filename);
Igor Sysoeve0af1b82002-08-16 15:27:03 +0000484
485 if (err == NGX_ENOENT)
Igor Sysoeva58e3ca2002-09-02 14:48:24 +0000486 return NGX_HTTP_NOT_FOUND;
Igor Sysoeve0af1b82002-08-16 15:27:03 +0000487 else
Igor Sysoeva58e3ca2002-09-02 14:48:24 +0000488 return NGX_HTTP_INTERNAL_SERVER_ERROR;
Igor Sysoeve0af1b82002-08-16 15:27:03 +0000489 }
490
Igor Sysoeva58e3ca2002-09-02 14:48:24 +0000491 if (ngx_is_dir(r->fileinfo)) {
Igor Sysoev2b542382002-08-20 14:48:28 +0000492 ngx_log_debug(r->connection->log, "HTTP DIR: '%s'" _ r->filename);
Igor Sysoeve0af1b82002-08-16 15:27:03 +0000493 *file++ = '/';
494 *file = '\0';
495 r->headers_out->location = r->location;
Igor Sysoeva58e3ca2002-09-02 14:48:24 +0000496 return NGX_HTTP_MOVED_PERMANENTLY;
Igor Sysoeve0af1b82002-08-16 15:27:03 +0000497 }
498
Igor Sysoeva58e3ca2002-09-02 14:48:24 +0000499 r->handler = ngx_http_static_handler;
Igor Sysoev2b542382002-08-20 14:48:28 +0000500
Igor Sysoeve0af1b82002-08-16 15:27:03 +0000501 return NGX_OK;
502}
503
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000504
505static int ngx_http_writer(ngx_event_t *ev)
506{
507 int rc;
Igor Sysoeva58e3ca2002-09-02 14:48:24 +0000508 unsigned int timeout;
509 ngx_connection_t *c;
510 ngx_http_request_t *r;
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000511
Igor Sysoeva58e3ca2002-09-02 14:48:24 +0000512 c = (ngx_connection_t *) ev->data;
513 r = (ngx_http_request_t *) c->data;
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000514
Igor Sysoev96f83772002-09-07 10:14:25 +0000515 c->sent = 0;
516
Igor Sysoeva58e3ca2002-09-02 14:48:24 +0000517 rc = ngx_http_output_filter(r, NULL);
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000518
Igor Sysoeva58e3ca2002-09-02 14:48:24 +0000519 ngx_log_debug(ev->log, "output_filter: %d" _ rc);
520
521 if (rc == NGX_AGAIN) {
522
523 if (c->sent > 0) {
524 ngx_log_debug(ev->log, "sent: " QD_FMT _ c->sent);
525 timeout = (ngx_msec_t) (c->sent * 10);
526 ngx_log_debug(ev->log, "timeout: %d" _ timeout);
527 ngx_del_timer(ev);
528 ngx_add_timer(ev, timeout);
529 }
530
531 if (ev->oneshot)
532 if (ngx_add_event(r->connection->write, NGX_WRITE_EVENT,
533 NGX_ONESHOT_EVENT) == NGX_ERROR) {
534 /* log http request */
535 return ngx_http_close_request(r);
536 }
537
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000538 return rc;
Igor Sysoeva58e3ca2002-09-02 14:48:24 +0000539 }
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000540
541 if (rc == NGX_ERROR)
542 return rc;
543
544 /* rc == NGX_OK */
545
Igor Sysoeva58e3ca2002-09-02 14:48:24 +0000546 return ngx_http_close_request(r);
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000547
Igor Sysoeva58e3ca2002-09-02 14:48:24 +0000548/*
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000549 if (!keepalive)
550 if (linger)
551 shutdown socket
552 else
553 close socket
554
555 log http request
556 close http request
557 if (keepalive)
558 return NGX_OK;
559 else
560 close connection
561 return NGX_OK;
Igor Sysoeva58e3ca2002-09-02 14:48:24 +0000562*/
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000563}
564
Igor Sysoeva58e3ca2002-09-02 14:48:24 +0000565#if 0
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000566
567static int ngx_http_keepalive_handler(ngx_event_t *ev)
568{
569 ngx_connection_t *c;
570 ngx_http_log_ctx_t *ctx;
571
572 if (closed)
573 /* NGX_LOG_INFO or even silent */
574 return NGX_ERROR;
575
576 c = (ngx_connection_t *) ev->data;
577
578 ctx = (ngx_http_log_ctx_t *) c->log->data;
579 ctx->action = "reading client request line";
580 c->log->handler = ngx_http_log_error;
581
582 return ngx_http_init_request(ev);
583}
584
585#endif
586
Igor Sysoev2b542382002-08-20 14:48:28 +0000587
Igor Sysoeva58e3ca2002-09-02 14:48:24 +0000588static int ngx_http_special_response(ngx_http_request_t *r, int error)
Igor Sysoev2b542382002-08-20 14:48:28 +0000589{
Igor Sysoeva58e3ca2002-09-02 14:48:24 +0000590 return ngx_http_error(r, error);
Igor Sysoeve0af1b82002-08-16 15:27:03 +0000591}
Igor Sysoeve0af1b82002-08-16 15:27:03 +0000592
593static int ngx_http_redirect(ngx_http_request_t *r, int redirect)
594{
595 /* STUB */
Igor Sysoeva58e3ca2002-09-02 14:48:24 +0000596
597 /* log request */
598
599 return ngx_http_close_request(r);
Igor Sysoeve0af1b82002-08-16 15:27:03 +0000600}
601
602static int ngx_http_error(ngx_http_request_t *r, int error)
603{
604 /* STUB */
Igor Sysoeva58e3ca2002-09-02 14:48:24 +0000605 ngx_log_debug(r->connection->log, "http error: %d" _ error);
606
607 /* log request */
608
609 return ngx_http_close_request(r);
Igor Sysoev0c331d92002-08-15 17:20:26 +0000610}
611
612#if 0
613
614static int ngx_process_http_request(ngx_http_request_t *r)
615{
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000616 int fd;
617 struct stat sb;
618 ngx_http_header_out_t *header_out;
619 ngx_chunk_t *header, *ch;
620
621 int index = (*(r->uri_end - 1) == '/') ? sizeof(NGX_INDEX) : 1;
622 char *name = ngx_palloc(r->pool,
623 r->uri_end - r->uri_start + strlen(ngx_root) + index);
624 strcpy(name, ngx_root);
625 strcat(name, r->uri_start);
626 if (*(r->uri_end - 1) == '/')
627 strcat(name, NGX_INDEX);
628
629 ngx_log_debug(r->connection->log, "HTTP URI: '%s'", name);
630
631 if ((fd = open(name, O_RDONLY)) == -1) {
632 ngx_log_error(NGX_LOG_ERR, r->connection->log, errno,
633 "open %s failed", name);
634 return -1;
635 }
636
637 if (fstat(fd, &sb) == -1) {
638 ngx_log_error(NGX_LOG_ERR, r->connection->log, errno,
639 "fstat %s failed", name);
640 return -1;
641 }
642
643 header_out = ngx_palloc(r->pool, sizeof(ngx_http_header_out_t));
644
645 header_out->status = NGX_HTTP_OK;
646 header_out->content_length = sb.st_size;
647 header_out->last_modified = sb.st_mtime;
648 header_out->content_type = "text/html";
649 header_out->charset = "koi8-r";
650 header_out->date = time(NULL);
651 header_out->connection = NGX_HTTP_CONN_CLOSE;
652
653/*
654 header_out->connection = NGX_HTTP_CONN_KEEP_ALIVE;
655 r->connection->read->event_handler = ngx_http_init_request;
656*/
657
658 header = ngx_http_header(r, header_out);
659 ch = ngx_palloc(r->pool, sizeof(ngx_chunk_t));
660 ch->ident = fd;
661 ch->offset = 0;
662 ch->size = sb.st_size;
663 ch->next = NULL;
664 header->next = ch;
665
666 ngx_event_write(r->connection, header);
667
668 return 0;
669}
670
Igor Sysoev0c331d92002-08-15 17:20:26 +0000671#endif
672
Igor Sysoev016b8522002-08-29 16:59:54 +0000673static int ngx_http_close_request(ngx_http_request_t *r)
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000674{
Igor Sysoev016b8522002-08-29 16:59:54 +0000675 ngx_destroy_pool(r->pool);
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000676
Igor Sysoev016b8522002-08-29 16:59:54 +0000677 ngx_log_debug(r->connection->log, "http close");
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000678
Igor Sysoeva58e3ca2002-09-02 14:48:24 +0000679 ngx_del_timer(r->connection->read);
680 ngx_del_timer(r->connection->write);
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000681
Igor Sysoev016b8522002-08-29 16:59:54 +0000682 return NGX_ERROR;
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000683}
684
685
686static size_t ngx_http_log_error(void *data, char *buf, size_t len)
687{
688 ngx_http_log_ctx_t *ctx = (ngx_http_log_ctx_t *) data;
Igor Sysoeva58e3ca2002-09-02 14:48:24 +0000689
Igor Sysoev0ad17c02002-08-26 15:18:19 +0000690 if (ctx->url)
691 return ngx_snprintf(buf, len, " while %s, client: %s, URL: %s",
692 ctx->action, ctx->client, ctx->url);
693 else
694 return ngx_snprintf(buf, len, " while %s, client: %s",
695 ctx->action, ctx->client);
Igor Sysoev6de5c2c2002-08-06 16:39:45 +0000696}