summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGlenn Strauss <gstrauss@gluelogic.com>2021-07-06 22:58:13 -0400
committerGlenn Strauss <gstrauss@gluelogic.com>2021-09-04 08:08:26 -0400
commit91472ab7681b26f36b813f3b245c0e98f91b4c3f (patch)
treec0a71cb0f9d52747ec4c0409f8863b9f64233e83
parenta0a8cf821d2292e6662119e158e73c175452f1c3 (diff)
downloadlighttpd-git-91472ab7681b26f36b813f3b245c0e98f91b4c3f.tar.gz
[tests] t/test_mod_staticfile
move some tests from tests/request.t to src/t/test_mod_staticfile.c
-rw-r--r--.gitignore1
-rw-r--r--src/CMakeLists.txt27
-rw-r--r--src/Makefile.am5
-rw-r--r--src/meson.build44
-rw-r--r--src/mod_staticfile.c32
-rw-r--r--src/t/test_mod_staticfile.c458
-rw-r--r--tests/CMakeLists.txt1
-rw-r--r--tests/Makefile.am1
-rwxr-xr-xtests/cachable.t211
-rwxr-xr-xtests/core-request.t9
-rwxr-xr-xtests/core-response.t17
-rw-r--r--tests/meson.build1
-rwxr-xr-xtests/request.t56
13 files changed, 556 insertions, 307 deletions
diff --git a/.gitignore b/.gitignore
index c7c2b84d..2e699450 100644
--- a/.gitignore
+++ b/.gitignore
@@ -55,6 +55,7 @@ test_configfile
test_mod_access
test_mod_evhost
test_mod_simple_vhost
+test_mod_staticfile
test_mod_userdir
test_request
versionstamp.h
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 5fec0207..c92a85b7 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -927,6 +927,30 @@ add_executable(test_mod_simple_vhost
)
add_test(NAME test_mod_simple_vhost COMMAND test_mod_simple_vhost)
+add_executable(test_mod_staticfile
+ t/test_mod_staticfile.c
+ request.c
+ base64.c
+ buffer.c
+ burl.c
+ array.c
+ chunk.c
+ fdevent.c
+ http-header-glue.c
+ http_cgi.c
+ http_chunk.c
+ http_date.c
+ http_etag.c
+ http_header.c
+ http_kv.c
+ log.c
+ sock_addr.c
+ stat_cache.c
+ algo_splaytree.c
+ ck.c
+)
+add_test(NAME test_mod_staticfile COMMAND test_mod_staticfile)
+
add_executable(test_mod_userdir
t/test_mod_userdir.c
buffer.c
@@ -1084,6 +1108,7 @@ endif()
if(HAVE_LIBFAM)
target_link_libraries(lighttpd fam)
+ target_link_libraries(test_mod_staticfile fam)
endif()
if(HAVE_GDBM_H)
@@ -1204,6 +1229,8 @@ if(WITH_LIBUNWIND)
add_target_properties(test_mod_evhost COMPILE_FLAGS ${LIBUNWIND_CFLAGS})
target_link_libraries(test_mod_simple_vhost ${LIBUNWIND_LDFLAGS})
add_target_properties(test_mod_simple_vhost COMPILE_FLAGS ${LIBUNWIND_CFLAGS})
+ target_link_libraries(test_mod_staticfile ${LIBUNWIND_LDFLAGS})
+ add_target_properties(test_mod_staticfile COMPILE_FLAGS ${LIBUNWIND_CFLAGS})
target_link_libraries(test_mod_userdir ${LIBUNWIND_LDFLAGS})
add_target_properties(test_mod_userdir COMPILE_FLAGS ${LIBUNWIND_CFLAGS})
target_link_libraries(test_request ${LIBUNWIND_LDFLAGS})
diff --git a/src/Makefile.am b/src/Makefile.am
index fe7341e6..1f15aec4 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -10,6 +10,7 @@ noinst_PROGRAMS=\
t/test_mod_access \
t/test_mod_evhost \
t/test_mod_simple_vhost \
+ t/test_mod_staticfile \
t/test_mod_userdir \
t/test_request
@@ -26,6 +27,7 @@ TESTS=\
t/test_mod_access$(EXEEXT) \
t/test_mod_evhost$(EXEEXT) \
t/test_mod_simple_vhost$(EXEEXT) \
+ t/test_mod_staticfile$(EXEEXT) \
t/test_mod_userdir$(EXEEXT) \
t/test_request$(EXEEXT)
@@ -663,6 +665,9 @@ t_test_mod_evhost_LDADD = $(LIBUNWIND_LIBS)
t_test_mod_simple_vhost_SOURCES = t/test_mod_simple_vhost.c buffer.c array.c log.c ck.c
t_test_mod_simple_vhost_LDADD = $(LIBUNWIND_LIBS)
+t_test_mod_staticfile_SOURCES = t/test_mod_staticfile.c request.c base64.c buffer.c burl.c array.c chunk.c fdevent.c http-header-glue.c http_cgi.c http_chunk.c http_date.c http_etag.c http_header.c http_kv.c log.c sock_addr.c stat_cache.c algo_splaytree.c ck.c
+t_test_mod_staticfile_LDADD = $(LIBUNWIND_LIBS) $(FAM_LIBS)
+
t_test_mod_userdir_SOURCES = t/test_mod_userdir.c buffer.c array.c log.c ck.c
t_test_mod_userdir_LDADD = $(LIBUNWIND_LIBS)
diff --git a/src/meson.build b/src/meson.build
index fdf57ca9..a0c6ee9e 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -895,7 +895,11 @@ test('test_configfile', executable('test_configfile',
'sock_addr.c',
'ck.c',
],
- dependencies: common_flags + libpcre + libunwind,
+ dependencies: [ common_flags
+ , libpcre
+ , libunwind
+ , libws2_32
+ ],
build_by_default: false,
))
@@ -949,6 +953,38 @@ test('test_mod_simple_vhost', executable('test_mod_simple_vhost',
build_by_default: false,
))
+test('test_mod_staticfile', executable('test_mod_staticfile',
+ sources: [
+ 't/test_mod_staticfile.c',
+ 'request.c',
+ 'base64.c',
+ 'buffer.c',
+ 'burl.c',
+ 'array.c',
+ 'chunk.c',
+ 'fdevent.c',
+ 'http-header-glue.c',
+ 'http_cgi.c',
+ 'http_chunk.c',
+ 'http_date.c',
+ 'http_etag.c',
+ 'http_header.c',
+ 'http_kv.c',
+ 'log.c',
+ 'sock_addr.c',
+ 'stat_cache.c',
+ 'algo_splaytree.c',
+ 'ck.c'
+ ],
+ dependencies: [ common_flags
+ , libfam
+ , libpcre
+ , libunwind
+ , libws2_32
+ ],
+ build_by_default: false,
+))
+
test('test_mod_userdir', executable('test_mod_userdir',
sources: [
't/test_mod_userdir.c',
@@ -974,7 +1010,11 @@ test('test_request', executable('test_request',
'sock_addr.c',
'ck.c',
],
- dependencies: common_flags + libunwind,
+ dependencies: [ common_flags
+ , libpcre
+ , libunwind
+ , libws2_32
+ ],
build_by_default: false,
))
diff --git a/src/mod_staticfile.c b/src/mod_staticfile.c
index 763cc521..d39abe29 100644
--- a/src/mod_staticfile.c
+++ b/src/mod_staticfile.c
@@ -107,25 +107,19 @@ mod_staticfile_not_handled(request_st * const r, const char * const msg)
return HANDLER_GO_ON;
}
-URIHANDLER_FUNC(mod_staticfile_subrequest) {
- if (NULL != r->handler_module) return HANDLER_GO_ON;
- if (!http_method_get_head_post(r->http_method)) return HANDLER_GO_ON;
- /* r->physical.path is non-empty for handle_subrequest_start */
- /*if (buffer_is_blank(&r->physical.path)) return HANDLER_GO_ON;*/
-
- plugin_data * const p = p_d;
- mod_staticfile_patch_config(r, p);
-
- if (p->conf.disable_pathinfo && !buffer_is_blank(&r->pathinfo)) {
+static handler_t
+mod_staticfile_process (request_st * const r, plugin_config * const pconf)
+{
+ if (pconf->disable_pathinfo && !buffer_is_blank(&r->pathinfo)) {
return mod_staticfile_not_handled(r, "pathinfo");
}
- if (p->conf.exclude_ext
- && array_match_value_suffix(p->conf.exclude_ext, &r->physical.path)) {
+ if (pconf->exclude_ext
+ && array_match_value_suffix(pconf->exclude_ext, &r->physical.path)) {
return mod_staticfile_not_handled(r, "extension");
}
- if (!p->conf.etags_used) r->conf.etag_flags = 0;
+ if (!pconf->etags_used) r->conf.etag_flags = 0;
/* r->tmp_sce is set in http_response_physical_path_check() and is valid
* in handle_subrequest_start callback -- handle_subrequest_start callbacks
@@ -138,6 +132,18 @@ URIHANDLER_FUNC(mod_staticfile_subrequest) {
return HANDLER_FINISHED;
}
+URIHANDLER_FUNC(mod_staticfile_subrequest) {
+ if (NULL != r->handler_module) return HANDLER_GO_ON;
+ if (!http_method_get_head_post(r->http_method)) return HANDLER_GO_ON;
+ /* r->physical.path is non-empty for handle_subrequest_start */
+ /*if (buffer_is_blank(&r->physical.path)) return HANDLER_GO_ON;*/
+
+ plugin_data * const p = p_d;
+ mod_staticfile_patch_config(r, p);
+
+ return mod_staticfile_process(r, &p->conf);
+}
+
int mod_staticfile_plugin_init(plugin *p);
int mod_staticfile_plugin_init(plugin *p) {
diff --git a/src/t/test_mod_staticfile.c b/src/t/test_mod_staticfile.c
new file mode 100644
index 00000000..58e4e968
--- /dev/null
+++ b/src/t/test_mod_staticfile.c
@@ -0,0 +1,458 @@
+#include "first.h"
+
+#undef NDEBUG
+#include <sys/types.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "mod_staticfile.c"
+#include "http_date.h"
+#include "http_etag.h"
+#include "http_header.h"
+
+__attribute_noinline__
+static void test_mod_staticfile_reset (request_st * const r)
+{
+ r->http_status = 0;
+ r->resp_htags = 0;
+ array_reset_data_strings(&r->resp_headers);
+ http_response_body_clear(r, 0);
+ buffer_clear(&r->physical.etag);
+ r->conf.etag_flags = ETAG_USE_INODE | ETAG_USE_MTIME | ETAG_USE_SIZE;
+}
+
+__attribute_noinline__
+static void
+run_http_response_send_file (request_st * const r, int line, int status, const char *desc)
+{
+ http_response_send_file(r, &r->physical.path, NULL);
+ if (r->http_status != status) {
+ fprintf(stderr,
+ "%s.%d: %s() failed: expected '%d', got '%d' for test %s\n",
+ __FILE__, line, "http_response_send_file", status,
+ r->http_status, desc);
+ fflush(stderr);
+ abort();
+ }
+}
+
+static void
+test_http_response_send_file (request_st * const r, time_t lmtime)
+{
+ test_mod_staticfile_reset(r);
+ const buffer *vb;
+
+ /*(mismatch test must be first, else stat_cache will have cached mimetype)*/
+ array * const mimetypes_empty = array_init(0);
+ const array * const mimetypes_orig = r->conf.mimetypes;
+ r->conf.mimetypes = mimetypes_empty;
+ run_http_response_send_file(r, __LINE__, 200,
+ "basic static file (w/o mimetype match)");
+ vb = http_header_response_get(r, HTTP_HEADER_CONTENT_TYPE,
+ CONST_STR_LEN("Content-Type"));
+ assert(vb && buffer_eq_slen(vb, CONST_STR_LEN("application/octet-stream")));
+ test_mod_staticfile_reset(r);
+ r->conf.mimetypes = mimetypes_orig;
+ array_free(mimetypes_empty);
+
+ run_http_response_send_file(r, __LINE__, 200,
+ "basic static file (w/ mimetype match)");
+ vb = http_header_response_get(r, HTTP_HEADER_CONTENT_TYPE,
+ CONST_STR_LEN("Content-Type"));
+ assert(vb && buffer_eq_slen(vb, CONST_STR_LEN("text/plain")));
+ vb = http_header_response_get(r, HTTP_HEADER_ETAG,
+ CONST_STR_LEN("ETag"));
+ assert(vb && vb->ptr[0] == '"' && vb->ptr[buffer_clen(vb)-1] == '"');
+ vb = http_header_response_get(r, HTTP_HEADER_LAST_MODIFIED,
+ CONST_STR_LEN("Last-Modified"));
+ assert(vb);
+ test_mod_staticfile_reset(r);
+
+ const uint32_t plen = buffer_clen(&r->physical.path);
+ buffer_append_string_len(&r->physical.path, CONST_STR_LEN("-nonexistent"));
+ run_http_response_send_file(r, __LINE__, 404,
+ "non-existent file");
+ test_mod_staticfile_reset(r);
+ buffer_truncate(&r->physical.path, plen);
+
+ http_header_request_set(r, HTTP_HEADER_IF_MODIFIED_SINCE,
+ CONST_STR_LEN("If-Modified-Since"),
+ CONST_STR_LEN(""));
+ run_http_response_send_file(r, __LINE__, 200,
+ "if-modified-since invalid (empty)");
+ test_mod_staticfile_reset(r);
+
+ http_header_request_set(r, HTTP_HEADER_IF_MODIFIED_SINCE,
+ CONST_STR_LEN("If-Modified-Since"),
+ CONST_STR_LEN("foobar"));
+ run_http_response_send_file(r, __LINE__, 200,
+ "if-modified-since invalid (not time string)");
+ test_mod_staticfile_reset(r);
+
+ http_header_request_set(r, HTTP_HEADER_IF_MODIFIED_SINCE,
+ CONST_STR_LEN("If-Modified-Since"),
+ CONST_STR_LEN("this string is too long to be a valid timestamp"));
+ run_http_response_send_file(r, __LINE__, 200,
+ "if-modified-since invalid (too long to be valid time string)");
+ test_mod_staticfile_reset(r);
+
+ char lmtime_str[HTTP_DATE_SZ];
+ uint32_t lmtime_len;
+
+ lmtime_len = http_date_time_to_str(lmtime_str,sizeof(lmtime_str),
+ lmtime ? lmtime-1 : lmtime);
+ http_header_request_set(r, HTTP_HEADER_IF_MODIFIED_SINCE,
+ CONST_STR_LEN("If-Modified-Since"),
+ lmtime_str, lmtime_len);
+ run_http_response_send_file(r, __LINE__, 200,
+ "if-modified-since older than st_mtime");
+ test_mod_staticfile_reset(r);
+
+ lmtime_len = http_date_time_to_str(lmtime_str,sizeof(lmtime_str),lmtime);
+ http_header_request_set(r, HTTP_HEADER_IF_MODIFIED_SINCE,
+ CONST_STR_LEN("If-Modified-Since"),
+ lmtime_str, lmtime_len);
+ run_http_response_send_file(r, __LINE__, 304,
+ "if-modified-since matches st_mtime");
+ test_mod_staticfile_reset(r);
+
+ lmtime_len = http_date_time_to_str(lmtime_str,sizeof(lmtime_str),lmtime+1);
+ http_header_request_set(r, HTTP_HEADER_IF_MODIFIED_SINCE,
+ CONST_STR_LEN("If-Modified-Since"),
+ lmtime_str, lmtime_len);
+ run_http_response_send_file(r, __LINE__, 304,
+ "if-modified-since newer than st_mtime");
+ test_mod_staticfile_reset(r);
+
+ buffer_append_string_len(
+ http_header_request_get(r, HTTP_HEADER_IF_MODIFIED_SINCE,
+ CONST_STR_LEN("If-Modified-Since")),
+ CONST_STR_LEN("; foo"));
+ run_http_response_send_file(r, __LINE__, 200,
+ "if-modified-since newer but overload (invalid)");
+ test_mod_staticfile_reset(r);
+
+ http_header_request_unset(r, HTTP_HEADER_IF_MODIFIED_SINCE,
+ CONST_STR_LEN("If-Modified-Since"));
+
+ buffer *etag = buffer_init();
+ http_header_request_set(r, HTTP_HEADER_IF_NONE_MATCH,
+ CONST_STR_LEN("If-None-Match"),
+ CONST_STR_LEN("foo"));
+ run_http_response_send_file(r, __LINE__, 200,
+ "if-none-match (etag mismatch)");
+ vb = http_header_response_get(r, HTTP_HEADER_ETAG,
+ CONST_STR_LEN("ETag"));
+ assert(vb);
+ buffer_copy_buffer(etag, vb);
+ test_mod_staticfile_reset(r);
+
+ http_header_request_set(r, HTTP_HEADER_IF_NONE_MATCH,
+ CONST_STR_LEN("If-None-Match"),
+ CONST_BUF_LEN(etag));
+ run_http_response_send_file(r, __LINE__, 304,
+ "if-none-match (etag match)");
+ test_mod_staticfile_reset(r);
+
+ r->conf.etag_flags = 0;
+ http_header_request_set(r, HTTP_HEADER_IF_NONE_MATCH,
+ CONST_STR_LEN("If-None-Match"),
+ CONST_BUF_LEN(etag));
+ run_http_response_send_file(r, __LINE__, 200,
+ "if-none-match (etag would match, but etags disabled in config)");
+ test_mod_staticfile_reset(r);
+ r->conf.etag_flags = ETAG_USE_INODE | ETAG_USE_MTIME | ETAG_USE_SIZE;
+
+ http_header_request_set(r, HTTP_HEADER_IF_NONE_MATCH,
+ CONST_STR_LEN("If-None-Match"),
+ CONST_BUF_LEN(etag));
+ lmtime_len = http_date_time_to_str(lmtime_str,sizeof(lmtime_str),
+ lmtime ? lmtime-1 : lmtime);
+ http_header_request_set(r, HTTP_HEADER_IF_MODIFIED_SINCE,
+ CONST_STR_LEN("If-Modified-Since"),
+ lmtime_str, lmtime_len);
+ run_http_response_send_file(r, __LINE__, 304,
+ "if-none-match (etag match), "
+ "if-modified-since (old) (should be ignored)");
+ test_mod_staticfile_reset(r);
+
+ http_header_request_set(r, HTTP_HEADER_IF_NONE_MATCH,
+ CONST_STR_LEN("If-None-Match"),
+ CONST_BUF_LEN(etag));
+ lmtime_len = http_date_time_to_str(lmtime_str,sizeof(lmtime_str),lmtime);
+ http_header_request_set(r, HTTP_HEADER_IF_MODIFIED_SINCE,
+ CONST_STR_LEN("If-Modified-Since"),
+ lmtime_str, lmtime_len);
+ run_http_response_send_file(r, __LINE__, 304,
+ "if-none-match (etag match), "
+ "if-modified-since (now) (should be ignored)");
+ test_mod_staticfile_reset(r);
+
+ http_header_request_set(r, HTTP_HEADER_IF_NONE_MATCH,
+ CONST_STR_LEN("If-None-Match"),
+ CONST_BUF_LEN(etag));
+ http_header_request_set(r, HTTP_HEADER_IF_MODIFIED_SINCE,
+ CONST_STR_LEN("If-Modified-Since"),
+ CONST_STR_LEN("Sun, 01 Jan 1970 00:00:01 GMT foo"));
+ run_http_response_send_file(r, __LINE__, 304,
+ "if-none-match (etag match), "
+ "if-modified-since (overlong; invalid) (should be ignored)");
+ test_mod_staticfile_reset(r);
+
+ http_header_request_set(r, HTTP_HEADER_IF_NONE_MATCH,
+ CONST_STR_LEN("If-None-Match"),
+ CONST_STR_LEN("foo"));
+ lmtime_len = http_date_time_to_str(lmtime_str,sizeof(lmtime_str),
+ lmtime ? lmtime-1 : lmtime);
+ http_header_request_set(r, HTTP_HEADER_IF_MODIFIED_SINCE,
+ CONST_STR_LEN("If-Modified-Since"),
+ lmtime_str, lmtime_len);
+ run_http_response_send_file(r, __LINE__, 200,
+ "if-none-match (etag mismatch), "
+ "if-modified-since (old) (should be ignored)");
+ test_mod_staticfile_reset(r);
+
+ http_header_request_set(r, HTTP_HEADER_IF_NONE_MATCH,
+ CONST_STR_LEN("If-None-Match"),
+ CONST_STR_LEN("foo"));
+ lmtime_len = http_date_time_to_str(lmtime_str,sizeof(lmtime_str),lmtime);
+ http_header_request_set(r, HTTP_HEADER_IF_MODIFIED_SINCE,
+ CONST_STR_LEN("If-Modified-Since"),
+ lmtime_str, lmtime_len);
+ run_http_response_send_file(r, __LINE__, 200,
+ "if-none-match (etag mismatch), "
+ "if-modified-since (now) (should be ignored)");
+ test_mod_staticfile_reset(r);
+
+ http_header_request_unset(r, HTTP_HEADER_IF_MODIFIED_SINCE,
+ CONST_STR_LEN("If-Modified-Since"));
+
+ http_header_request_set(r, HTTP_HEADER_IF_NONE_MATCH,
+ CONST_STR_LEN("If-None-Match"),
+ etag->ptr, buffer_clen(etag)-1);
+ run_http_response_send_file(r, __LINE__, 200,
+ "if-none-match (etag invalid; mismatched quotes)");
+ test_mod_staticfile_reset(r);
+
+ http_header_request_set(r, HTTP_HEADER_IF_NONE_MATCH,
+ CONST_STR_LEN("If-None-Match"),
+ etag->ptr+1, buffer_clen(etag)-2);
+ run_http_response_send_file(r, __LINE__, 200,
+ "if-none-match (etag invalid; no quotes)");
+ test_mod_staticfile_reset(r);
+
+ http_header_request_set(r, HTTP_HEADER_IF_NONE_MATCH,
+ CONST_STR_LEN("If-None-Match"),
+ CONST_STR_LEN("*"));
+ run_http_response_send_file(r, __LINE__, 304,
+ "if-none-match (etag * (unquoted) matches any ETag)");
+ test_mod_staticfile_reset(r);
+
+ http_header_request_set(r, HTTP_HEADER_IF_NONE_MATCH,
+ CONST_STR_LEN("If-None-Match"),
+ CONST_STR_LEN("\"*\""));
+ run_http_response_send_file(r, __LINE__, 200,
+ "if-none-match (etag \"*\" (quoted) is a regular ETag)");
+ test_mod_staticfile_reset(r);
+
+ buffer * const rqst_etag =
+ http_header_request_set_ptr(r, HTTP_HEADER_IF_NONE_MATCH,
+ CONST_STR_LEN("If-None-Match"));
+
+ buffer_copy_string_len(rqst_etag, CONST_STR_LEN("W/"));
+ buffer_append_buffer(rqst_etag, etag);
+ run_http_response_send_file(r, __LINE__, 304,
+ "if-none-match (weak etag) matches like ETag for GET and HEAD)");
+ test_mod_staticfile_reset(r);
+
+ /*(200 expected here instead of 206 since Range is handled later)*/
+ http_header_request_set(r, HTTP_HEADER_RANGE,
+ CONST_STR_LEN("Range"),
+ CONST_STR_LEN("bytes=0-0"));
+ run_http_response_send_file(r, __LINE__, 200,
+ "if-none-match (weak etag) does not match for Range request)");
+ test_mod_staticfile_reset(r);
+ http_header_request_unset(r, HTTP_HEADER_RANGE, CONST_STR_LEN("Range"));
+
+ buffer_copy_string_len(rqst_etag, CONST_STR_LEN("W/\"12345\""));
+ run_http_response_send_file(r, __LINE__, 200,
+ "if-none-match (weak etag no match)");
+ test_mod_staticfile_reset(r);
+
+ buffer_append_string_len(rqst_etag, CONST_STR_LEN(", "));
+ buffer_append_buffer(rqst_etag, etag);
+ run_http_response_send_file(r, __LINE__, 304,
+ "if-none-match (etag list, second etag matches)");
+ test_mod_staticfile_reset(r);
+
+ buffer_append_string_len(rqst_etag, CONST_STR_LEN(", W/"));
+ buffer_append_buffer(rqst_etag, etag);
+ run_http_response_send_file(r, __LINE__, 304,
+ "if-none-match (etag list, second etag matches weakly)");
+ test_mod_staticfile_reset(r);
+
+ buffer_copy_string_len(rqst_etag, CONST_STR_LEN("\"12345\",, ,, , "));
+ buffer_append_buffer(rqst_etag, etag);
+ run_http_response_send_file(r, __LINE__, 304,
+ "if-none-match (etag list non-normalized, ending with etag match)");
+ test_mod_staticfile_reset(r);
+
+ buffer_copy_string_len(rqst_etag, CONST_STR_LEN("\"1234\", "));
+ buffer_append_buffer(rqst_etag, etag);
+ buffer_append_string_len(rqst_etag, CONST_STR_LEN(", \"brokentrailing"));
+ run_http_response_send_file(r, __LINE__, 304,
+ "if-none-match (etag list with etag match then invalid trailing data)");
+ test_mod_staticfile_reset(r);
+
+ http_header_request_unset(r, HTTP_HEADER_IF_NONE_MATCH,
+ CONST_STR_LEN("If-None-Match"));
+
+ buffer_free(etag);
+}
+
+__attribute_noinline__
+static void
+run_mod_staticfile_process (request_st * const r, plugin_config * const pconf, int line, int status, const char *desc)
+{
+ handler_t rc = mod_staticfile_process(r, pconf);
+ if (r->http_status != status
+ || rc != (status ? HANDLER_FINISHED : HANDLER_GO_ON)) {
+ fprintf(stderr,
+ "%s.%d: %s() failed: expected '%d', got '%d' for test %s\n",
+ __FILE__, line, "mod_staticfile_process", status,
+ r->http_status, desc);
+ fflush(stderr);
+ abort();
+ }
+}
+
+static void
+test_mod_staticfile_process (request_st * const r, plugin_config * const pconf)
+{
+ test_mod_staticfile_reset(r);
+
+ pconf->disable_pathinfo = 0;
+ buffer_copy_string_len(&r->pathinfo, CONST_STR_LEN("/pathinfo"));
+ run_mod_staticfile_process(r, pconf, __LINE__, 200,
+ "pathinfo allowed and present");
+ test_mod_staticfile_reset(r);
+ pconf->disable_pathinfo = 1;
+ run_mod_staticfile_process(r, pconf, __LINE__, 0,
+ "pathinfo denied and present");
+ test_mod_staticfile_reset(r);
+ buffer_clear(&r->pathinfo);
+ run_mod_staticfile_process(r, pconf, __LINE__, 200,
+ "pathinfo denied and not present");
+ test_mod_staticfile_reset(r);
+ pconf->disable_pathinfo = 0;
+
+ array * const a = array_init(1);
+ array_insert_value(a, CONST_STR_LEN(".exe"));
+ pconf->exclude_ext = a;
+ run_mod_staticfile_process(r, pconf, __LINE__, 200,
+ "extension disallowed (no match)");
+ test_mod_staticfile_reset(r);
+ buffer_append_string_len(&r->physical.path, CONST_STR_LEN(".exe"));
+ run_mod_staticfile_process(r, pconf, __LINE__, 0,
+ "extension disallowed (match)");
+ test_mod_staticfile_reset(r);
+ pconf->exclude_ext = NULL;
+ array_free(a);
+}
+
+#include <unistd.h> /* unlink() */
+
+int main (void)
+{
+ char fn[] = "/tmp/lighttpd_mod_staticfile.XXXXXX";
+ #ifdef __COVERITY__
+ /* POSIX-2008 requires mkstemp create file with 0600 perms */
+ umask(0600);
+ #endif
+ /* coverity[secure_temp : FALSE] */
+ int fd = mkstemp(fn);
+ if (fd < 0) {
+ perror("mkstemp()");
+ exit(1);
+ }
+ struct stat st;
+ if (0 != fstat(fd, &st)) {
+ perror("fstat()");
+ exit(1);
+ }
+
+ plugin_data * const p = mod_staticfile_init();
+ assert(NULL != p);
+ p->conf.etags_used = 1;
+
+ request_st r;
+
+ memset(&r, 0, sizeof(request_st));
+ r.http_method = HTTP_METHOD_GET;
+ r.http_version = HTTP_VERSION_1_1;
+ r.tmp_buf = buffer_init();
+ r.conf.errh = log_error_st_init();
+ r.conf.errh->errorlog_fd = -1; /* (disable) */
+ r.conf.follow_symlink = 1;
+ buffer_copy_string_len(&r.uri.path, CONST_STR_LEN("/"));
+ array * const mimetypes = array_init(1);
+ r.conf.mimetypes = mimetypes;
+ array_set_key_value(mimetypes, fn+sizeof(fn)-8, 7,
+ CONST_STR_LEN("text/plain"));
+
+ strftime_cache_reset();
+
+ buffer_copy_string_len(&r.physical.path, fn, sizeof(fn)-1);
+ test_http_response_send_file(&r, st.st_mtime);
+
+ r.rqst_htags = 0;
+ array_reset_data_strings(&r.rqst_headers);
+
+ buffer_copy_string_len(&r.physical.path, fn, sizeof(fn)-1);
+ test_mod_staticfile_process(&r, &p->conf);
+
+ array_free(mimetypes);
+ log_error_st_free(r.conf.errh);
+ buffer_free(r.tmp_buf);
+ chunkqueue_reset(&r.write_queue);
+
+ free(r.uri.path.ptr);
+ free(r.physical.etag.ptr);
+ free(r.physical.path.ptr);
+ free(r.physical.rel_path.ptr);
+ free(r.physical.doc_root.ptr);
+
+ free(p);
+ stat_cache_free();
+ unlink(fn);
+ return 0;
+}
+
+
+/*
+ * stub functions
+ */
+
+#include "fdevent_impl.h"
+int fdevent_select_init(struct fdevents *ev) { return NULL == ev; }
+int fdevent_poll_init(struct fdevents *ev) { return NULL == ev; }
+int fdevent_linux_sysepoll_init(struct fdevents *ev) { return NULL == ev; }
+int fdevent_solaris_devpoll_init(struct fdevents *ev) { return NULL == ev; }
+int fdevent_solaris_port_init(struct fdevents *ev) { return NULL == ev; }
+int fdevent_freebsd_kqueue_init(struct fdevents *ev) { return NULL == ev; }
+int fdevent_libev_init(struct fdevents *ev) { return NULL == ev; }
+
+int config_plugin_values_init(server *srv, void *p_d, const config_plugin_keys_t *cpk, const char *mname) {
+ UNUSED(srv);
+ UNUSED(p_d);
+ UNUSED(cpk);
+ UNUSED(mname);
+ return 0;
+}
+
+int config_check_cond(request_st *r, int context_ndx) {
+ UNUSED(r);
+ UNUSED(context_ndx);
+ return 0;
+}
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index e199811b..0db1a440 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -3,7 +3,6 @@ add_executable(scgi-responder scgi-responder.c)
set(T_FILES
prepare.sh
- cachable.t
core-404-handler.t
core-condition.t
core-keepalive.t
diff --git a/tests/Makefile.am b/tests/Makefile.am
index c6c1231b..a23c519a 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -13,7 +13,6 @@ TESTS=\
CONFS=\
404-handler.conf \
- cachable.t \
condition.conf \
core-404-handler.t \
core-condition.t \
diff --git a/tests/cachable.t b/tests/cachable.t
deleted file mode 100755
index 5dfd5a3b..00000000
--- a/tests/cachable.t
+++ /dev/null
@@ -1,211 +0,0 @@
-#!/usr/bin/env perl
-BEGIN {
- # add current source dir to the include-path
- # we need this for make distcheck
- (my $srcdir = $0) =~ s,/[^/]+$,/,;
- unshift @INC, $srcdir;
-}
-
-use strict;
-use IO::Socket;
-use Test::More tests => 24;
-use LightyTest;
-
-my $tf = LightyTest->new();
-my $t;
-
-ok($tf->start_proc == 0, "Starting lighttpd") or die();
-
-## check if If-Modified-Since, If-None-Match works
-
-$t->{REQUEST} = ( <<EOF
-GET / HTTP/1.0
-If-Modified-Since: Sun, 01 Jan 1970 00:00:01 GMT
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
-ok($tf->handle_http($t) == 0, 'Conditional GET - old If-Modified-Since');
-
-$t->{REQUEST} = ( <<EOF
-GET / HTTP/1.0
-If-Modified-Since: Sun, 01 Jan 1970 00:00:01 GMT; foo
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, '+Last-Modified' => ''} ];
-ok($tf->handle_http($t) == 0, 'Conditional GET - old If-Modified-Since, comment');
-
-my $now = $t->{date};
-
-$t->{REQUEST} = ( <<EOF
-GET / HTTP/1.0
-If-Modified-Since: $now
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 304 } ];
-ok($tf->handle_http($t) == 0, 'Conditional GET - new If-Modified-Since');
-
-$t->{REQUEST} = ( <<EOF
-GET / HTTP/1.0
-If-None-Match: foo
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, '+ETag' => ''} ];
-ok($tf->handle_http($t) == 0, 'Conditional GET - old If-None-Match');
-
-my $etag = $t->{etag};
-
-$t->{REQUEST} = ( <<EOF
-GET / HTTP/1.0
-If-None-Match: $etag
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 304 } ];
-ok($tf->handle_http($t) == 0, 'Conditional GET - old If-None-Match');
-
-$t->{REQUEST} = ( <<EOF
-GET / HTTP/1.0
-If-None-Match: $etag
-If-Modified-Since: Sun, 01 Jan 1970 00:00:01 GMT; foo
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 304 } ];
-ok($tf->handle_http($t) == 0, 'Conditional GET - ETag + old Last-Modified (which should be ignored)');
-
-$t->{REQUEST} = ( <<EOF
-GET / HTTP/1.0
-If-None-Match: $etag
-If-Modified-Since: $now; foo
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 304 } ];
-ok($tf->handle_http($t) == 0, 'Conditional GET - ETag, Last-Modified + comment (which should be ignored)');
-
-$t->{REQUEST} = ( <<EOF
-GET / HTTP/1.0
-If-None-Match: Foo
-If-Modified-Since: Sun, 01 Jan 1970 00:00:01 GMT; foo
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
-ok($tf->handle_http($t) == 0, 'Conditional GET - old ETAG + old Last-Modified');
-
-$t->{REQUEST} = ( <<EOF
-GET / HTTP/1.0
-If-None-Match: $etag
-If-Modified-Since: $now foo
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 304 } ];
-ok($tf->handle_http($t) == 0, 'Conditional GET - ETag + Last-Modified + overlong timestamp (which should be ignored)');
-
-$t->{REQUEST} = ( <<EOF
-GET / HTTP/1.0
-If-None-Match: $etag
-Host: etag.example.org
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
-ok($tf->handle_http($t) == 0, 'Conditional GET - ETag + disabled etags on server side');
-
-###############
-
-ok($etag =~ /^\"(.*)\"$/, "The server must quote ETags");
-
-$t->{REQUEST} = ( <<EOF
-GET / HTTP/1.0
-If-None-Match: $1
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
-ok($tf->handle_http($t) == 0, 'The client must send a quoted ETag');
-
-$etag =~ /^(\".*)\"$/;
-$t->{REQUEST} = ( <<EOF
-GET / HTTP/1.0
-If-None-Match: $1
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
-ok($tf->handle_http($t) == 0, 'The ETag must be surrounded by quotes');
-
-$t->{REQUEST} = ( <<EOF
-GET / HTTP/1.0
-If-None-Match: *
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 304 } ];
-ok($tf->handle_http($t) == 0, 'An unquoted star matches any ETag');
-
-$t->{REQUEST} = ( <<EOF
-GET / HTTP/1.0
-If-None-Match: "*"
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
-ok($tf->handle_http($t) == 0, 'A quoted star is just a regular ETag');
-
-{
- $t->{REQUEST} = ( <<EOF
-GET / HTTP/1.0
-If-None-Match: W/$etag
-EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 304 } ];
- ok($tf->handle_http($t) == 0, 'A weak etag matches like a regular ETag for HEAD and GET');
-}
-
-$t->{REQUEST} = ( <<EOF
-GET / HTTP/1.1
-Host: www.example.org
-If-None-Match: W/$etag
-Connection: close
-Range: bytes=0-0
-EOF
-);
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.1', 'HTTP-Status' => 206, 'HTTP-Content' => '<' } ];
-ok($tf->handle_http($t) == 0, 'A weak etag does not match for ranged requests');
-
-$t->{REQUEST} = ( <<EOF
-GET / HTTP/1.0
-If-None-Match: W/"12345"
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
-ok($tf->handle_http($t) == 0, 'However, a weak ETag is not *');
-
-$t->{REQUEST} = ( <<EOF
-GET / HTTP/1.0
-If-None-Match: "12345", $etag
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 304 } ];
-ok($tf->handle_http($t) == 0, 'Client sent a list of ETags, the second matches');
-
-{
- $t->{REQUEST} = ( <<EOF
-GET / HTTP/1.0
-If-None-Match: "12345", W/$etag
-EOF
- );
- $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 304 } ];
- ok($tf->handle_http($t) == 0, 'The second provided ETag matches weakly');
-}
-
-$t->{REQUEST} = ( <<EOF
-GET / HTTP/1.0
-If-None-Match: "12345",, ,, , $etag
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 304 } ];
-ok($tf->handle_http($t) == 0, 'Broken client did get around to sending good data');
-
-$t->{REQUEST} = ( <<EOF
-GET / HTTP/1.0
-If-None-Match: "1234", $etag, "brokentrailing
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 304 } ];
-ok($tf->handle_http($t) == 0, 'Bad syntax *after* a matching ETag doesn\'t matter');
-
-ok($tf->stop_proc == 0, "Stopping lighttpd");
-
diff --git a/tests/core-request.t b/tests/core-request.t
index 8d982fc8..d30e952c 100755
--- a/tests/core-request.t
+++ b/tests/core-request.t
@@ -8,7 +8,7 @@ BEGIN {
use strict;
use IO::Socket;
-use Test::More tests => 11;
+use Test::More tests => 10;
use LightyTest;
my $tf = LightyTest->new();
@@ -76,13 +76,6 @@ $t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'Conte
ok($tf->handle_http($t) == 0, 'Content-Type - image/jpeg (upper case)');
$t->{REQUEST} = ( <<EOF
-GET /a HTTP/1.0
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'Content-Type' => 'application/octet-stream' } ];
-ok($tf->handle_http($t) == 0, 'Content-Type - unknown');
-
-$t->{REQUEST} = ( <<EOF
GET /Foo.txt HTTP/1.0
EOF
);
diff --git a/tests/core-response.t b/tests/core-response.t
index d9ea023e..1c19e85c 100755
--- a/tests/core-response.t
+++ b/tests/core-response.t
@@ -8,7 +8,7 @@ BEGIN {
use strict;
use IO::Socket;
-use Test::More tests => 13;
+use Test::More tests => 11;
use LightyTest;
my $tf = LightyTest->new();
@@ -27,21 +27,6 @@ EOF
$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.1', 'HTTP-Status' => 200, '+Date' => '' } ];
ok($tf->handle_http($t) == 0, 'Date header');
-$t->{REQUEST} = ( <<EOF
-GET / HTTP/1.0
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, '+ETag' => '' } ];
-ok($tf->handle_http($t) == 0, 'ETag is set');
-
-$t->{REQUEST} = ( <<EOF
-GET / HTTP/1.0
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'ETag' => '/^".+"$/' } ];
-ok($tf->handle_http($t) == 0, 'ETag has quotes');
-
-
## Low-Level Response-Header Parsing - Content-Length
diff --git a/tests/meson.build b/tests/meson.build
index 9ecc9192..943c1adf 100644
--- a/tests/meson.build
+++ b/tests/meson.build
@@ -13,7 +13,6 @@ env.set('srcdir', meson.current_source_dir())
env.set('top_builddir', meson.build_root())
tests = [
- 'cachable.t',
'core-404-handler.t',
'core-condition.t',
'core-keepalive.t',
diff --git a/tests/request.t b/tests/request.t
index ea8852d6..f2264486 100755
--- a/tests/request.t
+++ b/tests/request.t
@@ -8,7 +8,7 @@ BEGIN {
use strict;
use IO::Socket;
-use Test::More tests => 52;
+use Test::More tests => 44;
use LightyTest;
my $tf = LightyTest->new();
@@ -19,13 +19,6 @@ ok($tf->start_proc == 0, "Starting lighttpd") or die();
## Basic Request-Handling
$t->{REQUEST} = ( <<EOF
-GET /foobar HTTP/1.0
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 404 } ];
-ok($tf->handle_http($t) == 0, 'file not found');
-
-$t->{REQUEST} = ( <<EOF
GET /foobar?foobar HTTP/1.0
EOF
);
@@ -48,14 +41,6 @@ EOF
$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'HTTP-Content' => '12345'."\n", 'Content-Type' => 'text/html' } ];
ok($tf->handle_http($t) == 0, 'GET, content == 12345, mimetype text/html');
-$t->{REQUEST} = ( <<EOF
-GET /dummyfile.bla HTTP/1.0
-Host: 123.example.org
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'HTTP-Content' => '12345'."\n", 'Content-Type' => 'application/octet-stream' } ];
-ok($tf->handle_http($t) == 0, 'GET, content == 12345, mimetype application/octet-stream');
-
$t->{REQUEST} = ( <<EOF
POST / HTTP/1.0
@@ -445,19 +430,6 @@ ok($tf->handle_http($t) == 0, 'OPTIONS for RTSP');
my $nextyr = (gmtime(time()))[5] + 1900 + 1;
-$t->{REQUEST} = ( "GET / HTTP/1.0\r\nIf-Modified-Since: \r\n\r\n" );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
-ok($tf->handle_http($t) == 0, 'empty If-Modified-Since');
-
-$t->{REQUEST} = ( "GET / HTTP/1.0\r\nIf-Modified-Since: foobar\r\n\r\n" );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
-ok($tf->handle_http($t) == 0, 'broken If-Modified-Since');
-
-$t->{REQUEST} = ( "GET / HTTP/1.0\r\nIf-Modified-Since: this string is too long to be a valid timestamp\r\n\r\n" );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200 } ];
-ok($tf->handle_http($t) == 0, 'broken If-Modified-Since');
-
-
$t->{REQUEST} = ( <<EOF
GET /index.html HTTP/1.0
If-Modified-Since2: Sun, 01 Jan $nextyr 00:00:03 GMT
@@ -472,15 +444,7 @@ GET /index.html HTTP/1.0
If-Modified-Since: Sun, 01 Jan $nextyr 00:00:02 GMT
EOF
);
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 304, 'Content-Type' => 'text/html' } ];
-ok($tf->handle_http($t) == 0, 'If-Modified-Since');
-
-$t->{REQUEST} = ( <<EOF
-GET /index.html HTTP/1.0
-If-Modified-Since: Sun, 01 Jan $nextyr 00:00:02 GMT
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 304, '-Content-Length' => '' } ];
+$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 304, '-Content-Length' => '', 'Content-Type' => 'text/html' } ];
ok($tf->handle_http($t) == 0, 'Status 304 has no Content-Length (#1002)');
$t->{REQUEST} = ( <<EOF
@@ -493,22 +457,6 @@ $t->{SLOWREQUEST} = 1;
ok($tf->handle_http($t) == 0, 'GET, slow \\r\\n\\r\\n (#2105)');
undef $t->{SLOWREQUEST};
-print "\nPathinfo for static files\n";
-$t->{REQUEST} = ( <<EOF
-GET /image.jpg/index.php HTTP/1.0
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 200, 'Content-Type' => 'image/jpeg' } ];
-ok($tf->handle_http($t) == 0, 'static file accepting pathinfo by default');
-
-$t->{REQUEST} = ( <<EOF
-GET /image.jpg/index.php HTTP/1.0
-Host: zzz.example.org
-EOF
- );
-$t->{RESPONSE} = [ { 'HTTP-Protocol' => 'HTTP/1.0', 'HTTP-Status' => 403 } ];
-ok($tf->handle_http($t) == 0, 'static file with forbidden pathinfo');
-
$t->{REQUEST} = ( <<EOF
GET /www/abc/def HTTP/1.0
EOF