[core] remove some unused header includes
[lighttpd.git] / src / response.c
blobe77926d7f4026f0f389996279b6b7d58b8cb0016
1 #include "first.h"
3 #include "response.h"
4 #include "keyvalue.h"
5 #include "log.h"
6 #include "stat_cache.h"
7 #include "chunk.h"
9 #include "configfile.h"
11 #include "plugin.h"
13 #include <sys/types.h>
14 #include <sys/stat.h>
16 #include <limits.h>
17 #include <errno.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include <time.h>
21 #include <unistd.h>
23 #include "sys-socket.h"
25 int http_response_write_header(server *srv, connection *con) {
26 buffer *b;
27 size_t i;
28 int have_date = 0;
29 int have_server = 0;
31 b = buffer_init();
33 if (con->request.http_version == HTTP_VERSION_1_1) {
34 buffer_copy_string_len(b, CONST_STR_LEN("HTTP/1.1 "));
35 } else {
36 buffer_copy_string_len(b, CONST_STR_LEN("HTTP/1.0 "));
38 buffer_append_int(b, con->http_status);
39 buffer_append_string_len(b, CONST_STR_LEN(" "));
40 buffer_append_string(b, get_http_status_name(con->http_status));
42 /* disable keep-alive if requested */
43 if (con->request_count > con->conf.max_keep_alive_requests || 0 == con->conf.max_keep_alive_idle) {
44 con->keep_alive = 0;
45 } else {
46 con->keep_alive_idle = con->conf.max_keep_alive_idle;
49 if (con->request.http_version != HTTP_VERSION_1_1 || con->keep_alive == 0) {
50 if (con->keep_alive) {
51 response_header_overwrite(srv, con, CONST_STR_LEN("Connection"), CONST_STR_LEN("keep-alive"));
52 } else {
53 response_header_overwrite(srv, con, CONST_STR_LEN("Connection"), CONST_STR_LEN("close"));
57 /* add all headers */
58 for (i = 0; i < con->response.headers->used; i++) {
59 data_string *ds;
61 ds = (data_string *)con->response.headers->data[i];
63 if (buffer_string_is_empty(ds->value) || buffer_string_is_empty(ds->key)) continue;
64 if (0 == strncasecmp(ds->key->ptr, CONST_STR_LEN("X-Sendfile"))) continue;
65 if (0 == strncasecmp(ds->key->ptr, CONST_STR_LEN("X-LIGHTTPD-"))) {
66 if (0 == strncasecmp(ds->key->ptr+sizeof("X-LIGHTTPD-")-1, CONST_STR_LEN("KBytes-per-second"))) {
67 /* "X-LIGHTTPD-KBytes-per-second" */
68 long limit = strtol(ds->value->ptr, NULL, 10);
69 if (limit > 0
70 && (limit < con->conf.kbytes_per_second
71 || 0 == con->conf.kbytes_per_second)) {
72 if (limit > USHRT_MAX) limit= USHRT_MAX;
73 con->conf.kbytes_per_second = limit;
76 continue;
77 } else {
78 if (0 == strcasecmp(ds->key->ptr, "Date")) have_date = 1;
79 if (0 == strcasecmp(ds->key->ptr, "Server")) have_server = 1;
80 if (0 == strcasecmp(ds->key->ptr, "Content-Encoding") && 304 == con->http_status) continue;
82 buffer_append_string_len(b, CONST_STR_LEN("\r\n"));
83 buffer_append_string_buffer(b, ds->key);
84 buffer_append_string_len(b, CONST_STR_LEN(": "));
85 #if 0
86 /**
87 * the value might contain newlines, encode them with at least one white-space
89 buffer_append_string_encoded(b, CONST_BUF_LEN(ds->value), ENCODING_HTTP_HEADER);
90 #else
91 buffer_append_string_buffer(b, ds->value);
92 #endif
96 if (!have_date) {
97 /* HTTP/1.1 requires a Date: header */
98 buffer_append_string_len(b, CONST_STR_LEN("\r\nDate: "));
100 /* cache the generated timestamp */
101 if (srv->cur_ts != srv->last_generated_date_ts) {
102 buffer_string_prepare_copy(srv->ts_date_str, 255);
104 buffer_append_strftime(srv->ts_date_str, "%a, %d %b %Y %H:%M:%S GMT", gmtime(&(srv->cur_ts)));
106 srv->last_generated_date_ts = srv->cur_ts;
109 buffer_append_string_buffer(b, srv->ts_date_str);
112 if (!have_server) {
113 if (!buffer_string_is_empty(con->conf.server_tag)) {
114 buffer_append_string_len(b, CONST_STR_LEN("\r\nServer: "));
115 buffer_append_string_encoded(b, CONST_BUF_LEN(con->conf.server_tag), ENCODING_HTTP_HEADER);
119 buffer_append_string_len(b, CONST_STR_LEN("\r\n\r\n"));
121 con->bytes_header = buffer_string_length(b);
123 if (con->conf.log_response_header) {
124 log_error_write(srv, __FILE__, __LINE__, "sSb", "Response-Header:", "\n", b);
127 chunkqueue_prepend_buffer(con->write_queue, b);
128 buffer_free(b);
130 return 0;
133 handler_t http_response_prepare(server *srv, connection *con) {
134 handler_t r;
136 /* looks like someone has already done a decision */
137 if (con->mode == DIRECT &&
138 (con->http_status != 0 && con->http_status != 200)) {
139 /* remove a packets in the queue */
140 if (con->file_finished == 0) {
141 chunkqueue_reset(con->write_queue);
144 return HANDLER_FINISHED;
147 /* no decision yet, build conf->filename */
148 if (con->mode == DIRECT && buffer_is_empty(con->physical.path)) {
149 char *qstr;
151 /* we only come here when we have the parse the full request again
153 * a HANDLER_COMEBACK from mod_rewrite and mod_fastcgi might be a
154 * problem here as mod_setenv might get called multiple times
156 * fastcgi-auth might lead to a COMEBACK too
157 * fastcgi again dead server too
159 * mod_compress might add headers twice too
161 * */
163 config_cond_cache_reset(srv, con);
164 config_setup_connection(srv, con); /* Perhaps this could be removed at other places. */
166 if (con->conf.log_condition_handling) {
167 log_error_write(srv, __FILE__, __LINE__, "s", "run condition");
171 * prepare strings
173 * - uri.path_raw
174 * - uri.path (secure)
175 * - uri.query
180 * Name according to RFC 2396
182 * - scheme
183 * - authority
184 * - path
185 * - query
187 * (scheme)://(authority)(path)?(query)#fragment
192 /* initial scheme value. can be overwritten for example by mod_extforward later */
193 if (con->srv_socket->is_ssl) {
194 buffer_copy_string_len(con->uri.scheme, CONST_STR_LEN("https"));
195 } else {
196 buffer_copy_string_len(con->uri.scheme, CONST_STR_LEN("http"));
198 buffer_copy_buffer(con->uri.authority, con->request.http_host);
199 buffer_to_lower(con->uri.authority);
201 /** their might be a fragment which has to be cut away */
202 if (NULL != (qstr = strchr(con->request.uri->ptr, '#'))) {
203 buffer_string_set_length(con->request.uri, qstr - con->request.uri->ptr);
206 /** extract query string from request.uri */
207 if (NULL != (qstr = strchr(con->request.uri->ptr, '?'))) {
208 buffer_copy_string (con->uri.query, qstr + 1);
209 buffer_copy_string_len(con->uri.path_raw, con->request.uri->ptr, qstr - con->request.uri->ptr);
210 } else {
211 buffer_reset (con->uri.query);
212 buffer_copy_buffer(con->uri.path_raw, con->request.uri);
215 /* decode url to path
217 * - decode url-encodings (e.g. %20 -> ' ')
218 * - remove path-modifiers (e.g. /../)
221 if (con->request.http_method == HTTP_METHOD_OPTIONS &&
222 con->uri.path_raw->ptr[0] == '*' && con->uri.path_raw->ptr[1] == '\0') {
223 /* OPTIONS * ... */
224 buffer_copy_buffer(con->uri.path, con->uri.path_raw);
225 } else {
226 buffer_copy_buffer(srv->tmp_buf, con->uri.path_raw);
227 buffer_urldecode_path(srv->tmp_buf);
228 buffer_path_simplify(con->uri.path, srv->tmp_buf);
231 con->conditional_is_valid[COMP_SERVER_SOCKET] = 1; /* SERVERsocket */
232 con->conditional_is_valid[COMP_HTTP_SCHEME] = 1; /* Scheme: */
233 con->conditional_is_valid[COMP_HTTP_HOST] = 1; /* Host: */
234 con->conditional_is_valid[COMP_HTTP_REMOTE_IP] = 1; /* Client-IP */
235 con->conditional_is_valid[COMP_HTTP_REQUEST_METHOD] = 1; /* REQUEST_METHOD */
236 con->conditional_is_valid[COMP_HTTP_URL] = 1; /* HTTPurl */
237 con->conditional_is_valid[COMP_HTTP_QUERY_STRING] = 1; /* HTTPqs */
238 con->conditional_is_valid[COMP_HTTP_REQUEST_HEADER] = 1; /* HTTP request header */
239 config_patch_connection(srv, con);
241 /* do we have to downgrade to 1.0 ? */
242 if (!con->conf.allow_http11) {
243 con->request.http_version = HTTP_VERSION_1_0;
246 if (con->conf.log_request_handling) {
247 log_error_write(srv, __FILE__, __LINE__, "s", "-- splitting Request-URI");
248 log_error_write(srv, __FILE__, __LINE__, "sb", "Request-URI : ", con->request.uri);
249 log_error_write(srv, __FILE__, __LINE__, "sb", "URI-scheme : ", con->uri.scheme);
250 log_error_write(srv, __FILE__, __LINE__, "sb", "URI-authority : ", con->uri.authority);
251 log_error_write(srv, __FILE__, __LINE__, "sb", "URI-path (raw) : ", con->uri.path_raw);
252 log_error_write(srv, __FILE__, __LINE__, "sb", "URI-path (clean): ", con->uri.path);
253 log_error_write(srv, __FILE__, __LINE__, "sb", "URI-query : ", con->uri.query);
256 /* con->conf.max_request_size is in kBytes */
257 if (0 != con->conf.max_request_size &&
258 (off_t)con->request.content_length > ((off_t)con->conf.max_request_size << 10)) {
259 log_error_write(srv, __FILE__, __LINE__, "sos",
260 "request-size too long:", (off_t) con->request.content_length, "-> 413");
261 con->keep_alive = 0;
262 con->http_status = 413;
263 con->file_finished = 1;
265 return HANDLER_FINISHED;
271 * call plugins
273 * - based on the raw URL
277 switch(r = plugins_call_handle_uri_raw(srv, con)) {
278 case HANDLER_GO_ON:
279 break;
280 case HANDLER_FINISHED:
281 case HANDLER_COMEBACK:
282 case HANDLER_WAIT_FOR_EVENT:
283 case HANDLER_ERROR:
284 return r;
285 default:
286 log_error_write(srv, __FILE__, __LINE__, "sd", "handle_uri_raw: unknown return value", r);
287 break;
292 * call plugins
294 * - based on the clean URL
298 switch(r = plugins_call_handle_uri_clean(srv, con)) {
299 case HANDLER_GO_ON:
300 break;
301 case HANDLER_FINISHED:
302 case HANDLER_COMEBACK:
303 case HANDLER_WAIT_FOR_EVENT:
304 case HANDLER_ERROR:
305 return r;
306 default:
307 log_error_write(srv, __FILE__, __LINE__, "");
308 break;
311 if (con->request.http_method == HTTP_METHOD_OPTIONS &&
312 con->uri.path->ptr[0] == '*' && con->uri.path_raw->ptr[1] == '\0') {
313 /* option requests are handled directly without checking of the path */
315 response_header_insert(srv, con, CONST_STR_LEN("Allow"), CONST_STR_LEN("OPTIONS, GET, HEAD, POST"));
317 con->http_status = 200;
318 con->file_finished = 1;
320 return HANDLER_FINISHED;
323 /***
325 * border
327 * logical filename (URI) becomes a physical filename here
336 /* 1. stat()
337 * ... ISREG() -> ok, go on
338 * ... ISDIR() -> index-file -> redirect
340 * 2. pathinfo()
341 * ... ISREG()
343 * 3. -> 404
348 * SEARCH DOCUMENT ROOT
351 /* set a default */
353 buffer_copy_buffer(con->physical.doc_root, con->conf.document_root);
354 buffer_copy_buffer(con->physical.rel_path, con->uri.path);
356 #if defined(__WIN32) || defined(__CYGWIN__)
357 /* strip dots from the end and spaces
359 * windows/dos handle those filenames as the same file
361 * foo == foo. == foo..... == "foo... " == "foo.. ./"
363 * This will affect in some cases PATHINFO
365 * on native windows we could prepend the filename with \\?\ to circumvent
366 * this behaviour. I have no idea how to push this through cygwin
368 * */
370 if (con->physical.rel_path->used > 1) {
371 buffer *b = con->physical.rel_path;
372 size_t len = buffer_string_length(b);
374 /* strip trailing " /" or "./" once */
375 if (len > 1 &&
376 b->ptr[len - 1] == '/' &&
377 (b->ptr[len - 2] == ' ' || b->ptr[len - 2] == '.')) {
378 len -= 2;
380 /* strip all trailing " " and "." */
381 while (len > 0 && ( ' ' == b->ptr[len-1] || '.' == b->ptr[len-1] ) ) --len;
382 buffer_string_set_length(b, len);
384 #endif
386 if (con->conf.log_request_handling) {
387 log_error_write(srv, __FILE__, __LINE__, "s", "-- before doc_root");
388 log_error_write(srv, __FILE__, __LINE__, "sb", "Doc-Root :", con->physical.doc_root);
389 log_error_write(srv, __FILE__, __LINE__, "sb", "Rel-Path :", con->physical.rel_path);
390 log_error_write(srv, __FILE__, __LINE__, "sb", "Path :", con->physical.path);
392 /* the docroot plugin should set the doc_root and might also set the physical.path
393 * for us (all vhost-plugins are supposed to set the doc_root)
394 * */
395 switch(r = plugins_call_handle_docroot(srv, con)) {
396 case HANDLER_GO_ON:
397 break;
398 case HANDLER_FINISHED:
399 case HANDLER_COMEBACK:
400 case HANDLER_WAIT_FOR_EVENT:
401 case HANDLER_ERROR:
402 return r;
403 default:
404 log_error_write(srv, __FILE__, __LINE__, "");
405 break;
408 /* MacOS X and Windows can't distiguish between upper and lower-case
410 * convert to lower-case
412 if (con->conf.force_lowercase_filenames) {
413 buffer_to_lower(con->physical.rel_path);
416 /* the docroot plugins might set the servername, if they don't we take http-host */
417 if (buffer_string_is_empty(con->server_name)) {
418 buffer_copy_buffer(con->server_name, con->uri.authority);
422 * create physical filename
423 * -> physical.path = docroot + rel_path
427 buffer_copy_buffer(con->physical.basedir, con->physical.doc_root);
428 buffer_copy_buffer(con->physical.path, con->physical.doc_root);
429 buffer_append_slash(con->physical.path);
430 if (!buffer_string_is_empty(con->physical.rel_path) &&
431 con->physical.rel_path->ptr[0] == '/') {
432 /* coverity[overflow_sink : FALSE] */
433 buffer_append_string_len(con->physical.path, con->physical.rel_path->ptr + 1, buffer_string_length(con->physical.rel_path) - 1);
434 } else {
435 buffer_append_string_buffer(con->physical.path, con->physical.rel_path);
438 if (con->conf.log_request_handling) {
439 log_error_write(srv, __FILE__, __LINE__, "s", "-- after doc_root");
440 log_error_write(srv, __FILE__, __LINE__, "sb", "Doc-Root :", con->physical.doc_root);
441 log_error_write(srv, __FILE__, __LINE__, "sb", "Rel-Path :", con->physical.rel_path);
442 log_error_write(srv, __FILE__, __LINE__, "sb", "Path :", con->physical.path);
445 switch(r = plugins_call_handle_physical(srv, con)) {
446 case HANDLER_GO_ON:
447 break;
448 case HANDLER_FINISHED:
449 case HANDLER_COMEBACK:
450 case HANDLER_WAIT_FOR_EVENT:
451 case HANDLER_ERROR:
452 return r;
453 default:
454 log_error_write(srv, __FILE__, __LINE__, "");
455 break;
458 if (con->conf.log_request_handling) {
459 log_error_write(srv, __FILE__, __LINE__, "s", "-- logical -> physical");
460 log_error_write(srv, __FILE__, __LINE__, "sb", "Doc-Root :", con->physical.doc_root);
461 log_error_write(srv, __FILE__, __LINE__, "sb", "Basedir :", con->physical.basedir);
462 log_error_write(srv, __FILE__, __LINE__, "sb", "Rel-Path :", con->physical.rel_path);
463 log_error_write(srv, __FILE__, __LINE__, "sb", "Path :", con->physical.path);
468 * Noone catched away the file from normal path of execution yet (like mod_access)
470 * Go on and check of the file exists at all
473 if (con->mode == DIRECT) {
474 char *slash = NULL;
475 char *pathinfo = NULL;
476 int found = 0;
477 stat_cache_entry *sce = NULL;
479 if (con->conf.log_request_handling) {
480 log_error_write(srv, __FILE__, __LINE__, "s", "-- handling physical path");
481 log_error_write(srv, __FILE__, __LINE__, "sb", "Path :", con->physical.path);
484 if (HANDLER_ERROR != stat_cache_get_entry(srv, con, con->physical.path, &sce)) {
485 /* file exists */
487 if (con->conf.log_request_handling) {
488 log_error_write(srv, __FILE__, __LINE__, "s", "-- file found");
489 log_error_write(srv, __FILE__, __LINE__, "sb", "Path :", con->physical.path);
491 #ifdef HAVE_LSTAT
492 if ((sce->is_symlink != 0) && !con->conf.follow_symlink) {
493 con->http_status = 403;
495 if (con->conf.log_request_handling) {
496 log_error_write(srv, __FILE__, __LINE__, "s", "-- access denied due symlink restriction");
497 log_error_write(srv, __FILE__, __LINE__, "sb", "Path :", con->physical.path);
500 buffer_reset(con->physical.path);
501 return HANDLER_FINISHED;
503 #endif
504 if (S_ISDIR(sce->st.st_mode)) {
505 if (con->uri.path->ptr[buffer_string_length(con->uri.path) - 1] != '/') {
506 /* redirect to .../ */
508 http_response_redirect_to_directory(srv, con);
510 return HANDLER_FINISHED;
512 #ifdef HAVE_LSTAT
513 } else if (!S_ISREG(sce->st.st_mode) && !sce->is_symlink) {
514 #else
515 } else if (!S_ISREG(sce->st.st_mode)) {
516 #endif
517 /* any special handling of non-reg files ?*/
521 } else {
522 switch (errno) {
523 case EACCES:
524 con->http_status = 403;
526 if (con->conf.log_request_handling) {
527 log_error_write(srv, __FILE__, __LINE__, "s", "-- access denied");
528 log_error_write(srv, __FILE__, __LINE__, "sb", "Path :", con->physical.path);
531 buffer_reset(con->physical.path);
532 return HANDLER_FINISHED;
533 case ENAMETOOLONG:
534 /* file name to be read was too long. return 404 */
535 case ENOENT:
536 con->http_status = 404;
538 if (con->conf.log_request_handling) {
539 log_error_write(srv, __FILE__, __LINE__, "s", "-- file not found");
540 log_error_write(srv, __FILE__, __LINE__, "sb", "Path :", con->physical.path);
543 buffer_reset(con->physical.path);
544 return HANDLER_FINISHED;
545 case ENOTDIR:
546 /* PATH_INFO ! :) */
547 break;
548 default:
549 /* we have no idea what happend. let's tell the user so. */
550 con->http_status = 500;
551 buffer_reset(con->physical.path);
553 log_error_write(srv, __FILE__, __LINE__, "ssbsb",
554 "file not found ... or so: ", strerror(errno),
555 con->uri.path,
556 "->", con->physical.path);
558 return HANDLER_FINISHED;
561 /* not found, perhaps PATHINFO */
563 buffer_copy_buffer(srv->tmp_buf, con->physical.path);
565 do {
566 if (slash) {
567 buffer_copy_string_len(con->physical.path, srv->tmp_buf->ptr, slash - srv->tmp_buf->ptr);
568 } else {
569 buffer_copy_buffer(con->physical.path, srv->tmp_buf);
572 if (HANDLER_ERROR != stat_cache_get_entry(srv, con, con->physical.path, &sce)) {
573 found = S_ISREG(sce->st.st_mode);
574 break;
577 if (pathinfo != NULL) {
578 *pathinfo = '\0';
580 slash = strrchr(srv->tmp_buf->ptr, '/');
582 if (pathinfo != NULL) {
583 /* restore '/' */
584 *pathinfo = '/';
587 if (slash) pathinfo = slash;
588 } while ((found == 0) && (slash != NULL) && ((size_t)(slash - srv->tmp_buf->ptr) > (buffer_string_length(con->physical.basedir) - 1)));
590 if (found == 0) {
591 /* no it really doesn't exists */
592 con->http_status = 404;
594 if (con->conf.log_file_not_found) {
595 log_error_write(srv, __FILE__, __LINE__, "sbsb",
596 "file not found:", con->uri.path,
597 "->", con->physical.path);
600 buffer_reset(con->physical.path);
602 return HANDLER_FINISHED;
605 #ifdef HAVE_LSTAT
606 if ((sce->is_symlink != 0) && !con->conf.follow_symlink) {
607 con->http_status = 403;
609 if (con->conf.log_request_handling) {
610 log_error_write(srv, __FILE__, __LINE__, "s", "-- access denied due symlink restriction");
611 log_error_write(srv, __FILE__, __LINE__, "sb", "Path :", con->physical.path);
614 buffer_reset(con->physical.path);
615 return HANDLER_FINISHED;
617 #endif
619 /* we have a PATHINFO */
620 if (pathinfo) {
621 size_t len = strlen(pathinfo), reqlen;
622 if (con->conf.force_lowercase_filenames
623 && len <= (reqlen = buffer_string_length(con->request.uri))
624 && 0 == strncasecmp(con->request.uri->ptr + reqlen - len, pathinfo, len)) {
625 /* attempt to preserve case-insensitive PATH_INFO
626 * (works in common case where mod_alias, mod_magnet, and other modules
627 * have not modified the PATH_INFO portion of request URI, or did so
628 * with exactly the PATH_INFO desired) */
629 buffer_copy_string_len(con->request.pathinfo, con->request.uri->ptr + reqlen - len, len);
630 } else {
631 buffer_copy_string_len(con->request.pathinfo, pathinfo, len);
635 * shorten uri.path
638 buffer_string_set_length(con->uri.path, buffer_string_length(con->uri.path) - len);
641 if (con->conf.log_request_handling) {
642 log_error_write(srv, __FILE__, __LINE__, "s", "-- after pathinfo check");
643 log_error_write(srv, __FILE__, __LINE__, "sb", "Path :", con->physical.path);
644 log_error_write(srv, __FILE__, __LINE__, "sb", "URI :", con->uri.path);
645 log_error_write(srv, __FILE__, __LINE__, "sb", "Pathinfo :", con->request.pathinfo);
649 if (con->conf.log_request_handling) {
650 log_error_write(srv, __FILE__, __LINE__, "s", "-- handling subrequest");
651 log_error_write(srv, __FILE__, __LINE__, "sb", "Path :", con->physical.path);
654 /* call the handlers */
655 switch(r = plugins_call_handle_subrequest_start(srv, con)) {
656 case HANDLER_GO_ON:
657 /* request was not handled */
658 break;
659 case HANDLER_FINISHED:
660 default:
661 if (con->conf.log_request_handling) {
662 log_error_write(srv, __FILE__, __LINE__, "s", "-- subrequest finished");
665 /* something strange happend */
666 return r;
669 /* if we are still here, no one wanted the file, status 403 is ok I think */
671 if (con->mode == DIRECT && con->http_status == 0) {
672 switch (con->request.http_method) {
673 case HTTP_METHOD_OPTIONS:
674 con->http_status = 200;
675 break;
676 default:
677 con->http_status = 403;
680 return HANDLER_FINISHED;
685 switch(r = plugins_call_handle_subrequest(srv, con)) {
686 case HANDLER_GO_ON:
687 /* request was not handled, looks like we are done */
688 return HANDLER_FINISHED;
689 case HANDLER_FINISHED:
690 /* request is finished */
691 default:
692 /* something strange happend */
693 return r;
696 /* can't happen */
697 return HANDLER_COMEBACK;