6 #include "stat_cache.h"
9 #include "configfile.h"
10 #include "connections.h"
14 #include <sys/types.h>
29 #include "sys-socket.h"
32 int http_response_write_header(server
*srv
, connection
*con
) {
40 if (con
->request
.http_version
== HTTP_VERSION_1_1
) {
41 buffer_copy_string_len(b
, CONST_STR_LEN("HTTP/1.1 "));
43 buffer_copy_string_len(b
, CONST_STR_LEN("HTTP/1.0 "));
45 buffer_append_int(b
, con
->http_status
);
46 buffer_append_string_len(b
, CONST_STR_LEN(" "));
47 buffer_append_string(b
, get_http_status_name(con
->http_status
));
49 /* disable keep-alive if requested */
50 if (con
->request_count
> con
->conf
.max_keep_alive_requests
|| 0 == con
->conf
.max_keep_alive_idle
) {
53 con
->keep_alive_idle
= con
->conf
.max_keep_alive_idle
;
56 if (con
->request
.http_version
!= HTTP_VERSION_1_1
|| con
->keep_alive
== 0) {
57 if (con
->keep_alive
) {
58 response_header_overwrite(srv
, con
, CONST_STR_LEN("Connection"), CONST_STR_LEN("keep-alive"));
60 response_header_overwrite(srv
, con
, CONST_STR_LEN("Connection"), CONST_STR_LEN("close"));
64 if (con
->response
.transfer_encoding
& HTTP_TRANSFER_ENCODING_CHUNKED
) {
65 response_header_overwrite(srv
, con
, CONST_STR_LEN("Transfer-Encoding"), CONST_STR_LEN("chunked"));
70 for (i
= 0; i
< con
->response
.headers
->used
; i
++) {
73 ds
= (data_string
*)con
->response
.headers
->data
[i
];
75 if (!buffer_is_empty(ds
->value
) && !buffer_is_empty(ds
->key
) &&
76 0 != strncasecmp(ds
->key
->ptr
, CONST_STR_LEN("X-LIGHTTPD-")) &&
77 0 != strncasecmp(ds
->key
->ptr
, CONST_STR_LEN("X-Sendfile"))) {
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(": "));
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
);
91 buffer_append_string_buffer(b
, ds
->value
);
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
);
113 if (buffer_is_empty(con
->conf
.server_tag
)) {
114 buffer_append_string_len(b
, CONST_STR_LEN("\r\nServer: " PACKAGE_DESC
));
115 } else if (!buffer_string_is_empty(con
->conf
.server_tag
)) {
116 buffer_append_string_len(b
, CONST_STR_LEN("\r\nServer: "));
117 buffer_append_string_encoded(b
, CONST_BUF_LEN(con
->conf
.server_tag
), ENCODING_HTTP_HEADER
);
121 buffer_append_string_len(b
, CONST_STR_LEN("\r\n\r\n"));
123 con
->bytes_header
= buffer_string_length(b
);
125 if (con
->conf
.log_response_header
) {
126 log_error_write(srv
, __FILE__
, __LINE__
, "sSb", "Response-Header:", "\n", b
);
129 chunkqueue_prepend_buffer(con
->write_queue
, b
);
136 static void https_add_ssl_entries(connection
*con
) {
143 SSL_get_verify_result(con
->ssl
) != X509_V_OK
144 || !(xs
= SSL_get_peer_certificate(con
->ssl
))
149 xn
= X509_get_subject_name(xs
);
150 for (i
= 0, nentries
= X509_NAME_entry_count(xn
); i
< nentries
; ++i
) {
155 if (!(xe
= X509_NAME_get_entry(xn
, i
))) {
158 xobjnid
= OBJ_obj2nid((ASN1_OBJECT
*)X509_NAME_ENTRY_get_object(xe
));
159 xobjsn
= OBJ_nid2sn(xobjnid
);
164 if (NULL
== (envds
= (data_string
*)array_get_unused_element(con
->environment
, TYPE_STRING
))) {
165 envds
= data_string_init();
167 buffer_copy_string_len(envds
->key
, CONST_STR_LEN("SSL_CLIENT_S_DN_"));
168 buffer_append_string(envds
->key
, xobjsn
);
169 buffer_copy_string_len(
171 (const char *)xe
->value
->data
, xe
->value
->length
173 /* pick one of the exported values as "REMOTE_USER", for example
174 * ssl.verifyclient.username = "SSL_CLIENT_S_DN_UID" or "SSL_CLIENT_S_DN_emailAddress"
176 if (buffer_is_equal(con
->conf
.ssl_verifyclient_username
, envds
->key
)) {
178 if (NULL
== (ds
= (data_string
*)array_get_element(con
->environment
, "REMOTE_USER"))) {
179 if (NULL
== (ds
= (data_string
*)array_get_unused_element(con
->environment
, TYPE_STRING
))) {
180 ds
= data_string_init();
182 buffer_copy_string(ds
->key
, "REMOTE_USER");
183 array_insert_unique(con
->environment
, (data_unset
*)ds
);
185 buffer_copy_buffer(ds
->value
, envds
->value
);
187 array_insert_unique(con
->environment
, (data_unset
*)envds
);
189 if (con
->conf
.ssl_verifyclient_export_cert
) {
191 if (NULL
!= (bio
= BIO_new(BIO_s_mem()))) {
195 PEM_write_bio_X509(bio
, xs
);
196 n
= BIO_pending(bio
);
198 if (NULL
== (envds
= (data_string
*)array_get_unused_element(con
->environment
, TYPE_STRING
))) {
199 envds
= data_string_init();
202 buffer_copy_string_len(envds
->key
, CONST_STR_LEN("SSL_CLIENT_CERT"));
203 buffer_string_prepare_copy(envds
->value
, n
);
204 BIO_read(bio
, envds
->value
->ptr
, n
);
206 buffer_commit(envds
->value
, n
);
207 array_insert_unique(con
->environment
, (data_unset
*)envds
);
215 handler_t
http_response_prepare(server
*srv
, connection
*con
) {
218 /* looks like someone has already done a decision */
219 if (con
->mode
== DIRECT
&&
220 (con
->http_status
!= 0 && con
->http_status
!= 200)) {
221 /* remove a packets in the queue */
222 if (con
->file_finished
== 0) {
223 chunkqueue_reset(con
->write_queue
);
226 return HANDLER_FINISHED
;
229 /* no decision yet, build conf->filename */
230 if (con
->mode
== DIRECT
&& buffer_is_empty(con
->physical
.path
)) {
233 /* we only come here when we have the parse the full request again
235 * a HANDLER_COMEBACK from mod_rewrite and mod_fastcgi might be a
236 * problem here as mod_setenv might get called multiple times
238 * fastcgi-auth might lead to a COMEBACK too
239 * fastcgi again dead server too
241 * mod_compress might add headers twice too
245 config_cond_cache_reset(srv
, con
);
246 config_setup_connection(srv
, con
); /* Perhaps this could be removed at other places. */
248 if (con
->conf
.log_condition_handling
) {
249 log_error_write(srv
, __FILE__
, __LINE__
, "s", "run condition");
256 * - uri.path (secure)
262 * Name according to RFC 2396
269 * (scheme)://(authority)(path)?(query)#fragment
274 /* initial scheme value. can be overwritten for example by mod_extforward later */
275 if (con
->srv_socket
->is_ssl
) {
276 buffer_copy_string_len(con
->uri
.scheme
, CONST_STR_LEN("https"));
278 buffer_copy_string_len(con
->uri
.scheme
, CONST_STR_LEN("http"));
280 buffer_copy_buffer(con
->uri
.authority
, con
->request
.http_host
);
281 buffer_to_lower(con
->uri
.authority
);
283 /** their might be a fragment which has to be cut away */
284 if (NULL
!= (qstr
= strchr(con
->request
.uri
->ptr
, '#'))) {
285 buffer_string_set_length(con
->request
.uri
, qstr
- con
->request
.uri
->ptr
);
288 /** extract query string from request.uri */
289 if (NULL
!= (qstr
= strchr(con
->request
.uri
->ptr
, '?'))) {
290 buffer_copy_string (con
->uri
.query
, qstr
+ 1);
291 buffer_copy_string_len(con
->uri
.path_raw
, con
->request
.uri
->ptr
, qstr
- con
->request
.uri
->ptr
);
293 buffer_reset (con
->uri
.query
);
294 buffer_copy_buffer(con
->uri
.path_raw
, con
->request
.uri
);
297 /* decode url to path
299 * - decode url-encodings (e.g. %20 -> ' ')
300 * - remove path-modifiers (e.g. /../)
303 if (con
->request
.http_method
== HTTP_METHOD_OPTIONS
&&
304 con
->uri
.path_raw
->ptr
[0] == '*' && con
->uri
.path_raw
->ptr
[1] == '\0') {
306 buffer_copy_buffer(con
->uri
.path
, con
->uri
.path_raw
);
308 buffer_copy_buffer(srv
->tmp_buf
, con
->uri
.path_raw
);
309 buffer_urldecode_path(srv
->tmp_buf
);
310 buffer_path_simplify(con
->uri
.path
, srv
->tmp_buf
);
313 con
->conditional_is_valid
[COMP_SERVER_SOCKET
] = 1; /* SERVERsocket */
314 con
->conditional_is_valid
[COMP_HTTP_SCHEME
] = 1; /* Scheme: */
315 con
->conditional_is_valid
[COMP_HTTP_HOST
] = 1; /* Host: */
316 con
->conditional_is_valid
[COMP_HTTP_REMOTE_IP
] = 1; /* Client-IP */
317 con
->conditional_is_valid
[COMP_HTTP_REFERER
] = 1; /* Referer: */
318 con
->conditional_is_valid
[COMP_HTTP_USER_AGENT
] = /* User-Agent: */
319 con
->conditional_is_valid
[COMP_HTTP_LANGUAGE
] = 1; /* Accept-Language: */
320 con
->conditional_is_valid
[COMP_HTTP_COOKIE
] = 1; /* Cookie: */
321 con
->conditional_is_valid
[COMP_HTTP_REQUEST_METHOD
] = 1; /* REQUEST_METHOD */
322 con
->conditional_is_valid
[COMP_HTTP_URL
] = 1; /* HTTPurl */
323 con
->conditional_is_valid
[COMP_HTTP_QUERY_STRING
] = 1; /* HTTPqs */
324 config_patch_connection(srv
, con
);
327 if (con
->srv_socket
->is_ssl
&& con
->conf
.ssl_verifyclient
) {
328 https_add_ssl_entries(con
);
332 /* do we have to downgrade to 1.0 ? */
333 if (!con
->conf
.allow_http11
) {
334 con
->request
.http_version
= HTTP_VERSION_1_0
;
337 if (con
->conf
.log_request_handling
) {
338 log_error_write(srv
, __FILE__
, __LINE__
, "s", "-- splitting Request-URI");
339 log_error_write(srv
, __FILE__
, __LINE__
, "sb", "Request-URI : ", con
->request
.uri
);
340 log_error_write(srv
, __FILE__
, __LINE__
, "sb", "URI-scheme : ", con
->uri
.scheme
);
341 log_error_write(srv
, __FILE__
, __LINE__
, "sb", "URI-authority : ", con
->uri
.authority
);
342 log_error_write(srv
, __FILE__
, __LINE__
, "sb", "URI-path (raw) : ", con
->uri
.path_raw
);
343 log_error_write(srv
, __FILE__
, __LINE__
, "sb", "URI-path (clean): ", con
->uri
.path
);
344 log_error_write(srv
, __FILE__
, __LINE__
, "sb", "URI-query : ", con
->uri
.query
);
352 * - based on the raw URL
356 switch(r
= plugins_call_handle_uri_raw(srv
, con
)) {
359 case HANDLER_FINISHED
:
360 case HANDLER_COMEBACK
:
361 case HANDLER_WAIT_FOR_EVENT
:
365 log_error_write(srv
, __FILE__
, __LINE__
, "sd", "handle_uri_raw: unknown return value", r
);
373 * - based on the clean URL
377 switch(r
= plugins_call_handle_uri_clean(srv
, con
)) {
380 case HANDLER_FINISHED
:
381 case HANDLER_COMEBACK
:
382 case HANDLER_WAIT_FOR_EVENT
:
386 log_error_write(srv
, __FILE__
, __LINE__
, "");
390 if (con
->request
.http_method
== HTTP_METHOD_OPTIONS
&&
391 con
->uri
.path
->ptr
[0] == '*' && con
->uri
.path_raw
->ptr
[1] == '\0') {
392 /* option requests are handled directly without checking of the path */
394 response_header_insert(srv
, con
, CONST_STR_LEN("Allow"), CONST_STR_LEN("OPTIONS, GET, HEAD, POST"));
396 con
->http_status
= 200;
397 con
->file_finished
= 1;
399 return HANDLER_FINISHED
;
406 * logical filename (URI) becomes a physical filename here
416 * ... ISREG() -> ok, go on
417 * ... ISDIR() -> index-file -> redirect
427 * SEARCH DOCUMENT ROOT
432 buffer_copy_buffer(con
->physical
.doc_root
, con
->conf
.document_root
);
433 buffer_copy_buffer(con
->physical
.rel_path
, con
->uri
.path
);
435 #if defined(__WIN32) || defined(__CYGWIN__)
436 /* strip dots from the end and spaces
438 * windows/dos handle those filenames as the same file
440 * foo == foo. == foo..... == "foo... " == "foo.. ./"
442 * This will affect in some cases PATHINFO
444 * on native windows we could prepend the filename with \\?\ to circumvent
445 * this behaviour. I have no idea how to push this through cygwin
449 if (con
->physical
.rel_path
->used
> 1) {
450 buffer
*b
= con
->physical
.rel_path
;
451 size_t len
= buffer_string_length(b
);
454 /* strip trailing " /" or "./" once */
456 b
->ptr
[len
- 1] == '/' &&
457 (b
->ptr
[len
- 2] == ' ' || b
->ptr
[len
- 2] == '.')) {
460 /* strip all trailing " " and "." */
461 while (len
> 0 && ( ' ' == b
->ptr
[len
-1] || '.' == b
->ptr
[len
-1] ) ) --len
;
462 buffer_string_set_length(b
, len
);
466 if (con
->conf
.log_request_handling
) {
467 log_error_write(srv
, __FILE__
, __LINE__
, "s", "-- before doc_root");
468 log_error_write(srv
, __FILE__
, __LINE__
, "sb", "Doc-Root :", con
->physical
.doc_root
);
469 log_error_write(srv
, __FILE__
, __LINE__
, "sb", "Rel-Path :", con
->physical
.rel_path
);
470 log_error_write(srv
, __FILE__
, __LINE__
, "sb", "Path :", con
->physical
.path
);
472 /* the docroot plugin should set the doc_root and might also set the physical.path
473 * for us (all vhost-plugins are supposed to set the doc_root)
475 switch(r
= plugins_call_handle_docroot(srv
, con
)) {
478 case HANDLER_FINISHED
:
479 case HANDLER_COMEBACK
:
480 case HANDLER_WAIT_FOR_EVENT
:
484 log_error_write(srv
, __FILE__
, __LINE__
, "");
488 /* MacOS X and Windows can't distiguish between upper and lower-case
490 * convert to lower-case
492 if (con
->conf
.force_lowercase_filenames
) {
493 buffer_to_lower(con
->physical
.rel_path
);
496 /* the docroot plugins might set the servername, if they don't we take http-host */
497 if (buffer_string_is_empty(con
->server_name
)) {
498 buffer_copy_buffer(con
->server_name
, con
->uri
.authority
);
502 * create physical filename
503 * -> physical.path = docroot + rel_path
507 buffer_copy_buffer(con
->physical
.basedir
, con
->physical
.doc_root
);
508 buffer_copy_buffer(con
->physical
.path
, con
->physical
.doc_root
);
509 buffer_append_slash(con
->physical
.path
);
510 if (!buffer_string_is_empty(con
->physical
.rel_path
) &&
511 con
->physical
.rel_path
->ptr
[0] == '/') {
512 buffer_append_string_len(con
->physical
.path
, con
->physical
.rel_path
->ptr
+ 1, buffer_string_length(con
->physical
.rel_path
) - 1);
514 buffer_append_string_buffer(con
->physical
.path
, con
->physical
.rel_path
);
517 if (con
->conf
.log_request_handling
) {
518 log_error_write(srv
, __FILE__
, __LINE__
, "s", "-- after doc_root");
519 log_error_write(srv
, __FILE__
, __LINE__
, "sb", "Doc-Root :", con
->physical
.doc_root
);
520 log_error_write(srv
, __FILE__
, __LINE__
, "sb", "Rel-Path :", con
->physical
.rel_path
);
521 log_error_write(srv
, __FILE__
, __LINE__
, "sb", "Path :", con
->physical
.path
);
524 switch(r
= plugins_call_handle_physical(srv
, con
)) {
527 case HANDLER_FINISHED
:
528 case HANDLER_COMEBACK
:
529 case HANDLER_WAIT_FOR_EVENT
:
533 log_error_write(srv
, __FILE__
, __LINE__
, "");
537 if (con
->conf
.log_request_handling
) {
538 log_error_write(srv
, __FILE__
, __LINE__
, "s", "-- logical -> physical");
539 log_error_write(srv
, __FILE__
, __LINE__
, "sb", "Doc-Root :", con
->physical
.doc_root
);
540 log_error_write(srv
, __FILE__
, __LINE__
, "sb", "Basedir :", con
->physical
.basedir
);
541 log_error_write(srv
, __FILE__
, __LINE__
, "sb", "Rel-Path :", con
->physical
.rel_path
);
542 log_error_write(srv
, __FILE__
, __LINE__
, "sb", "Path :", con
->physical
.path
);
547 * Noone catched away the file from normal path of execution yet (like mod_access)
549 * Go on and check of the file exists at all
552 if (con
->mode
== DIRECT
) {
554 char *pathinfo
= NULL
;
556 stat_cache_entry
*sce
= NULL
;
558 if (con
->conf
.log_request_handling
) {
559 log_error_write(srv
, __FILE__
, __LINE__
, "s", "-- handling physical path");
560 log_error_write(srv
, __FILE__
, __LINE__
, "sb", "Path :", con
->physical
.path
);
563 if (HANDLER_ERROR
!= stat_cache_get_entry(srv
, con
, con
->physical
.path
, &sce
)) {
566 if (con
->conf
.log_request_handling
) {
567 log_error_write(srv
, __FILE__
, __LINE__
, "s", "-- file found");
568 log_error_write(srv
, __FILE__
, __LINE__
, "sb", "Path :", con
->physical
.path
);
571 if ((sce
->is_symlink
!= 0) && !con
->conf
.follow_symlink
) {
572 con
->http_status
= 403;
574 if (con
->conf
.log_request_handling
) {
575 log_error_write(srv
, __FILE__
, __LINE__
, "s", "-- access denied due symlink restriction");
576 log_error_write(srv
, __FILE__
, __LINE__
, "sb", "Path :", con
->physical
.path
);
579 buffer_reset(con
->physical
.path
);
580 return HANDLER_FINISHED
;
583 if (S_ISDIR(sce
->st
.st_mode
)) {
584 if (con
->uri
.path
->ptr
[buffer_string_length(con
->uri
.path
) - 1] != '/') {
585 /* redirect to .../ */
587 http_response_redirect_to_directory(srv
, con
);
589 return HANDLER_FINISHED
;
592 } else if (!S_ISREG(sce
->st
.st_mode
) && !sce
->is_symlink
) {
594 } else if (!S_ISREG(sce
->st
.st_mode
)) {
596 /* any special handling of non-reg files ?*/
603 con
->http_status
= 403;
605 if (con
->conf
.log_request_handling
) {
606 log_error_write(srv
, __FILE__
, __LINE__
, "s", "-- access denied");
607 log_error_write(srv
, __FILE__
, __LINE__
, "sb", "Path :", con
->physical
.path
);
610 buffer_reset(con
->physical
.path
);
611 return HANDLER_FINISHED
;
613 /* file name to be read was too long. return 404 */
615 con
->http_status
= 404;
617 if (con
->conf
.log_request_handling
) {
618 log_error_write(srv
, __FILE__
, __LINE__
, "s", "-- file not found");
619 log_error_write(srv
, __FILE__
, __LINE__
, "sb", "Path :", con
->physical
.path
);
622 buffer_reset(con
->physical
.path
);
623 return HANDLER_FINISHED
;
628 /* we have no idea what happend. let's tell the user so. */
629 con
->http_status
= 500;
630 buffer_reset(con
->physical
.path
);
632 log_error_write(srv
, __FILE__
, __LINE__
, "ssbsb",
633 "file not found ... or so: ", strerror(errno
),
635 "->", con
->physical
.path
);
637 return HANDLER_FINISHED
;
640 /* not found, perhaps PATHINFO */
642 buffer_copy_buffer(srv
->tmp_buf
, con
->physical
.path
);
646 buffer_copy_string_len(con
->physical
.path
, srv
->tmp_buf
->ptr
, slash
- srv
->tmp_buf
->ptr
);
648 buffer_copy_buffer(con
->physical
.path
, srv
->tmp_buf
);
651 if (HANDLER_ERROR
!= stat_cache_get_entry(srv
, con
, con
->physical
.path
, &sce
)) {
652 found
= S_ISREG(sce
->st
.st_mode
);
656 if (pathinfo
!= NULL
) {
659 slash
= strrchr(srv
->tmp_buf
->ptr
, '/');
661 if (pathinfo
!= NULL
) {
666 if (slash
) pathinfo
= slash
;
667 } while ((found
== 0) && (slash
!= NULL
) && ((size_t)(slash
- srv
->tmp_buf
->ptr
) > (buffer_string_length(con
->physical
.basedir
) - 1)));
670 /* no it really doesn't exists */
671 con
->http_status
= 404;
673 if (con
->conf
.log_file_not_found
) {
674 log_error_write(srv
, __FILE__
, __LINE__
, "sbsb",
675 "file not found:", con
->uri
.path
,
676 "->", con
->physical
.path
);
679 buffer_reset(con
->physical
.path
);
681 return HANDLER_FINISHED
;
685 if ((sce
->is_symlink
!= 0) && !con
->conf
.follow_symlink
) {
686 con
->http_status
= 403;
688 if (con
->conf
.log_request_handling
) {
689 log_error_write(srv
, __FILE__
, __LINE__
, "s", "-- access denied due symlink restriction");
690 log_error_write(srv
, __FILE__
, __LINE__
, "sb", "Path :", con
->physical
.path
);
693 buffer_reset(con
->physical
.path
);
694 return HANDLER_FINISHED
;
698 /* we have a PATHINFO */
700 buffer_copy_string(con
->request
.pathinfo
, pathinfo
);
706 buffer_string_set_length(con
->uri
.path
, buffer_string_length(con
->uri
.path
) - strlen(pathinfo
));
709 if (con
->conf
.log_request_handling
) {
710 log_error_write(srv
, __FILE__
, __LINE__
, "s", "-- after pathinfo check");
711 log_error_write(srv
, __FILE__
, __LINE__
, "sb", "Path :", con
->physical
.path
);
712 log_error_write(srv
, __FILE__
, __LINE__
, "sb", "URI :", con
->uri
.path
);
713 log_error_write(srv
, __FILE__
, __LINE__
, "sb", "Pathinfo :", con
->request
.pathinfo
);
717 if (con
->conf
.log_request_handling
) {
718 log_error_write(srv
, __FILE__
, __LINE__
, "s", "-- handling subrequest");
719 log_error_write(srv
, __FILE__
, __LINE__
, "sb", "Path :", con
->physical
.path
);
722 /* call the handlers */
723 switch(r
= plugins_call_handle_subrequest_start(srv
, con
)) {
725 /* request was not handled */
727 case HANDLER_FINISHED
:
729 if (con
->conf
.log_request_handling
) {
730 log_error_write(srv
, __FILE__
, __LINE__
, "s", "-- subrequest finished");
733 /* something strange happend */
737 /* if we are still here, no one wanted the file, status 403 is ok I think */
739 if (con
->mode
== DIRECT
&& con
->http_status
== 0) {
740 switch (con
->request
.http_method
) {
741 case HTTP_METHOD_OPTIONS
:
742 con
->http_status
= 200;
745 con
->http_status
= 403;
748 return HANDLER_FINISHED
;
753 switch(r
= plugins_call_handle_subrequest(srv
, con
)) {
755 /* request was not handled, looks like we are done */
756 return HANDLER_FINISHED
;
757 case HANDLER_FINISHED
:
758 /* request is finished */
760 /* something strange happend */
765 return HANDLER_COMEBACK
;