2008-10-25 12:53:57 +00:00
|
|
|
|
2008-11-16 20:33:53 +00:00
|
|
|
#include <lighttpd/base.h>
|
|
|
|
#include <lighttpd/plugin_core.h>
|
2008-10-25 12:53:57 +00:00
|
|
|
|
2010-09-05 11:21:42 +00:00
|
|
|
static void vrequest_job_cb(liJob *job) {
|
|
|
|
liVRequest *vr = LI_CONTAINER_OF(job, liVRequest, job);
|
|
|
|
li_vrequest_state_machine(vr);
|
|
|
|
}
|
|
|
|
|
2010-08-25 22:34:28 +00:00
|
|
|
liVRequest* li_vrequest_new(liWorker *wrk, liConInfo *coninfo) {
|
|
|
|
liServer *srv = wrk->srv;
|
2009-07-08 19:06:07 +00:00
|
|
|
liVRequest *vr = g_slice_new0(liVRequest);
|
2008-10-25 12:53:57 +00:00
|
|
|
|
2010-07-31 12:44:45 +00:00
|
|
|
vr->coninfo = coninfo;
|
2010-08-25 22:34:28 +00:00
|
|
|
vr->wrk = wrk;
|
2009-07-08 19:06:07 +00:00
|
|
|
vr->state = LI_VRS_CLEAN;
|
2008-10-25 12:53:57 +00:00
|
|
|
|
2013-05-22 15:26:33 +00:00
|
|
|
vr->backend = NULL;
|
|
|
|
vr->backend_drain = NULL;
|
|
|
|
vr->backend_source = NULL;
|
|
|
|
vr->direct_out = NULL;
|
|
|
|
|
2009-01-01 15:44:42 +00:00
|
|
|
vr->plugin_ctx = g_ptr_array_new();
|
|
|
|
g_ptr_array_set_size(vr->plugin_ctx, g_hash_table_size(srv->plugins));
|
2009-07-08 19:06:07 +00:00
|
|
|
vr->options = g_slice_copy(srv->option_def_values->len * sizeof(liOptionValue), srv->option_def_values->data);
|
2010-01-24 20:30:41 +00:00
|
|
|
vr->optionptrs = g_slice_copy(srv->optionptr_def_values->len * sizeof(liOptionPtrValue*), srv->optionptr_def_values->data);
|
|
|
|
{
|
|
|
|
guint i;
|
|
|
|
for (i = 0; i < srv->optionptr_def_values->len; i++) {
|
|
|
|
if (vr->optionptrs[i]) {
|
|
|
|
g_atomic_int_inc(&vr->optionptrs[i]->refcount);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2008-12-30 00:21:03 +00:00
|
|
|
|
2009-07-09 20:17:24 +00:00
|
|
|
li_request_init(&vr->request);
|
|
|
|
li_physical_init(&vr->physical);
|
|
|
|
li_response_init(&vr->response);
|
|
|
|
li_environment_init(&vr->env);
|
2008-10-25 12:53:57 +00:00
|
|
|
|
2013-05-22 15:26:33 +00:00
|
|
|
li_vrequest_filters_init(vr);
|
2009-12-19 21:18:10 +00:00
|
|
|
|
|
|
|
vr->in_buffer_state.flush_limit = -1; /* wait until upload is complete */
|
|
|
|
vr->in_buffer_state.split_on_file_chunks = FALSE;
|
|
|
|
|
2013-05-22 15:26:33 +00:00
|
|
|
li_action_stack_init(&vr->action_stack);
|
|
|
|
|
2010-09-05 11:21:42 +00:00
|
|
|
li_job_init(&vr->job, vrequest_job_cb);
|
2009-03-26 22:05:17 +00:00
|
|
|
|
2010-09-05 11:21:42 +00:00
|
|
|
vr->stat_cache_entries = g_ptr_array_sized_new(2);
|
2009-04-14 16:18:25 +00:00
|
|
|
|
2008-10-25 12:53:57 +00:00
|
|
|
return vr;
|
|
|
|
}
|
|
|
|
|
2009-07-09 20:17:24 +00:00
|
|
|
void li_vrequest_free(liVRequest* vr) {
|
2010-01-24 20:30:41 +00:00
|
|
|
liServer *srv = vr->wrk->srv;
|
|
|
|
|
2013-05-22 15:26:33 +00:00
|
|
|
if (NULL != vr->backend_drain) {
|
|
|
|
li_stream_reset(vr->backend_drain);
|
|
|
|
li_stream_release(vr->backend_drain);
|
|
|
|
vr->backend_drain = NULL;
|
|
|
|
}
|
|
|
|
if (NULL != vr->backend_source) {
|
|
|
|
li_stream_reset(vr->backend_source);
|
|
|
|
li_stream_release(vr->backend_source);
|
|
|
|
vr->backend_source = NULL;
|
|
|
|
vr->direct_out = NULL;
|
|
|
|
}
|
|
|
|
|
2009-07-09 20:17:24 +00:00
|
|
|
li_action_stack_clear(vr, &vr->action_stack);
|
2010-04-03 19:16:11 +00:00
|
|
|
if (vr->state != LI_VRS_CLEAN) {
|
|
|
|
li_plugins_handle_vrclose(vr);
|
2013-05-22 15:26:33 +00:00
|
|
|
vr->state = LI_VRS_CLEAN;
|
|
|
|
vr->backend = NULL;
|
2010-04-03 19:16:11 +00:00
|
|
|
}
|
2009-01-01 15:44:42 +00:00
|
|
|
g_ptr_array_free(vr->plugin_ctx, TRUE);
|
2013-05-22 15:26:33 +00:00
|
|
|
vr->plugin_ctx = NULL;
|
2008-12-31 15:23:00 +00:00
|
|
|
|
2009-07-09 20:17:24 +00:00
|
|
|
li_request_clear(&vr->request);
|
|
|
|
li_physical_clear(&vr->physical);
|
|
|
|
li_response_clear(&vr->response);
|
|
|
|
li_environment_clear(&vr->env);
|
2008-10-25 12:53:57 +00:00
|
|
|
|
2013-05-22 15:26:33 +00:00
|
|
|
li_vrequest_filters_clear(vr);
|
|
|
|
|
2009-12-19 21:18:10 +00:00
|
|
|
li_filter_buffer_on_disk_reset(&vr->in_buffer_state);
|
2008-10-25 12:53:57 +00:00
|
|
|
|
2010-09-05 11:21:42 +00:00
|
|
|
li_job_clear(&vr->job);
|
2008-12-30 20:55:00 +00:00
|
|
|
|
2010-01-24 20:30:41 +00:00
|
|
|
g_slice_free1(srv->option_def_values->len * sizeof(liOptionValue), vr->options);
|
|
|
|
{
|
|
|
|
guint i;
|
|
|
|
for (i = 0; i < srv->optionptr_def_values->len; i++) {
|
|
|
|
li_release_optionptr(srv, vr->optionptrs[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
g_slice_free1(srv->optionptr_def_values->len * sizeof(liOptionPtrValue*), vr->optionptrs);
|
2008-12-30 00:21:03 +00:00
|
|
|
|
2012-03-17 14:52:19 +00:00
|
|
|
li_log_context_set(&vr->log_context, NULL);
|
2009-03-26 22:05:17 +00:00
|
|
|
|
2009-10-05 17:41:48 +00:00
|
|
|
while (vr->stat_cache_entries->len > 0 ) {
|
|
|
|
liStatCacheEntry *sce = g_ptr_array_index(vr->stat_cache_entries, 0);
|
2009-07-09 20:17:24 +00:00
|
|
|
li_stat_cache_entry_release(vr, sce);
|
2009-03-26 22:05:17 +00:00
|
|
|
}
|
|
|
|
g_ptr_array_free(vr->stat_cache_entries, TRUE);
|
|
|
|
|
2009-07-08 19:06:07 +00:00
|
|
|
g_slice_free(liVRequest, vr);
|
2008-10-25 12:53:57 +00:00
|
|
|
}
|
|
|
|
|
2009-10-07 14:02:09 +00:00
|
|
|
void li_vrequest_reset(liVRequest *vr, gboolean keepalive) {
|
2010-01-24 20:30:41 +00:00
|
|
|
liServer *srv = vr->wrk->srv;
|
|
|
|
|
2013-05-22 15:26:33 +00:00
|
|
|
if (NULL != vr->backend_drain) {
|
|
|
|
li_stream_disconnect(vr->backend_drain);
|
|
|
|
li_stream_release(vr->backend_drain);
|
|
|
|
vr->backend_drain = NULL;
|
|
|
|
}
|
|
|
|
if (NULL != vr->backend_source) {
|
|
|
|
if (NULL == vr->backend_source->dest) {
|
|
|
|
/* wasn't connected: disconnect source */
|
|
|
|
li_stream_disconnect(vr->backend_source);
|
|
|
|
}
|
|
|
|
li_stream_disconnect_dest(vr->backend_source);
|
|
|
|
li_stream_release(vr->backend_source);
|
|
|
|
vr->backend_source = NULL;
|
|
|
|
vr->direct_out = NULL;
|
|
|
|
}
|
|
|
|
|
2009-07-09 20:17:24 +00:00
|
|
|
li_action_stack_reset(vr, &vr->action_stack);
|
2010-04-03 19:32:02 +00:00
|
|
|
if (vr->state != LI_VRS_CLEAN) {
|
|
|
|
li_plugins_handle_vrclose(vr);
|
2013-05-22 15:26:33 +00:00
|
|
|
vr->state = LI_VRS_CLEAN;
|
|
|
|
vr->backend = NULL;
|
2010-04-03 19:32:02 +00:00
|
|
|
}
|
2009-01-01 15:44:42 +00:00
|
|
|
{
|
|
|
|
gint len = vr->plugin_ctx->len;
|
|
|
|
g_ptr_array_set_size(vr->plugin_ctx, 0);
|
|
|
|
g_ptr_array_set_size(vr->plugin_ctx, len);
|
|
|
|
}
|
2008-12-31 15:23:00 +00:00
|
|
|
|
2008-10-25 12:53:57 +00:00
|
|
|
|
2009-10-07 14:02:09 +00:00
|
|
|
/* don't reset request for keep-alive tracking */
|
|
|
|
if (!keepalive) li_request_reset(&vr->request);
|
2009-07-09 20:17:24 +00:00
|
|
|
li_physical_reset(&vr->physical);
|
|
|
|
li_response_reset(&vr->response);
|
|
|
|
li_environment_reset(&vr->env);
|
2008-10-25 12:53:57 +00:00
|
|
|
|
2013-05-22 15:26:33 +00:00
|
|
|
li_vrequest_filters_reset(vr);
|
|
|
|
|
2009-12-19 21:18:10 +00:00
|
|
|
li_filter_buffer_on_disk_reset(&vr->in_buffer_state);
|
|
|
|
vr->in_buffer_state.flush_limit = -1; /* wait until upload is complete */
|
|
|
|
vr->in_buffer_state.split_on_file_chunks = FALSE;
|
|
|
|
|
2010-09-05 11:21:42 +00:00
|
|
|
li_job_reset(&vr->job);
|
2008-12-30 20:55:00 +00:00
|
|
|
|
2009-10-05 17:41:48 +00:00
|
|
|
while (vr->stat_cache_entries->len > 0 ) {
|
|
|
|
liStatCacheEntry *sce = g_ptr_array_index(vr->stat_cache_entries, 0);
|
2009-07-09 20:17:24 +00:00
|
|
|
li_stat_cache_entry_release(vr, sce);
|
2009-03-01 20:16:58 +00:00
|
|
|
}
|
|
|
|
|
2010-01-24 20:30:41 +00:00
|
|
|
memcpy(vr->options, srv->option_def_values->data, srv->option_def_values->len * sizeof(liOptionValue));
|
|
|
|
{
|
|
|
|
guint i;
|
|
|
|
for (i = 0; i < srv->optionptr_def_values->len; i++) {
|
|
|
|
liOptionPtrValue *oval = g_array_index(srv->optionptr_def_values, liOptionPtrValue*, i);
|
|
|
|
if (vr->optionptrs[i] != oval) {
|
|
|
|
li_release_optionptr(srv, vr->optionptrs[i]);
|
2010-07-11 21:53:59 +00:00
|
|
|
if (oval)
|
|
|
|
g_atomic_int_inc(&oval->refcount);
|
2010-01-24 20:30:41 +00:00
|
|
|
vr->optionptrs[i] = oval;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2012-03-17 14:52:19 +00:00
|
|
|
|
|
|
|
li_log_context_set(&vr->log_context, NULL);
|
2008-10-25 12:53:57 +00:00
|
|
|
}
|
|
|
|
|
2009-07-09 20:17:24 +00:00
|
|
|
void li_vrequest_error(liVRequest *vr) {
|
2009-07-08 19:06:07 +00:00
|
|
|
vr->state = LI_VRS_ERROR;
|
2013-05-22 15:26:33 +00:00
|
|
|
|
|
|
|
li_stream_reset(vr->coninfo->req);
|
|
|
|
li_stream_reset(vr->coninfo->resp);
|
|
|
|
|
2009-07-09 20:17:24 +00:00
|
|
|
li_vrequest_joblist_append(vr);
|
2008-10-25 12:53:57 +00:00
|
|
|
}
|
|
|
|
|
2009-07-09 20:17:24 +00:00
|
|
|
void li_vrequest_backend_error(liVRequest *vr, liBackendError berror) {
|
2013-05-22 15:26:33 +00:00
|
|
|
if (vr->state < LI_VRS_READ_CONTENT) {
|
|
|
|
vr->action_stack.backend_failed = TRUE;
|
|
|
|
vr->action_stack.backend_error = berror;
|
|
|
|
li_vrequest_joblist_append(vr);
|
|
|
|
} else {
|
|
|
|
vr->response.http_status = 503;
|
|
|
|
li_vrequest_error(vr);
|
|
|
|
}
|
2008-12-31 13:36:24 +00:00
|
|
|
}
|
|
|
|
|
2009-07-09 20:17:24 +00:00
|
|
|
void li_vrequest_backend_overloaded(liVRequest *vr) {
|
2010-08-19 15:24:07 +00:00
|
|
|
li_vrequest_backend_error(vr, LI_BACKEND_OVERLOAD);
|
2009-01-01 15:44:42 +00:00
|
|
|
}
|
2009-07-09 20:17:24 +00:00
|
|
|
void li_vrequest_backend_dead(liVRequest *vr) {
|
2010-08-19 15:24:07 +00:00
|
|
|
li_vrequest_backend_error(vr, LI_BACKEND_DEAD);
|
2008-12-31 13:36:24 +00:00
|
|
|
}
|
|
|
|
|
2009-01-01 15:44:42 +00:00
|
|
|
|
2009-10-07 14:02:09 +00:00
|
|
|
/* resets fields which weren't reset in favor of keep-alive tracking */
|
|
|
|
void li_vrequest_start(liVRequest *vr) {
|
|
|
|
if (LI_VRS_CLEAN == vr->state) {
|
|
|
|
li_request_reset(&vr->request);
|
|
|
|
}
|
2010-01-03 16:39:26 +00:00
|
|
|
|
2013-05-18 13:27:59 +00:00
|
|
|
vr->ts_started = li_cur_ts(vr->wrk);
|
2009-10-07 14:02:09 +00:00
|
|
|
}
|
|
|
|
|
2008-10-25 12:53:57 +00:00
|
|
|
/* received all request headers */
|
2009-07-09 20:17:24 +00:00
|
|
|
void li_vrequest_handle_request_headers(liVRequest *vr) {
|
2009-07-08 19:06:07 +00:00
|
|
|
if (LI_VRS_CLEAN == vr->state) {
|
|
|
|
vr->state = LI_VRS_HANDLE_REQUEST_HEADERS;
|
2008-10-25 12:53:57 +00:00
|
|
|
}
|
2009-07-09 20:17:24 +00:00
|
|
|
li_vrequest_joblist_append(vr);
|
2008-10-25 12:53:57 +00:00
|
|
|
}
|
|
|
|
|
2013-05-22 15:26:33 +00:00
|
|
|
/* response completely ready */
|
|
|
|
gboolean li_vrequest_handle_direct(liVRequest *vr) {
|
|
|
|
if (li_vrequest_handle_indirect(vr, NULL)) {
|
2013-05-18 13:27:59 +00:00
|
|
|
li_vrequest_indirect_connect(vr, li_stream_null_new(&vr->wrk->loop), li_stream_plug_new(&vr->wrk->loop));
|
2008-10-25 12:53:57 +00:00
|
|
|
|
2013-05-22 15:26:33 +00:00
|
|
|
/* release reference from _new */
|
|
|
|
li_stream_release(vr->backend_drain);
|
|
|
|
li_stream_release(vr->backend_source);
|
2008-10-25 12:53:57 +00:00
|
|
|
|
2013-05-22 15:26:33 +00:00
|
|
|
vr->direct_out = vr->backend_source->out;
|
|
|
|
vr->direct_out->is_closed = TRUE;
|
|
|
|
|
|
|
|
li_vrequest_indirect_headers_ready(vr);
|
2008-10-25 12:53:57 +00:00
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
} else {
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* handle request over time */
|
2009-07-09 20:17:24 +00:00
|
|
|
gboolean li_vrequest_handle_indirect(liVRequest *vr, liPlugin *p) {
|
2009-07-08 19:06:07 +00:00
|
|
|
if (vr->state < LI_VRS_READ_CONTENT) {
|
|
|
|
vr->state = LI_VRS_READ_CONTENT;
|
2009-01-01 15:44:42 +00:00
|
|
|
vr->backend = p;
|
2013-05-22 15:26:33 +00:00
|
|
|
|
2008-10-25 12:53:57 +00:00
|
|
|
return TRUE;
|
|
|
|
} else {
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-05-22 15:26:33 +00:00
|
|
|
void li_vrequest_indirect_connect(liVRequest *vr, liStream *backend_drain, liStream* backend_source) {
|
|
|
|
assert(LI_VRS_READ_CONTENT == vr->state);
|
|
|
|
assert(NULL != backend_drain);
|
|
|
|
|
|
|
|
li_stream_acquire(backend_drain);
|
|
|
|
vr->backend_drain = backend_drain;
|
|
|
|
|
|
|
|
/* connect in-queue */
|
|
|
|
if (NULL != vr->filters_in_last) {
|
|
|
|
li_stream_connect(vr->filters_in_last, vr->backend_drain);
|
|
|
|
li_stream_connect(vr->coninfo->req, vr->filters_in_first);
|
|
|
|
} else {
|
|
|
|
/* no filters */
|
|
|
|
li_stream_connect(vr->coninfo->req, vr->backend_drain);
|
|
|
|
}
|
|
|
|
|
|
|
|
li_stream_acquire(backend_source);
|
|
|
|
vr->backend_source = backend_source;
|
|
|
|
|
|
|
|
li_chunkqueue_set_limit(backend_source->out, vr->coninfo->resp->out->limit);
|
|
|
|
|
|
|
|
li_vrequest_joblist_append(vr);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* received all response headers/status code - call once from your indirect handler */
|
|
|
|
void li_vrequest_indirect_headers_ready(liVRequest* vr) {
|
|
|
|
assert(LI_VRS_HANDLE_RESPONSE_HEADERS > vr->state);
|
|
|
|
|
|
|
|
vr->state = LI_VRS_HANDLE_RESPONSE_HEADERS;
|
|
|
|
|
|
|
|
li_vrequest_joblist_append(vr);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2009-07-09 20:17:24 +00:00
|
|
|
gboolean li_vrequest_is_handled(liVRequest *vr) {
|
2009-07-08 19:06:07 +00:00
|
|
|
return vr->state >= LI_VRS_READ_CONTENT;
|
2009-03-17 10:42:50 +00:00
|
|
|
}
|
|
|
|
|
2009-09-28 22:24:37 +00:00
|
|
|
static liHandlerResult vrequest_do_handle_actions(liVRequest *vr) {
|
2009-07-09 20:17:24 +00:00
|
|
|
liHandlerResult res = li_action_execute(vr);
|
2008-10-25 12:53:57 +00:00
|
|
|
switch (res) {
|
2009-07-08 19:06:07 +00:00
|
|
|
case LI_HANDLER_GO_ON:
|
|
|
|
if (vr->state == LI_VRS_HANDLE_REQUEST_HEADERS) {
|
2008-10-25 12:53:57 +00:00
|
|
|
/* request not handled */
|
2009-07-09 20:17:24 +00:00
|
|
|
li_vrequest_handle_direct(vr);
|
2009-09-15 19:30:25 +00:00
|
|
|
if (vr->request.http_method == LI_HTTP_METHOD_OPTIONS) {
|
|
|
|
vr->response.http_status = 200;
|
|
|
|
li_http_header_append(vr->response.headers, CONST_STR_LEN("Allow"), CONST_STR_LEN("OPTIONS, GET, HEAD, POST"));
|
|
|
|
} else {
|
|
|
|
vr->response.http_status = 404;
|
|
|
|
if (CORE_OPTION(LI_CORE_OPTION_DEBUG_REQUEST_HANDLING).boolean) {
|
|
|
|
VR_DEBUG(vr, "%s", "actions didn't handle request");
|
|
|
|
}
|
2009-03-17 13:27:31 +00:00
|
|
|
}
|
2009-09-28 22:24:37 +00:00
|
|
|
return LI_HANDLER_GO_ON;
|
2008-10-25 12:53:57 +00:00
|
|
|
}
|
|
|
|
/* otherwise state already changed */
|
|
|
|
break;
|
2009-07-08 19:06:07 +00:00
|
|
|
case LI_HANDLER_COMEBACK:
|
2009-07-09 20:17:24 +00:00
|
|
|
li_vrequest_joblist_append(vr); /* come back later */
|
2009-09-28 22:24:37 +00:00
|
|
|
return LI_HANDLER_COMEBACK;
|
2009-07-08 19:06:07 +00:00
|
|
|
case LI_HANDLER_WAIT_FOR_EVENT:
|
2009-09-28 22:24:37 +00:00
|
|
|
return LI_HANDLER_WAIT_FOR_EVENT;
|
2009-07-08 19:06:07 +00:00
|
|
|
case LI_HANDLER_ERROR:
|
2009-09-28 22:24:37 +00:00
|
|
|
return LI_HANDLER_ERROR;
|
2008-10-25 12:53:57 +00:00
|
|
|
}
|
2009-09-28 22:24:37 +00:00
|
|
|
return LI_HANDLER_GO_ON;
|
2008-10-25 12:53:57 +00:00
|
|
|
}
|
|
|
|
|
2009-07-09 20:17:24 +00:00
|
|
|
void li_vrequest_state_machine(liVRequest *vr) {
|
2013-05-22 15:26:33 +00:00
|
|
|
gboolean done;
|
2008-10-25 12:53:57 +00:00
|
|
|
do {
|
2013-05-22 15:26:33 +00:00
|
|
|
done = TRUE;
|
|
|
|
|
2008-10-25 12:53:57 +00:00
|
|
|
switch (vr->state) {
|
2009-07-08 19:06:07 +00:00
|
|
|
case LI_VRS_CLEAN:
|
2008-10-25 12:53:57 +00:00
|
|
|
break;
|
|
|
|
|
2009-07-08 19:06:07 +00:00
|
|
|
case LI_VRS_HANDLE_REQUEST_HEADERS:
|
|
|
|
if (CORE_OPTION(LI_CORE_OPTION_DEBUG_REQUEST_HANDLING).boolean) {
|
2008-12-30 13:24:33 +00:00
|
|
|
VR_DEBUG(vr, "%s", "handle request header");
|
2008-10-25 12:53:57 +00:00
|
|
|
}
|
2009-09-28 22:24:37 +00:00
|
|
|
switch (vrequest_do_handle_actions(vr)) {
|
|
|
|
case LI_HANDLER_GO_ON:
|
|
|
|
break;
|
|
|
|
case LI_HANDLER_COMEBACK:
|
|
|
|
li_vrequest_joblist_append(vr); /* come back later */
|
|
|
|
return;
|
|
|
|
case LI_HANDLER_WAIT_FOR_EVENT:
|
2013-05-22 15:26:33 +00:00
|
|
|
return;
|
2009-09-28 22:24:37 +00:00
|
|
|
case LI_HANDLER_ERROR:
|
2011-01-10 19:00:44 +00:00
|
|
|
li_vrequest_error(vr);
|
2009-09-28 22:24:37 +00:00
|
|
|
return;
|
|
|
|
}
|
2011-01-10 19:00:44 +00:00
|
|
|
|
2013-05-22 15:26:33 +00:00
|
|
|
done = FALSE;
|
2011-01-10 19:00:44 +00:00
|
|
|
|
2008-10-25 12:53:57 +00:00
|
|
|
break;
|
|
|
|
|
2009-07-08 19:06:07 +00:00
|
|
|
case LI_VRS_READ_CONTENT:
|
2009-09-29 12:52:59 +00:00
|
|
|
if (CORE_OPTION(LI_CORE_OPTION_DEBUG_REQUEST_HANDLING).boolean) {
|
|
|
|
VR_DEBUG(vr, "%s", "read content");
|
|
|
|
}
|
2008-10-25 12:53:57 +00:00
|
|
|
break;
|
|
|
|
|
2009-07-08 19:06:07 +00:00
|
|
|
case LI_VRS_HANDLE_RESPONSE_HEADERS:
|
2009-09-29 12:52:59 +00:00
|
|
|
if (CORE_OPTION(LI_CORE_OPTION_DEBUG_REQUEST_HANDLING).boolean) {
|
|
|
|
VR_DEBUG(vr, "%s", "handle response header");
|
|
|
|
}
|
2009-09-28 22:24:37 +00:00
|
|
|
switch (vrequest_do_handle_actions(vr)) {
|
|
|
|
case LI_HANDLER_GO_ON:
|
|
|
|
break;
|
|
|
|
case LI_HANDLER_COMEBACK:
|
2013-05-22 15:26:33 +00:00
|
|
|
li_vrequest_joblist_append(vr); /* come back later */
|
2009-09-28 22:24:37 +00:00
|
|
|
return;
|
|
|
|
case LI_HANDLER_WAIT_FOR_EVENT:
|
2013-05-22 15:26:33 +00:00
|
|
|
return;
|
2009-07-08 19:06:07 +00:00
|
|
|
case LI_HANDLER_ERROR:
|
2009-07-09 20:17:24 +00:00
|
|
|
li_vrequest_error(vr);
|
2011-01-10 19:00:44 +00:00
|
|
|
return;
|
2008-10-25 12:53:57 +00:00
|
|
|
}
|
2013-05-22 15:26:33 +00:00
|
|
|
|
|
|
|
if (LI_VRS_HANDLE_RESPONSE_HEADERS != vr->state) break;
|
|
|
|
|
2011-01-10 19:00:44 +00:00
|
|
|
vr->state = LI_VRS_WRITE_CONTENT;
|
2013-05-22 15:26:33 +00:00
|
|
|
|
|
|
|
/* connect out-queue to signal that the headers are ready */
|
|
|
|
if (NULL != vr->direct_out) vr->direct_out->is_closed = TRUE; /* make sure this is closed for direct responses */
|
|
|
|
if (NULL != vr->filters_out_last) {
|
|
|
|
li_stream_connect(vr->backend_source, vr->filters_out_first);
|
|
|
|
li_stream_connect(vr->filters_out_last, vr->coninfo->resp);
|
|
|
|
} else {
|
|
|
|
/* no filters */
|
|
|
|
li_stream_connect(vr->backend_source, vr->coninfo->resp);
|
|
|
|
}
|
|
|
|
|
|
|
|
done = FALSE;
|
2008-10-25 12:53:57 +00:00
|
|
|
break;
|
|
|
|
|
2009-07-08 19:06:07 +00:00
|
|
|
case LI_VRS_WRITE_CONTENT:
|
2009-09-29 12:52:59 +00:00
|
|
|
if (CORE_OPTION(LI_CORE_OPTION_DEBUG_REQUEST_HANDLING).boolean) {
|
|
|
|
VR_DEBUG(vr, "%s", "write content");
|
|
|
|
}
|
2008-10-25 12:53:57 +00:00
|
|
|
break;
|
|
|
|
|
2009-07-08 19:06:07 +00:00
|
|
|
case LI_VRS_ERROR:
|
2009-09-29 12:52:59 +00:00
|
|
|
if (CORE_OPTION(LI_CORE_OPTION_DEBUG_REQUEST_HANDLING).boolean) {
|
|
|
|
VR_DEBUG(vr, "%s", "error");
|
|
|
|
}
|
2013-05-22 15:26:33 +00:00
|
|
|
vr->coninfo->callbacks->handle_response_error(vr);
|
|
|
|
return;
|
2008-10-25 12:53:57 +00:00
|
|
|
}
|
|
|
|
} while (!done);
|
|
|
|
}
|
|
|
|
|
2009-07-09 20:17:24 +00:00
|
|
|
void li_vrequest_joblist_append(liVRequest *vr) {
|
2013-05-18 13:27:59 +00:00
|
|
|
li_job_later(&vr->wrk->loop.jobqueue, &vr->job);
|
2008-10-25 12:53:57 +00:00
|
|
|
}
|
2009-01-05 21:24:54 +00:00
|
|
|
|
2010-09-05 11:21:42 +00:00
|
|
|
liJobRef* li_vrequest_get_ref(liVRequest *vr) {
|
2013-05-18 13:27:59 +00:00
|
|
|
return li_job_ref(&vr->wrk->loop.jobqueue, &vr->job);
|
2009-04-14 16:18:25 +00:00
|
|
|
}
|
|
|
|
|
2009-07-09 20:17:24 +00:00
|
|
|
gboolean li_vrequest_redirect(liVRequest *vr, GString *uri) {
|
|
|
|
if (!li_vrequest_handle_direct(vr))
|
2009-03-01 20:16:58 +00:00
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
vr->response.http_status = 301;
|
2009-07-09 20:17:24 +00:00
|
|
|
li_http_header_overwrite(vr->response.headers, CONST_STR_LEN("Location"), GSTR_LEN(uri));
|
2009-03-01 20:16:58 +00:00
|
|
|
|
|
|
|
return TRUE;
|
2009-03-11 15:57:07 +00:00
|
|
|
}
|
2009-11-15 20:59:16 +00:00
|
|
|
|
|
|
|
gboolean li_vrequest_redirect_directory(liVRequest *vr) {
|
|
|
|
GString *uri = vr->wrk->tmp_str;
|
|
|
|
|
|
|
|
/* redirect to scheme + host + path + / + querystring if directory without trailing slash */
|
|
|
|
/* TODO: local addr if HTTP 1.0 without host header, url encoding */
|
|
|
|
|
|
|
|
if (li_vrequest_is_handled(vr)) return FALSE;
|
|
|
|
|
|
|
|
g_string_truncate(uri, 0);
|
|
|
|
g_string_append_len(uri, GSTR_LEN(vr->request.uri.scheme));
|
|
|
|
g_string_append_len(uri, CONST_STR_LEN("://"));
|
|
|
|
if (vr->request.uri.authority->len > 0) {
|
|
|
|
g_string_append_len(uri, GSTR_LEN(vr->request.uri.authority));
|
|
|
|
} else {
|
2010-07-31 12:44:45 +00:00
|
|
|
g_string_append_len(uri, GSTR_LEN(vr->coninfo->local_addr_str));
|
2009-11-15 20:59:16 +00:00
|
|
|
}
|
|
|
|
g_string_append_len(uri, GSTR_LEN(vr->request.uri.raw_orig_path));
|
|
|
|
g_string_append_c(uri, '/');
|
|
|
|
if (vr->request.uri.query->len) {
|
|
|
|
g_string_append_c(uri, '?');
|
|
|
|
g_string_append_len(uri, GSTR_LEN(vr->request.uri.query));
|
|
|
|
}
|
|
|
|
|
|
|
|
return li_vrequest_redirect(vr, uri);
|
|
|
|
}
|
2010-07-31 12:44:45 +00:00
|
|
|
|
|
|
|
static void update_stats_avg(ev_tstamp now, liConInfo *coninfo) {
|
|
|
|
if ((now - coninfo->stats.last_avg) >= 5.0) {
|
|
|
|
coninfo->stats.bytes_out_5s_diff = coninfo->stats.bytes_out - coninfo->stats.bytes_out_5s;
|
|
|
|
coninfo->stats.bytes_out_5s = coninfo->stats.bytes_out;
|
|
|
|
coninfo->stats.bytes_in_5s_diff = coninfo->stats.bytes_in - coninfo->stats.bytes_in_5s;
|
|
|
|
coninfo->stats.bytes_in_5s = coninfo->stats.bytes_in;
|
|
|
|
coninfo->stats.last_avg = now;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void li_vrequest_update_stats_in(liVRequest *vr, goffset transferred) {
|
|
|
|
liConInfo *coninfo = vr->coninfo;
|
|
|
|
vr->wrk->stats.bytes_in += transferred;
|
|
|
|
coninfo->stats.bytes_in += transferred;
|
|
|
|
|
2013-05-18 13:27:59 +00:00
|
|
|
update_stats_avg(li_cur_ts(vr->wrk), coninfo);
|
2010-07-31 12:44:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void li_vrequest_update_stats_out(liVRequest *vr, goffset transferred) {
|
|
|
|
liConInfo *coninfo = vr->coninfo;
|
|
|
|
vr->wrk->stats.bytes_out += transferred;
|
|
|
|
coninfo->stats.bytes_out += transferred;
|
|
|
|
|
2013-05-18 13:27:59 +00:00
|
|
|
update_stats_avg(li_cur_ts(vr->wrk), coninfo);
|
2010-07-31 12:44:45 +00:00
|
|
|
}
|