summaryrefslogtreecommitdiff
path: root/src/mod_fastcgi.c
diff options
context:
space:
mode:
authorStefan Bühler <stbuehler@web.de>2009-06-11 12:35:00 +0000
committerStefan Bühler <stbuehler@web.de>2009-06-11 12:35:00 +0000
commitad1e80e5afc0a3d16c8d820bdaacf491163f8615 (patch)
treeab5c223d88a3e2766e080c63c1301f6f8fd1bcbb /src/mod_fastcgi.c
parent59eaedf353eb1c3e008840bfbb651d714295eeb4 (diff)
downloadlighttpd-git-ad1e80e5afc0a3d16c8d820bdaacf491163f8615.tar.gz
Add X-Sendfile-Range feature (fixes #2005)
git-svn-id: svn://svn.lighttpd.net/lighttpd/branches/lighttpd-1.4.x@2531 152afb58-edef-0310-8abb-c4023f1b3aa9
Diffstat (limited to 'src/mod_fastcgi.c')
-rw-r--r--src/mod_fastcgi.c39
1 files changed, 34 insertions, 5 deletions
diff --git a/src/mod_fastcgi.c b/src/mod_fastcgi.c
index 0fbfebf5..83cae360 100644
--- a/src/mod_fastcgi.c
+++ b/src/mod_fastcgi.c
@@ -2554,22 +2554,51 @@ static int fcgi_demux_response(server *srv, handler_ctx *hctx) {
stat_cache_entry *sce;
if (HANDLER_ERROR != stat_cache_get_entry(srv, con, ds->value, &sce)) {
- data_string *dcls;
+ data_string *dcls, *dsr;
+ off_t start = 0, end = sce->st.st_size, len;
if (NULL == (dcls = (data_string *)array_get_unused_element(con->response.headers, TYPE_STRING))) {
dcls = data_response_init();
}
/* found */
- http_chunk_append_file(srv, con, ds->value, 0, sce->st.st_size);
+ /* Assume we should serve from the beginning to the end of the file. */
+ /* If they gave us X-Sendfile-Range, adjust portion to serve. */
+ /* X-Sendfile-Range: header must include start offset, may include end offset, must end after the last offset */
+ if (NULL != (dsr = (data_string *) array_get_element(con->response.headers, "X-Sendfile-Range"))) {
+ char *end_part = NULL, *final_part = NULL;
+ start = strtoll(dsr->value->ptr, &end_part, 10);
+ if (start < 0 || end_part == ds->value->ptr) {
+ start = 0;
+ log_error_write(srv, __FILE__, __LINE__, "sb",
+ "Invalid X-Sendfile-Range header:",
+ dsr->value);
+ } else if (end_part && *end_part) {
+ end = strtoll(end_part, &final_part, 10);
+ if (end < 0 || end_part == final_part || !final_part || *final_part || start > end) {
+ start = 0;
+ end = sce->st.st_size;
+ log_error_write(srv, __FILE__, __LINE__, "sb",
+ "Invalid X-Sendfile-Range header:",
+ dsr->value);
+ } else {
+ if (end > sce->st.st_size) end = sce->st.st_size;
+ if (start > end) start = end;
+ }
+ } else {
+ if (start > end) start = end;
+ }
+ }
+ len = end - start;
+ if (len != 0) http_chunk_append_file(srv, con, ds->value, start, len);
hctx->send_content_body = 0; /* ignore the content */
joblist_append(srv, con);
- buffer_copy_string_len(dcls->key, "Content-Length", sizeof("Content-Length")-1);
- buffer_copy_off_t(dcls->value, sce->st.st_size);
+ buffer_copy_string_len(dcls->key, CONST_STR_LEN("Content-Length"));
+ buffer_copy_off_t(dcls->value, len);
dcls = (data_string*) array_replace(con->response.headers, (data_unset *)dcls);
if (dcls) dcls->free((data_unset*)dcls);
con->parsed_response |= HTTP_CONTENT_LENGTH;
- con->response.content_length = sce->st.st_size;
+ con->response.content_length = len;
} else {
log_error_write(srv, __FILE__, __LINE__, "sb",
"send-file error: couldn't get stat_cache entry for:",