[tests] t/test_mod_staticfile
move some tests from tests/request.t to src/t/test_mod_staticfile.cmaster
parent
a0a8cf821d
commit
91472ab768
@ -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;
|
||||
}
|
@ -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");
|
||||
|
Loading…
Reference in New Issue