static ngx_int_t ngx_http_lua_header_filter(ngx_http_request_t *r) { ngx_http_lua_loc_conf_t *llcf; ngx_http_lua_ctx_t *ctx; ngx_int_t rc; ngx_http_cleanup_t *cln; uint8_t old_context; ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "lua header filter for user lua code, uri \"%V\"", &r->uri); llcf = ngx_http_get_module_loc_conf(r, ngx_http_lua_module); if (llcf->body_filter_handler) { r->filter_need_in_memory = 1; } if (llcf->header_filter_handler == NULL) { dd("no header filter handler found"); return ngx_http_next_header_filter(r); } ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module); dd("ctx = %p", ctx); if (ctx == NULL) { ctx = ngx_http_lua_create_ctx(r); if (ctx == NULL) { return NGX_ERROR; } } if (ctx->cleanup == NULL) { cln = ngx_http_cleanup_add(r, 0); if (cln == NULL) { return NGX_ERROR; } cln->handler = ngx_http_lua_request_cleanup; cln->data = r; ctx->cleanup = &cln->handler; } old_context = ctx->context; ctx->context = NGX_HTTP_LUA_CONTEXT_HEADER_FILTER; dd("calling header filter handler"); rc = llcf->header_filter_handler(r); ctx->context = old_context; if (rc != NGX_OK) { dd("calling header filter handler rc %d", (int)rc); return NGX_ERROR; } return ngx_http_next_header_filter(r); }
static ngx_int_t subscriber_authorize_callback(ngx_http_request_t *r, void *data, ngx_int_t rc) { nchan_subrequest_data_t *d = data; ngx_event_t *timer; if (rc == NGX_HTTP_CLIENT_CLOSED_REQUEST) { d->sub->fn->release(d->sub, 1); //subscriber will be cleaned up and destroyed because this happens before the //subscriber's sudden_abort_handler is called } else { ngx_http_cleanup_t *cln = ngx_http_cleanup_add(r, 0); if(!cln) { return NGX_ERROR; } d->rc = rc; d->http_response_code = r->headers_out.status; d->timer_cleanup = cln; if((timer = ngx_pcalloc(r->pool, sizeof(*timer))) == NULL) { return NGX_ERROR; } timer->handler = subscriber_authorize_timer_callback_handler; timer->log = d->sub->request->connection->log; timer->data = data; cln->data = timer; cln->handler = (ngx_http_cleanup_pt )subscriber_authorize_timer_callback_cleanup; ngx_add_timer(timer, 0); //not sure if this needs to be done like this, but i'm just playing it safe here. } return NGX_OK; }
ngx_int_t ngx_push_longpoll_subscriber_enqueue(ngx_http_push_channel_t *channel, ngx_http_push_subscriber_t *subscriber, ngx_int_t subscriber_timeout) { ngx_http_cleanup_t *cln; ngx_http_push_subscriber_cleanup_t *clndata; ngx_http_request_t *r = subscriber->request; //attach a cleaner to remove the request from the channel and handle shared buffer deallocation. if ((cln=ngx_http_cleanup_add(r, sizeof(*clndata))) == NULL) { //make sure we can. return NGX_ERROR; } cln->handler = (ngx_http_cleanup_pt) ngx_http_push_subscriber_cleanup; clndata = (ngx_http_push_subscriber_cleanup_t *) cln->data; clndata->channel=channel; clndata->subscriber=subscriber; clndata->buf_use_count=0; clndata->buf=NULL; clndata->rchain=NULL; clndata->rpool=NULL; subscriber->clndata=clndata; //set up subscriber timeout event ngx_memzero(&subscriber->event, sizeof(subscriber->event)); if (subscriber_timeout > 0) { subscriber->event.handler = ngx_http_push_clean_timeouted_subscriber; subscriber->event.data = subscriber; subscriber->event.log = r->connection->log; ngx_add_timer(&subscriber->event, subscriber_timeout * 1000); } r->read_event_handler = ngx_http_test_reading; r->write_event_handler = ngx_http_request_empty_handler; r->main->count++; //this is the right way to hold and finalize the request... maybe //r->keepalive = 1; //stayin' alive!! return NGX_OK; }
static void nchan_output_reserve_message_queue(ngx_http_request_t *r, nchan_msg_t *msg) { nchan_request_ctx_t *ctx = ngx_http_get_module_ctx(r, ngx_nchan_module); ngx_http_cleanup_t *cln; if(msg->storage != NCHAN_MSG_SHARED) { if((msg = nchan_msg_derive_alloc(msg)) == NULL) { ERR("Coudln't alloc derived msg for output_reserve_message_queue"); return; } } if(!ctx->reserved_msg_queue) { if((ctx->reserved_msg_queue = ngx_palloc(r->pool, sizeof(*ctx->reserved_msg_queue))) == NULL) { ERR("Coudln't palloc reserved_msg_queue"); return; } nchan_reuse_queue_init(ctx->reserved_msg_queue, offsetof(rsvmsg_queue_t, prev), offsetof(rsvmsg_queue_t, next), rsvmsg_queue_palloc, rsvmsg_queue_release, r); if((cln = ngx_http_cleanup_add(r, 0)) == NULL) { ERR("Unable to add request cleanup for reserved_msg_queue queue"); assert(0); return; } cln->data = ctx; cln->handler = nchan_reserve_msg_cleanup; } rsvmsg_queue_t *qmsg = nchan_reuse_queue_push(ctx->reserved_msg_queue); qmsg->msg = msg; msg_reserve(msg, "output reservation"); }
static ngx_int_t ngx_http_lua_set_by_lua_init(ngx_http_request_t *r) { lua_State *L; ngx_http_lua_ctx_t *ctx; ngx_http_cleanup_t *cln; ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module); if (ctx == NULL) { ctx = ngx_http_lua_create_ctx(r); if (ctx == NULL) { return NGX_ERROR; } } else { L = ngx_http_lua_get_lua_vm(r, ctx); ngx_http_lua_reset_ctx(r, L, ctx); } if (ctx->cleanup == NULL) { cln = ngx_http_cleanup_add(r, 0); if (cln == NULL) { return NGX_ERROR; } cln->handler = ngx_http_lua_request_cleanup_handler; cln->data = ctx; ctx->cleanup = &cln->handler; } ctx->context = NGX_HTTP_LUA_CONTEXT_SET; return NGX_OK; }
subscriber_t *longpoll_subscriber_create(ngx_http_request_t *r, nchan_msg_id_t *msg_id) { DBG("create for req %p", r); full_subscriber_t *fsub; //TODO: allocate from pool (but not the request's pool) if((fsub = ngx_alloc(sizeof(*fsub), ngx_cycle->log)) == NULL) { ERR("Unable to allocate"); assert(0); return NULL; } nchan_subscriber_init(&fsub->sub, &new_longpoll_sub, r, msg_id); fsub->privdata = NULL; fsub->data.cln = NULL; fsub->data.finalize_request = 1; fsub->data.holding = 0; fsub->data.act_as_intervalpoll = 0; nchan_subscriber_init_timeout_timer(&fsub->sub, &fsub->data.timeout_ev); fsub->data.dequeue_handler = empty_handler; fsub->data.dequeue_handler_data = NULL; fsub->data.already_responded = 0; fsub->data.awaiting_destruction = 0; if(fsub->sub.cf->longpoll_multimsg) { nchan_request_ctx_t *ctx = ngx_http_get_module_ctx(r, ngx_nchan_module); fsub->sub.dequeue_after_response = 0; ctx->bcp = ngx_palloc(r->pool, sizeof(nchan_bufchain_pool_t)); nchan_bufchain_pool_init(ctx->bcp, r->pool); } fsub->data.multimsg_first = NULL; fsub->data.multimsg_last = NULL; #if NCHAN_SUBSCRIBER_LEAK_DEBUG subscriber_debug_add(&fsub->sub); //set debug label fsub->sub.lbl = ngx_calloc(r->uri.len+1, ngx_cycle->log); ngx_memcpy(fsub->sub.lbl, r->uri.data, r->uri.len); #endif //http request sudden close cleanup if((fsub->data.cln = ngx_http_cleanup_add(r, 0)) == NULL) { ERR("Unable to add request cleanup for longpoll subscriber"); assert(0); return NULL; } fsub->data.cln->data = fsub; fsub->data.cln->handler = (ngx_http_cleanup_pt )sudden_abort_handler; DBG("%p created for request %p", &fsub->sub, r); return &fsub->sub; }
static ngx_int_t longpoll_set_dequeue_callback(subscriber_t *self, subscriber_callback_pt cb, void *privdata) { full_subscriber_t *fsub = (full_subscriber_t *)self; if(fsub->data.cln == NULL) { fsub->data.cln = ngx_http_cleanup_add(fsub->sub.request, 0); fsub->data.cln->data = self; fsub->data.cln->handler = (ngx_http_cleanup_pt )request_cleanup_handler; } fsub->data.dequeue_handler = cb; fsub->data.dequeue_handler_data = privdata; return NGX_OK; }
static ngx_int_t ngx_http_groonga_handler_create_data(ngx_http_request_t *r, ngx_http_groonga_handler_data_t **data_return) { ngx_int_t rc; ngx_http_groonga_loc_conf_t *location_conf; ngx_http_cleanup_t *cleanup; ngx_http_groonga_handler_data_t *data; grn_ctx *context; location_conf = ngx_http_get_module_loc_conf(r, ngx_http_groonga_module); cleanup = ngx_http_cleanup_add(r, sizeof(ngx_http_groonga_handler_data_t)); cleanup->handler = ngx_http_groonga_handler_cleanup; data = cleanup->data; *data_return = data; context = &(data->context); rc = ngx_http_groonga_context_init(context, location_conf, r->pool, r->connection->log); if (rc != NGX_OK) { return rc; } data->initialized = GRN_TRUE; data->raw.processed = GRN_FALSE; data->raw.header_sent = GRN_FALSE; data->raw.r = r; data->raw.rc = NGX_OK; data->raw.free_chain = NULL; data->raw.busy_chain = NULL; GRN_TEXT_INIT(&(data->typed.head), GRN_NO_FLAGS); GRN_TEXT_INIT(&(data->typed.body), GRN_NO_FLAGS); GRN_TEXT_INIT(&(data->typed.foot), GRN_NO_FLAGS); grn_ctx_use(context, grn_ctx_db(&(location_conf->context))); rc = ngx_http_groonga_context_check_error(r->connection->log, context); if (rc != NGX_OK) { return rc; } grn_ctx_recv_handler_set(context, ngx_http_groonga_context_receive_handler, data); return NGX_OK; }
static ngx_int_t ngx_http_ip_blacklist_request_cleanup_init(ngx_http_request_t *r) { ngx_http_cleanup_t *cln; cln = ngx_http_cleanup_add(r, 0); if (cln == NULL) { return NGX_ERROR; } cln->handler = ngx_http_ip_blacklist_cleanup; cln->data = r; return NGX_OK; }
ngx_http_echo_ctx_t * ngx_http_echo_create_ctx(ngx_http_request_t *r) { ngx_http_echo_ctx_t *ctx; ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_echo_ctx_t)); if (ctx == NULL) { return NULL; } ctx->request = r; ctx->chunks_to_send = 10; ngx_http_cleanup_t *cln = ngx_http_cleanup_add(r, 0); cln->handler = ngx_http_hello_cleanup; cln->data = ctx; return ctx; }
ngx_int_t ngx_http_echo_exec_echo_sleep( ngx_http_request_t *r, ngx_http_echo_ctx_t *ctx, ngx_array_t *computed_args) { ngx_str_t *computed_arg; ngx_str_t *computed_arg_elts; float delay; /* in sec */ ngx_http_cleanup_t *cln; computed_arg_elts = computed_args->elts; computed_arg = &computed_arg_elts[0]; delay = atof( (char*) computed_arg->data ); if (delay < 0.001) { /* should be bigger than 1 msec */ ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "invalid sleep duration \"%V\"", &computed_arg_elts[0]); return NGX_HTTP_BAD_REQUEST; } dd("DELAY = %.02lf sec", delay); ngx_add_timer(&ctx->sleep, (ngx_msec_t) (1000 * delay)); /* we don't check broken downstream connections * ourselves so even if the client shuts down * the connection prematurely, nginx will still * go on waiting for our timers to get properly * expired. However, we'd still register a * cleanup handler for completeness. */ cln = ngx_http_cleanup_add(r, 0); if (cln == NULL) { return NGX_ERROR; } cln->handler = ngx_http_echo_sleep_cleanup; cln->data = r; return NGX_AGAIN; }
ngx_int_t ngx_http_echo_exec_echo_sleep(ngx_http_request_t *r, ngx_http_echo_ctx_t *ctx, ngx_array_t *computed_args) { ngx_str_t *computed_arg; ngx_str_t *computed_arg_elts; ngx_int_t delay; /* in msec */ ngx_http_cleanup_t *cln; computed_arg_elts = computed_args->elts; computed_arg = &computed_arg_elts[0]; delay = ngx_atofp(computed_arg->data, computed_arg->len, 3); if (delay == NGX_ERROR) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "invalid sleep duration \"%V\"", &computed_arg_elts[0]); return NGX_HTTP_BAD_REQUEST; } dd("adding timer with delay %lu ms, r:%.*s", (unsigned long) delay, (int) r->uri.len, r->uri.data); ngx_add_timer(&ctx->sleep, (ngx_msec_t) delay); /* we don't check broken downstream connections * ourselves so even if the client shuts down * the connection prematurely, nginx will still * go on waiting for our timers to get properly * expired. However, we'd still register a * cleanup handler for completeness. */ cln = ngx_http_cleanup_add(r, 0); if (cln == NULL) { return NGX_ERROR; } cln->handler = ngx_http_echo_sleep_cleanup; cln->data = r; return NGX_AGAIN; }
//----------------------------------------------------------------------------- ngx_int_t ngx_c2h5oh_init_request(ngx_http_request_t * r, ngx_c2h5oh_ctx_t * ctx) { ngx_http_cleanup_t* cln; if (ngx_c2h5oh_init_query_data(r, ctx) != 0) { return NGX_HTTP_BAD_REQUEST; } // init c2h5oh connection ------------------------------------------------- if (ctx->conn == NULL) { cln = ngx_http_cleanup_add(r, 0); if (cln == NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "[c2h5oh] cannot add cleanup"); return NGX_ERROR; } cln->handler = ngx_c2h5oh_cleanup; cln->data = ctx; ctx->conn = c2h5oh_create(); if (ctx->conn == NULL) { ngx_add_timer(&ctx->timer, (ngx_msec_t)1); r->main->count++; return NGX_DONE; } if (c2h5oh_query(ctx->conn, (const char *)ctx->query.data) != 0) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "[c2h5oh] error create query"); return NGX_ERROR; } } if (c2h5oh_poll(ctx->conn) == 0) { ngx_add_timer(&ctx->timer, (ngx_msec_t)1); r->main->count++; return NGX_DONE; } ngx_c2h5oh_post_response(r, ctx); return NGX_DONE; }
static safe_request_ptr_t *nchan_set_safe_request_ptr(ngx_http_request_t *r) { safe_request_ptr_t *data = ngx_alloc(sizeof(*data), ngx_cycle->log); ngx_http_cleanup_t *cln = ngx_http_cleanup_add(r, 0); if(!data || !cln) { nchan_log_request_error(r, "couldn't allocate request cleanup stuff."); if(cln) { cln->data = NULL; cln->handler = (ngx_http_cleanup_pt )clear_request_pointer; } nchan_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); return NULL; } data->cln = cln; data->r = r; cln->data = data; cln->handler = (ngx_http_cleanup_pt )clear_request_pointer; return data; }
static ngx_int_t ngx_http_groonga_handler_create_data(ngx_http_request_t *r, ngx_http_groonga_handler_data_t **data_return) { ngx_int_t rc; ngx_http_groonga_loc_conf_t *location_conf; ngx_http_cleanup_t *cleanup; ngx_http_groonga_handler_data_t *data; grn_ctx *context; location_conf = ngx_http_get_module_loc_conf(r, ngx_http_groonga_module); cleanup = ngx_http_cleanup_add(r, sizeof(ngx_http_groonga_handler_data_t)); cleanup->handler = ngx_http_groonga_handler_cleanup; data = cleanup->data; *data_return = data; context = &(data->context); grn_ctx_init(context, GRN_NO_FLAGS); GRN_TEXT_INIT(&(data->head), GRN_NO_FLAGS); GRN_TEXT_INIT(&(data->body), GRN_NO_FLAGS); GRN_TEXT_INIT(&(data->foot), GRN_NO_FLAGS); grn_ctx_use(context, grn_ctx_db(&(location_conf->context))); rc = ngx_http_groonga_context_check_error(r->connection->log, context); if (rc != NGX_OK) { return rc; } grn_ctx_recv_handler_set(context, ngx_http_groonga_context_receive_handler, data); return NGX_OK; }
subscriber_t *longpoll_subscriber_create(ngx_http_request_t *r, nchan_msg_id_t *msg_id) { DBG("create for req %p", r); full_subscriber_t *fsub; nchan_request_ctx_t *ctx = ngx_http_get_module_ctx(r, nchan_module); //TODO: allocate from pool (but not the request's pool) if((fsub = ngx_alloc(sizeof(*fsub), ngx_cycle->log)) == NULL) { ERR("Unable to allocate"); assert(0); return NULL; } ngx_memcpy(&fsub->sub, &new_longpoll_sub, sizeof(new_longpoll_sub)); fsub->sub.request = r; fsub->data.cln = NULL; fsub->data.finalize_request = 1; fsub->data.holding = 0; fsub->data.act_as_intervalpoll = 0; fsub->sub.cf = ngx_http_get_module_loc_conf(r, nchan_module); ngx_memzero(&fsub->data.timeout_ev, sizeof(fsub->data.timeout_ev)); fsub->data.timeout_handler = empty_handler; fsub->data.timeout_handler_data = NULL; fsub->data.dequeue_handler = empty_handler; fsub->data.dequeue_handler_data = NULL; fsub->data.already_responded = 0; fsub->data.awaiting_destruction = 0; fsub->sub.reserved = 0; fsub->sub.enqueued = 0; if(fsub->sub.cf->longpoll_multimsg) { fsub->sub.dequeue_after_response = 0; } fsub->data.multimsg_first = NULL; fsub->data.multimsg_last = NULL; #if NCHAN_SUBSCRIBER_LEAK_DEBUG subscriber_debug_add(&fsub->sub); //set debug label fsub->sub.lbl = ngx_calloc(r->uri.len+1, ngx_cycle->log); ngx_memcpy(fsub->sub.lbl, r->uri.data, r->uri.len); #endif if(msg_id) { nchan_copy_new_msg_id(&fsub->sub.last_msgid, msg_id); } else { fsub->sub.last_msgid.time = 0; fsub->sub.last_msgid.tag.fixed[0] = 0; fsub->sub.last_msgid.tagcount = 1; } ctx->prev_msg_id = fsub->sub.last_msgid; fsub->data.owner = memstore_slot(); //http request sudden close cleanup if((fsub->data.cln = ngx_http_cleanup_add(r, 0)) == NULL) { ERR("Unable to add request cleanup for longpoll subscriber"); assert(0); return NULL; } fsub->data.cln->data = fsub; fsub->data.cln->handler = (ngx_http_cleanup_pt )sudden_abort_handler; DBG("%p created for request %p", &fsub->sub, r); if(ctx) { ctx->sub = &fsub->sub; ctx->subscriber_type = fsub->sub.name; } return &fsub->sub; }
static void ngx_http_lua_timer_handler(ngx_event_t *ev) { int n; lua_State *L; ngx_int_t rc; ngx_log_t *log; ngx_connection_t *c = NULL, *saved_c = NULL; ngx_http_request_t *r = NULL; ngx_http_lua_ctx_t *ctx; ngx_http_cleanup_t *cln; ngx_http_log_ctx_t *logctx; ngx_http_lua_timer_ctx_t tctx; ngx_http_lua_main_conf_t *lmcf; ngx_http_core_loc_conf_t *clcf; ngx_log_debug0(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0, "lua ngx.timer expired"); ngx_memcpy(&tctx, ev->data, sizeof(ngx_http_lua_timer_ctx_t)); ngx_free(ev); ev = NULL; lmcf = tctx.lmcf; lmcf->pending_timers--; if (lmcf->running_timers >= lmcf->max_running_timers) { ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0, "%i lua_max_running_timers are not enough", lmcf->max_running_timers); goto abort; } /* create the fake connection (we temporarily use a valid fd (0) to make ngx_get_connection happy) */ if (ngx_cycle->files) { saved_c = ngx_cycle->files[0]; } c = ngx_get_connection(0, ngx_cycle->log); if (ngx_cycle->files) { ngx_cycle->files[0] = saved_c; } if (c == NULL) { goto abort; } c->fd = -1; c->pool = ngx_create_pool(NGX_CYCLE_POOL_SIZE, c->log); if (c->pool == NULL) { goto abort; } log = ngx_pcalloc(c->pool, sizeof(ngx_log_t)); if (log == NULL) { goto abort; } logctx = ngx_palloc(c->pool, sizeof(ngx_http_log_ctx_t)); if (logctx == NULL) { goto abort; } dd("c pool allocated: %d", (int) (sizeof(ngx_log_t) + sizeof(ngx_http_log_ctx_t) + sizeof(ngx_http_request_t))); logctx->connection = c; logctx->request = NULL; logctx->current_request = NULL; c->log = log; c->log->connection = c->number; c->log->handler = ngx_http_lua_log_timer_error; c->log->data = logctx; c->log->action = NULL; c->log_error = NGX_ERROR_INFO; #if 0 c->buffer = ngx_create_temp_buf(c->pool, 2); if (c->buffer == NULL) { goto abort; } c->buffer->start[0] = CR; c->buffer->start[1] = LF; #endif /* create the fake request */ r = ngx_pcalloc(c->pool, sizeof(ngx_http_request_t)); if (r == NULL) { goto abort; } c->requests++; logctx->request = r; logctx->current_request = r; r->pool = ngx_create_pool(NGX_CYCLE_POOL_SIZE, c->log); if (r->pool == NULL) { goto abort; } dd("r pool allocated: %d", (int) (sizeof(ngx_http_lua_ctx_t) + sizeof(void *) * ngx_http_max_module + sizeof(ngx_http_cleanup_t))); #if 0 hc = ngx_pcalloc(c->pool, sizeof(ngx_http_connection_t)); if (hc == NULL) { goto abort; } r->header_in = c->buffer; r->header_end = c->buffer->start; if (ngx_list_init(&r->headers_out.headers, r->pool, 0, sizeof(ngx_table_elt_t)) != NGX_OK) { goto abort; } if (ngx_list_init(&r->headers_in.headers, r->pool, 0, sizeof(ngx_table_elt_t)) != NGX_OK) { goto abort; } #endif r->ctx = ngx_pcalloc(r->pool, sizeof(void *) * ngx_http_max_module); if (r->ctx == NULL) { goto abort; } #if 0 cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module); r->variables = ngx_pcalloc(r->pool, cmcf->variables.nelts * sizeof(ngx_http_variable_value_t)); if (r->variables == NULL) { goto abort; } #endif ctx = ngx_http_lua_create_ctx(r); if (ctx == NULL) { goto abort; } r->headers_in.content_length_n = 0; c->data = r; #if 0 hc->request = r; r->http_connection = hc; #endif r->signature = NGX_HTTP_MODULE; r->connection = c; r->main = r; r->count = 1; r->method = NGX_HTTP_UNKNOWN; r->headers_in.keep_alive_n = -1; r->uri_changes = NGX_HTTP_MAX_URI_CHANGES + 1; r->subrequests = NGX_HTTP_MAX_SUBREQUESTS + 1; r->http_state = NGX_HTTP_PROCESS_REQUEST_STATE; r->discard_body = 1; r->main_conf = tctx.main_conf; r->srv_conf = tctx.srv_conf; r->loc_conf = tctx.loc_conf; clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); c->log->file = clcf->error_log->file; if (!(c->log->log_level & NGX_LOG_DEBUG_CONNECTION)) { c->log->log_level = clcf->error_log->log_level; } c->error = 1; ctx->cur_co_ctx = &ctx->entry_co_ctx; L = lmcf->lua; cln = ngx_http_cleanup_add(r, 0); if (cln == NULL) { goto abort; } cln->handler = ngx_http_lua_request_cleanup; cln->data = r; ctx->cleanup = &cln->handler; ctx->entered_content_phase = 1; ctx->context = NGX_HTTP_LUA_CONTEXT_TIMER; r->read_event_handler = ngx_http_block_reading; ctx->cur_co_ctx->co_ref = tctx.co_ref; ctx->cur_co_ctx->co = tctx.co; ctx->cur_co_ctx->co_status = NGX_HTTP_LUA_CO_RUNNING; dd("r connection: %p, log %p", r->connection, r->connection->log); /* save the request in coroutine globals table */ ngx_http_lua_set_req(tctx.co, r); lmcf->running_timers++; lua_pushboolean(tctx.co, tctx.premature); n = lua_gettop(tctx.co); if (n > 2) { lua_insert(tctx.co, 2); } rc = ngx_http_lua_run_thread(L, r, ctx, n - 1); dd("timer lua run thread: %d", (int) rc); if (rc == NGX_ERROR || rc >= NGX_OK) { /* do nothing */ } else if (rc == NGX_AGAIN) { rc = ngx_http_lua_content_run_posted_threads(L, r, ctx, 0); } else if (rc == NGX_DONE) { rc = ngx_http_lua_content_run_posted_threads(L, r, ctx, 1); } else { rc = NGX_OK; } ngx_http_lua_finalize_request(r, rc); return; abort: if (tctx.co_ref && tctx.co) { lua_pushlightuserdata(tctx.co, &ngx_http_lua_coroutines_key); lua_rawget(tctx.co, LUA_REGISTRYINDEX); luaL_unref(tctx.co, -1, tctx.co_ref); lua_settop(tctx.co, 0); } if (r && r->pool) { ngx_destroy_pool(r->pool); } if (c) { ngx_http_lua_close_fake_connection(c); } }
static int ngx_http_lua_socket_resolve_retval_handler(ngx_http_request_t *r, ngx_http_lua_socket_udp_upstream_t *u, lua_State *L) { ngx_http_lua_ctx_t *ctx; ngx_http_lua_co_ctx_t *coctx; ngx_udp_connection_t *uc; ngx_connection_t *c; ngx_http_cleanup_t *cln; ngx_http_upstream_resolved_t *ur; ngx_int_t rc; ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "lua udp socket resolve retval handler"); if (u->ft_type & NGX_HTTP_LUA_SOCKET_FT_RESOLVER) { return 2; } uc = &u->udp_connection; ur = u->resolved; if (ur->sockaddr) { uc->sockaddr = ur->sockaddr; uc->socklen = ur->socklen; uc->server = ur->host; } else { lua_pushnil(L); lua_pushliteral(L, "resolver not working"); return 2; } rc = ngx_http_lua_udp_connect(uc); if (rc != NGX_OK) { u->socket_errno = ngx_socket_errno; } if (u->cleanup == NULL) { cln = ngx_http_cleanup_add(r, 0); if (cln == NULL) { u->ft_type |= NGX_HTTP_LUA_SOCKET_FT_ERROR; lua_pushnil(L); lua_pushliteral(L, "out of memory"); return 2; } cln->handler = ngx_http_lua_socket_udp_cleanup; cln->data = u; u->cleanup = &cln->handler; } ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "lua udp socket connect: %i", rc); if (rc != NGX_OK) { return ngx_http_lua_socket_error_retval_handler(r, u, L); } /* rc == NGX_OK */ c = uc->connection; c->data = u; c->write->handler = NULL; c->read->handler = ngx_http_lua_socket_udp_handler; c->read->resolver = 0; c->pool = r->pool; c->log = r->connection->log; c->read->log = c->log; c->write->log = c->log; ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module); coctx = ctx->cur_co_ctx; coctx->data = u; u->read_event_handler = ngx_http_lua_socket_dummy_handler; lua_pushinteger(L, 1); return 1; }
static ngx_int_t ngx_http_zm_sso_cert_auth(ngx_http_request_t *r, ngx_zm_lookup_work_t *w) { ngx_http_variable_value_t *ssl_client_verify_var; ngx_http_variable_value_t *ssl_client_s_dn_var; ngx_str_t ssl_client_verify_value; ngx_str_t ssl_client_s_dn_value; ngx_http_zm_sso_loc_conf_t *zlcf; zlcf = ngx_http_get_module_loc_conf(r, ngx_http_zm_sso_module); w->protocol = ZM_PROTO_HTTP; /* it doesn't matter which protocol is used, for cert auth we don't want route */ if (zlcf->type == NGX_ZM_SSO_CERTAUTH) { w->isAdmin = 0; } else if (zlcf->type == NGX_ZM_SSO_CERTAUTH_ADMIN) { w->isAdmin = 1; } else { return NGX_HTTP_FORBIDDEN; } ssl_client_verify_var = ngx_http_get_indexed_variable(r, zlcf->ssl_client_verify_index); if (!ssl_client_verify_var->valid) { ngx_log_error (NGX_LOG_ERR, r->connection->log, 0, "nginx ssl module return invalid result for " "client cert auth"); return NGX_HTTP_INTERNAL_SERVER_ERROR; } ssl_client_verify_value.data = ssl_client_verify_var->data; ssl_client_verify_value.len = ssl_client_verify_var->len; if (ngx_strncasecmp(ssl_client_verify_value.data, (u_char*)"SUCCESS", sizeof ("SUCCESS") - 1) == 0) { /* get client cert subject dn */ ssl_client_s_dn_var = ngx_http_get_indexed_variable(r, zlcf->ssl_client_s_dn_index); if (!ssl_client_s_dn_var->valid) { ngx_log_error (NGX_LOG_ERR, r->connection->log, 0, "nginx ssl module return invalid subject DN for " "client cert auth"); return NGX_HTTP_INTERNAL_SERVER_ERROR; } ssl_client_s_dn_value.data = ssl_client_s_dn_var->data; ssl_client_s_dn_value.len = ssl_client_s_dn_var->len; w->auth_method = ZM_AUTHMETH_CERTAUTH; w->username = ssl_client_s_dn_value; if (r->headers_in.host != NULL) { w->virtual_host = r->headers_in.host->value; } w->login_attempts = 0; /* HTTP is always 0 */ w->connection = r->connection; w->on_success = ngx_http_zm_sso_cert_auth_on_success; w->on_failure = ngx_http_zm_sso_cert_auth_on_failure; ngx_http_cleanup_t * cln = ngx_http_cleanup_add(r, 0); cln->handler = ngx_http_zm_sso_cleanup; cln->data = w; r->main->count++; r->read_event_handler = ngx_http_zm_sso_rd_check_broken_connection; r->write_event_handler = ngx_http_zm_sso_wr_check_broken_connection; ngx_zm_lookup(w); return NGX_DONE; } else if (ngx_strncasecmp(ssl_client_verify_value.data, (u_char*)"NONE", sizeof ("NONE") - 1) == 0) { /* if ssl_verify_client is set to be "on", and the the verification fails, * nginx will return SSL handshake error; in this case, the code here will * never be executed. Only when ssl_verify_client is "optional", and client * doesn't send the cert, here will be executed. That is, directly redirect. */ ngx_log_error (NGX_LOG_INFO, r->connection->log, 0, "doesn't provide client cert, redirect to common https login page " "to do the username/password login"); return ngx_http_zm_sso_redirect (r); } else { ngx_log_error (NGX_LOG_ERR, r->connection->log, 0, "unexpected ssl client cert verification result %V", &ssl_client_verify_value); return NGX_HTTP_INTERNAL_SERVER_ERROR; } }
ngx_int_t ngx_http_lua_content_by_chunk(lua_State *L, ngx_http_request_t *r) { int cc_ref; lua_State *cc; ngx_http_lua_ctx_t *ctx; ngx_http_cleanup_t *cln; dd("content by chunk"); ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module); if (ctx == NULL) { ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_lua_ctx_t)); if (ctx == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } dd("setting new ctx, ctx = %p", ctx); ctx->cc_ref = LUA_NOREF; ctx->ctx_ref = LUA_NOREF; ngx_http_set_ctx(r, ctx, ngx_http_lua_module); } else { dd("reset ctx"); ngx_http_lua_reset_ctx(r, L, ctx); } ctx->entered_content_phase = 1; /* {{{ new coroutine to handle request */ cc = ngx_http_lua_new_thread(r, L, &cc_ref); if (cc == NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "(lua-content-by-chunk) failed to create new coroutine " "to handle request"); return NGX_HTTP_INTERNAL_SERVER_ERROR; } /* move code closure to new coroutine */ lua_xmove(L, cc, 1); /* set closure's env table to new coroutine's globals table */ lua_pushvalue(cc, LUA_GLOBALSINDEX); lua_setfenv(cc, -2); /* save reference of code to ease forcing stopping */ lua_pushvalue(cc, -1); lua_setglobal(cc, GLOBALS_SYMBOL_RUNCODE); /* save nginx request in coroutine globals table */ lua_pushlightuserdata(cc, r); lua_setglobal(cc, GLOBALS_SYMBOL_REQUEST); /* }}} */ ctx->cc = cc; ctx->cc_ref = cc_ref; /* {{{ register request cleanup hooks */ if (ctx->cleanup == NULL) { cln = ngx_http_cleanup_add(r, 0); if (cln == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } cln->handler = ngx_http_lua_request_cleanup; cln->data = r; ctx->cleanup = &cln->handler; } /* }}} */ return ngx_http_lua_run_thread(L, r, ctx, 0); }
static ngx_int_t ngx_http_lua_rewrite_by_chunk(lua_State *L, ngx_http_request_t *r) { int co_ref; lua_State *co; ngx_int_t rc; ngx_connection_t *c; ngx_http_lua_ctx_t *ctx; ngx_http_cleanup_t *cln; ngx_http_lua_loc_conf_t *llcf; /* {{{ new coroutine to handle request */ co = ngx_http_lua_new_thread(r, L, &co_ref); if (co == NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "lua: failed to create new coroutine to handle request"); return NGX_HTTP_INTERNAL_SERVER_ERROR; } /* move code closure to new coroutine */ lua_xmove(L, co, 1); /* set closure's env table to new coroutine's globals table */ lua_pushvalue(co, LUA_GLOBALSINDEX); lua_setfenv(co, -2); /* save nginx request in coroutine globals table */ lua_pushlightuserdata(co, &ngx_http_lua_request_key); lua_pushlightuserdata(co, r); lua_rawset(co, LUA_GLOBALSINDEX); /* }}} */ /* {{{ initialize request context */ ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module); dd("ctx = %p", ctx); if (ctx == NULL) { return NGX_ERROR; } ngx_http_lua_reset_ctx(r, L, ctx); ctx->entered_rewrite_phase = 1; ctx->cur_co_ctx = &ctx->entry_co_ctx; ctx->cur_co_ctx->co = co; ctx->cur_co_ctx->co_ref = co_ref; /* }}} */ /* {{{ register request cleanup hooks */ if (ctx->cleanup == NULL) { cln = ngx_http_cleanup_add(r, 0); if (cln == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } cln->handler = ngx_http_lua_request_cleanup; cln->data = r; ctx->cleanup = &cln->handler; } /* }}} */ ctx->context = NGX_HTTP_LUA_CONTEXT_REWRITE; llcf = ngx_http_get_module_loc_conf(r, ngx_http_lua_module); if (llcf->check_client_abort) { r->read_event_handler = ngx_http_lua_rd_check_broken_connection; } else { r->read_event_handler = ngx_http_block_reading; } rc = ngx_http_lua_run_thread(L, r, ctx, 0); if (rc == NGX_ERROR || rc > NGX_OK) { return rc; } c = r->connection; if (rc == NGX_AGAIN) { rc = ngx_http_lua_run_posted_threads(c, L, r, ctx); if (rc == NGX_OK) { return NGX_DECLINED; } return rc; } if (rc == NGX_DONE) { ngx_http_finalize_request(r, NGX_DONE); rc = ngx_http_lua_run_posted_threads(c, L, r, ctx); if (rc == NGX_OK) { return NGX_DECLINED; } return rc; } return NGX_DECLINED; }
static void ngx_http_lua_timer_handler(ngx_event_t *ev) { int n; lua_State *L; ngx_int_t rc; ngx_connection_t *c = NULL; ngx_http_request_t *r = NULL; ngx_http_lua_ctx_t *ctx; ngx_http_cleanup_t *cln; ngx_pool_cleanup_t *pcln; ngx_http_lua_timer_ctx_t tctx; ngx_http_lua_main_conf_t *lmcf; ngx_http_core_loc_conf_t *clcf; ngx_log_debug0(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0, "lua ngx.timer expired"); ngx_memcpy(&tctx, ev->data, sizeof(ngx_http_lua_timer_ctx_t)); ngx_free(ev); ev = NULL; lmcf = tctx.lmcf; lmcf->pending_timers--; if (lmcf->running_timers >= lmcf->max_running_timers) { ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0, "%i lua_max_running_timers are not enough", lmcf->max_running_timers); goto failed; } c = ngx_http_lua_create_fake_connection(tctx.pool); if (c == NULL) { goto failed; } c->log->handler = ngx_http_lua_log_timer_error; c->log->data = c; c->listening = tctx.listening; c->addr_text = tctx.client_addr_text; r = ngx_http_lua_create_fake_request(c); if (r == NULL) { goto failed; } r->main_conf = tctx.main_conf; r->srv_conf = tctx.srv_conf; r->loc_conf = tctx.loc_conf; clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); #if defined(nginx_version) && nginx_version >= 1003014 ngx_http_set_connection_log(r->connection, clcf->error_log); #else c->log->file = clcf->error_log->file; if (!(c->log->log_level & NGX_LOG_DEBUG_CONNECTION)) { c->log->log_level = clcf->error_log->log_level; } #endif dd("lmcf: %p", lmcf); ctx = ngx_http_lua_create_ctx(r); if (ctx == NULL) { goto failed; } if (tctx.vm_state) { ctx->vm_state = tctx.vm_state; pcln = ngx_pool_cleanup_add(r->pool, 0); if (pcln == NULL) { goto failed; } pcln->handler = ngx_http_lua_cleanup_vm; pcln->data = tctx.vm_state; } ctx->cur_co_ctx = &ctx->entry_co_ctx; L = ngx_http_lua_get_lua_vm(r, ctx); cln = ngx_http_cleanup_add(r, 0); if (cln == NULL) { goto failed; } cln->handler = ngx_http_lua_request_cleanup_handler; cln->data = ctx; ctx->cleanup = &cln->handler; ctx->entered_content_phase = 1; ctx->context = NGX_HTTP_LUA_CONTEXT_TIMER; r->read_event_handler = ngx_http_block_reading; ctx->cur_co_ctx->co_ref = tctx.co_ref; ctx->cur_co_ctx->co = tctx.co; ctx->cur_co_ctx->co_status = NGX_HTTP_LUA_CO_RUNNING; dd("r connection: %p, log %p", r->connection, r->connection->log); /* save the request in coroutine globals table */ ngx_http_lua_set_req(tctx.co, r); lmcf->running_timers++; lua_pushboolean(tctx.co, tctx.premature); n = lua_gettop(tctx.co); if (n > 2) { lua_insert(tctx.co, 2); } #ifdef NGX_LUA_USE_ASSERT ctx->cur_co_ctx->co_top = 1; #endif rc = ngx_http_lua_run_thread(L, r, ctx, n - 1); dd("timer lua run thread: %d", (int) rc); if (rc == NGX_ERROR || rc >= NGX_OK) { /* do nothing */ } else if (rc == NGX_AGAIN) { rc = ngx_http_lua_content_run_posted_threads(L, r, ctx, 0); } else if (rc == NGX_DONE) { rc = ngx_http_lua_content_run_posted_threads(L, r, ctx, 1); } else { rc = NGX_OK; } ngx_http_lua_finalize_request(r, rc); return; failed: if (tctx.co_ref && tctx.co) { lua_pushlightuserdata(tctx.co, &ngx_http_lua_coroutines_key); lua_rawget(tctx.co, LUA_REGISTRYINDEX); luaL_unref(tctx.co, -1, tctx.co_ref); lua_settop(tctx.co, 0); } if (tctx.vm_state) { ngx_http_lua_cleanup_vm(tctx.vm_state); } if (c) { ngx_http_lua_close_fake_connection(c); } else if (tctx.pool) { ngx_destroy_pool(tctx.pool); } }
static ngx_int_t ngx_http_spdy_serverpush_header_filter(ngx_http_request_t *r) { int rc; size_t len; u_char *p, *buf, *last; ngx_buf_t *b; ngx_str_t host; ngx_uint_t i, j, count, port; ngx_chain_t *cl; ngx_list_part_t *part, *pt; ngx_table_elt_t *header, *h; ngx_connection_t *c; ngx_http_cleanup_t *cln; ngx_http_core_loc_conf_t *clcf; ngx_http_core_srv_conf_t *cscf; ngx_http_spdy_stream_t *stream; ngx_http_spdy_out_frame_t *frame; ngx_http_spdy_connection_t *sc; struct sockaddr_in *sin; #if (NGX_HAVE_INET6) struct sockaddr_in6 *sin6; #endif u_char addr[NGX_SOCKADDR_STRLEN]; if (!r->spdy_stream) { return ngx_http_next_header_filter(r); } ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "spdy serverpush module header filter"); if (r->header_sent) { return NGX_OK; } r->header_sent = 1; if (r != r->main) { return NGX_OK; } c = r->connection; if (r->method == NGX_HTTP_HEAD) { r->header_only = 1; } switch (r->headers_out.status) { case NGX_HTTP_OK: case NGX_HTTP_PARTIAL_CONTENT: break; case NGX_HTTP_NOT_MODIFIED: r->header_only = 1; break; case NGX_HTTP_NO_CONTENT: r->header_only = 1; ngx_str_null(&r->headers_out.content_type); r->headers_out.content_length = NULL; r->headers_out.content_length_n = -1; /* fall through */ default: r->headers_out.last_modified_time = -1; r->headers_out.last_modified = NULL; } ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "spdy serverpush module header filter 2"); ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "From header Blaha spdy body filter \"%V?%V\"", &r->uri, &r->args); len = NGX_SPDY_NV_NUM_SIZE + ngx_http_spdy_nv_nsize("version") + ngx_http_spdy_nv_vsize("HTTP/1.1") + ngx_http_spdy_nv_nsize("status") + ngx_http_spdy_nv_vsize("418"); clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); len += ngx_http_spdy_nv_nsize("url") +ngx_http_spdy_nv_vsize("https://localhost/test.js"); if (r->headers_out.server == NULL) { len += ngx_http_spdy_nv_nsize("server"); len += clcf->server_tokens ? ngx_http_spdy_nv_vsize(NGINX_VER) : ngx_http_spdy_nv_vsize("nginx"); } if (r->headers_out.date == NULL) { len += ngx_http_spdy_nv_nsize("date") + ngx_http_spdy_nv_vsize("Wed, 31 Dec 1986 10:00:00 GMT"); } if (r->headers_out.content_type.len) { len += ngx_http_spdy_nv_nsize("content-type") + NGX_SPDY_NV_VLEN_SIZE + r->headers_out.content_type.len; if (r->headers_out.content_type_len == r->headers_out.content_type.len && r->headers_out.charset.len) { len += sizeof("; charset=") - 1 + r->headers_out.charset.len; } } if (r->headers_out.content_length == NULL && r->headers_out.content_length_n >= 0) { len += ngx_http_spdy_nv_nsize("content-length") + NGX_SPDY_NV_VLEN_SIZE + NGX_OFF_T_LEN; } if (r->headers_out.last_modified == NULL && r->headers_out.last_modified_time != -1) { len += ngx_http_spdy_nv_nsize("last-modified") + ngx_http_spdy_nv_vsize("Wed, 31 Dec 1986 10:00:00 GMT"); } if (r->headers_out.location && r->headers_out.location->value.len && r->headers_out.location->value.data[0] == '/') { r->headers_out.location->hash = 0; if (clcf->server_name_in_redirect) { cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module); host = cscf->server_name; } else if (r->headers_in.server.len) { host = r->headers_in.server; } else { host.len = NGX_SOCKADDR_STRLEN; host.data = addr; if (ngx_connection_local_sockaddr(c, &host, 0) != NGX_OK) { return NGX_ERROR; } } switch (c->local_sockaddr->sa_family) { #if (NGX_HAVE_INET6) case AF_INET6: sin6 = (struct sockaddr_in6 *) c->local_sockaddr; port = ntohs(sin6->sin6_port); break; #endif #if (NGX_HAVE_UNIX_DOMAIN) case AF_UNIX: port = 0; break; #endif default: /* AF_INET */ sin = (struct sockaddr_in *) c->local_sockaddr; port = ntohs(sin->sin_port); break; } len += ngx_http_spdy_nv_nsize("location") + ngx_http_spdy_nv_vsize("https://") + host.len + r->headers_out.location->value.len; if (clcf->port_in_redirect) { #if (NGX_HTTP_SSL) if (c->ssl) port = (port == 443) ? 0 : port; else #endif port = (port == 80) ? 0 : port; } else { port = 0; } if (port) { len += sizeof(":65535") - 1; } } else { ngx_str_null(&host); port = 0; } ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "spdy serverpush module header filter 3"); part = &r->headers_out.headers.part; header = part->elts; int isSet=0; for (i = 0; /* void */; i++) { if (i >= part->nelts) { if (part->next == NULL) { break; } part = part->next; header = part->elts; i = 0; } if (header[i].hash == 0) { continue; } ngx_str_t xac = ngx_string("X-Associated-Content"); if(ngx_strncmp(&header[i].key, &xac, 20) == 0 ) { isSet=1; } len += NGX_SPDY_NV_NLEN_SIZE + header[i].key.len + NGX_SPDY_NV_VLEN_SIZE + header[i].value.len; } buf = ngx_alloc(len, r->pool->log); if (buf == NULL) { return NGX_ERROR; } last = buf + NGX_SPDY_NV_NUM_SIZE; last = ngx_http_spdy_nv_write_name(last, "version"); last = ngx_http_spdy_nv_write_val(last, "HTTP/1.1"); last = ngx_http_spdy_nv_write_name(last, "status"); last = ngx_spdy_frame_write_uint16(last, 3); last = ngx_sprintf(last, "%03ui", r->headers_out.status); count = 2; last = ngx_http_spdy_nv_write_name(last, "url"); last = ngx_http_spdy_nv_write_val(last, "https://localhost/test.js"); count++; if (r->headers_out.server == NULL) { last = ngx_http_spdy_nv_write_name(last, "server"); last = clcf->server_tokens ? ngx_http_spdy_nv_write_val(last, NGINX_VER) : ngx_http_spdy_nv_write_val(last, "nginx"); count++; } if (r->headers_out.date == NULL) { last = ngx_http_spdy_nv_write_name(last, "date"); last = ngx_http_spdy_nv_write_vlen(last, ngx_cached_http_time.len); last = ngx_cpymem(last, ngx_cached_http_time.data, ngx_cached_http_time.len); count++; } if (r->headers_out.content_type.len) { last = ngx_http_spdy_nv_write_name(last, "content-type"); p = last + NGX_SPDY_NV_VLEN_SIZE; last = ngx_cpymem(p, r->headers_out.content_type.data, r->headers_out.content_type.len); if (r->headers_out.content_type_len == r->headers_out.content_type.len && r->headers_out.charset.len) { last = ngx_cpymem(last, "; charset=", sizeof("; charset=") - 1); last = ngx_cpymem(last, r->headers_out.charset.data, r->headers_out.charset.len); /* update r->headers_out.content_type for possible logging */ r->headers_out.content_type.len = last - p; r->headers_out.content_type.data = p; } (void) ngx_http_spdy_nv_write_vlen(p - NGX_SPDY_NV_VLEN_SIZE, r->headers_out.content_type.len); count++; } if (r->headers_out.content_length == NULL && r->headers_out.content_length_n >= 0) { last = ngx_http_spdy_nv_write_name(last, "content-length"); p = last + NGX_SPDY_NV_VLEN_SIZE; last = ngx_sprintf(p, "%O", r->headers_out.content_length_n); (void) ngx_http_spdy_nv_write_vlen(p - NGX_SPDY_NV_VLEN_SIZE, last - p); count++; } if (r->headers_out.last_modified == NULL && r->headers_out.last_modified_time != -1) { last = ngx_http_spdy_nv_write_name(last, "last-modified"); p = last + NGX_SPDY_NV_VLEN_SIZE; last = ngx_http_time(p, r->headers_out.last_modified_time); (void) ngx_http_spdy_nv_write_vlen(p - NGX_SPDY_NV_VLEN_SIZE, last - p); count++; } if (host.data) { last = ngx_http_spdy_nv_write_name(last, "location"); p = last + NGX_SPDY_NV_VLEN_SIZE; last = ngx_cpymem(p, "http", sizeof("http") - 1); #if (NGX_HTTP_SSL) if (c->ssl) { *last++ ='s'; } #endif *last++ = ':'; *last++ = '/'; *last++ = '/'; last = ngx_cpymem(last, host.data, host.len); if (port) { last = ngx_sprintf(last, ":%ui", port); } last = ngx_cpymem(last, r->headers_out.location->value.data, r->headers_out.location->value.len); /* update r->headers_out.location->value for possible logging */ r->headers_out.location->value.len = last - p; r->headers_out.location->value.data = p; ngx_str_set(&r->headers_out.location->key, "location"); (void) ngx_http_spdy_nv_write_vlen(p - NGX_SPDY_NV_VLEN_SIZE, r->headers_out.location->value.len); count++; } ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "spdy serverpush module header filter 4"); part = &r->headers_out.headers.part; header = part->elts; for (i = 0; /* void */; i++) { if (i >= part->nelts) { if (part->next == NULL) { break; } part = part->next; header = part->elts; i = 0; } if (header[i].hash == 0 || header[i].hash == 2) { continue; } if ((header[i].key.len == 6 && ngx_strncasecmp(header[i].key.data, (u_char *) "status", 6) == 0) || (header[i].key.len == 7 && ngx_strncasecmp(header[i].key.data, (u_char *) "version", 7) == 0)) { header[i].hash = 0; continue; } last = ngx_http_spdy_nv_write_nlen(last, header[i].key.len); ngx_strlow(last, header[i].key.data, header[i].key.len); last += header[i].key.len; p = last + NGX_SPDY_NV_VLEN_SIZE; last = ngx_cpymem(p, header[i].value.data, header[i].value.len); pt = part; h = header; for (j = i + 1; /* void */; j++) { if (j >= pt->nelts) { if (pt->next == NULL) { break; } pt = pt->next; h = pt->elts; j = 0; } if (h[j].hash == 0 || h[j].hash == 2 || h[j].key.len != header[i].key.len || ngx_strncasecmp(header[i].key.data, h[j].key.data, header[i].key.len)) { continue; } *last++ = '\0'; last = ngx_cpymem(last, h[j].value.data, h[j].value.len); h[j].hash = 2; } (void) ngx_http_spdy_nv_write_vlen(p - NGX_SPDY_NV_VLEN_SIZE, last - p); count++; } (void) ngx_spdy_frame_write_uint16(buf, count); stream = r->spdy_stream; sc = stream->connection; if(isSet) { ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "spdy serverpush module header filter 5"); //ngx_http_spdy_stream_t *myStream; myStream = ngx_http_spdy_create_stream(sc, get_next_even_stream_id(), 0); len = last - buf; b = ngx_create_temp_buf(r->pool, NGX_SPDY_FRAME_HEADER_SIZE + NGX_SPDY_SYN_STREAM_SIZE + deflateBound(&sc->zstream_out, len)); if (b == NULL) { ngx_free(buf); return NGX_ERROR; } b->last += NGX_SPDY_FRAME_HEADER_SIZE + NGX_SPDY_SYN_STREAM_SIZE; sc->zstream_out.next_in = buf; sc->zstream_out.avail_in = len; sc->zstream_out.next_out = b->last; sc->zstream_out.avail_out = b->end - b->last; rc = deflate(&sc->zstream_out, Z_SYNC_FLUSH); ngx_free(buf); if (rc != Z_OK) { ngx_log_error(NGX_LOG_ALERT, c->log, 0, "spdy deflate() failed: %d", rc); return NGX_ERROR; } ngx_log_debug5(NGX_LOG_DEBUG_HTTP, c->log, 0, "spdy deflate out: ni:%p no:%p ai:%ud ao:%ud rc:%d", sc->zstream_out.next_in, sc->zstream_out.next_out, sc->zstream_out.avail_in, sc->zstream_out.avail_out, rc); b->last = sc->zstream_out.next_out; p = b->pos; p = ngx_spdy_frame_write_head(p, NGX_SPDY_SYN_STREAM); len = b->last - b->pos; r->header_size = len; if (r->header_only) { b->last_buf = 1; p = ngx_spdy_frame_write_flags_and_len(p, NGX_SPDY_FLAG_FIN, len - NGX_SPDY_FRAME_HEADER_SIZE); } else { p = ngx_spdy_frame_write_flags_and_len(p, NGX_SPDY_FLAG_UNIDIRECTIONAL, len - NGX_SPDY_FRAME_HEADER_SIZE); } p= ngx_spdy_frame_write_sid(p, myStream->id); (void) ngx_spdy_frame_write_associated_sid(p, stream->id); cl = ngx_alloc_chain_link(r->pool); if (cl == NULL) { return NGX_ERROR; } cl->buf = b; cl->next = NULL; frame = ngx_palloc(r->pool, sizeof(ngx_http_spdy_out_frame_t)); if (frame == NULL) { return NGX_ERROR; } ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "spdy serverpush module header filter 6"); frame->first = cl; frame->last = cl; frame->handler = ngx_http_spdy_syn_frame_handler; frame->free = NULL; frame->stream = myStream; frame->size = len; frame->priority = myStream->priority; frame->blocked = 1; frame->fin = r->header_only; ngx_log_debug3(NGX_LOG_DEBUG_HTTP, stream->request->connection->log, 0, "spdy:%ui create JOLLY SYN_STREAM frame %p: size:%uz", myStream->id, frame, frame->size); ngx_http_spdy_queue_blocked_frame(sc, frame); r->blocked++; cln = ngx_http_cleanup_add(r, 0); if (cln == NULL) { return NGX_ERROR; } cln->handler = ngx_http_spdy_filter_cleanup; cln->data = myStream; myStream->waiting = 1; ngx_http_spdy_serverpush_filter_send(c, myStream); return ngx_http_next_header_filter(r); } else { ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "spdy serverpush module header filter 7"); return NGX_OK; } }
//----------------------------------------------------------------------------- static ngx_int_t ngx_c2h5oh_handler(ngx_http_request_t *r) { ngx_int_t rc; ngx_c2h5oh_ctx_t* ctx; ngx_http_cleanup_t* cln; ngx_c2h5oh_loc_conf_t * alcf; ctx = ngx_http_get_module_ctx(r, ngx_c2h5oh_module); if (!(r->method & (NGX_HTTP_GET|NGX_HTTP_HEAD|NGX_HTTP_POST))) { return NGX_HTTP_NOT_ALLOWED; } if (ctx == NULL) { ctx = ngx_palloc(r->pool, sizeof(ngx_c2h5oh_ctx_t)); if (ctx == NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "[c2h5oh] cannot allocate memory for c2h5oh context"); return NGX_HTTP_INTERNAL_SERVER_ERROR; } bzero(ctx, sizeof(ngx_c2h5oh_ctx_t)); alcf = ngx_http_get_module_loc_conf(r, ngx_c2h5oh_module); ctx->timer.handler = ngx_c2h5oh_event_handler; ctx->timer.data = r; ctx->timer.log = r->connection->log; ctx->timeout.msec = (r->start_msec + alcf->timeout) % 1000; ctx->timeout.sec = r->start_sec + (r->start_msec + alcf->timeout) / 1000; ngx_http_set_ctx(r, ctx, ngx_c2h5oh_module); } if (r->method & NGX_HTTP_POST) { rc = ngx_http_read_client_request_body(r, ngx_c2h5oh_post_handler); if (rc == NGX_AGAIN) { r->main->count++; return rc; } if (rc != NGX_OK) { r->main->count--; ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "[c2h5oh] error reading client request body - %d", rc); return rc; } r->main->count++; return rc; } else { rc = ngx_http_discard_request_body(r); if (rc != NGX_OK) { return rc; } } if (ngx_c2h5oh_init_query_data(r, ctx) != 0) { return NGX_HTTP_BAD_REQUEST; } if (ctx->conn == NULL) { cln = ngx_http_cleanup_add(r, 0); if (cln == NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "[c2h5oh] cannot add cleanup"); return NGX_ERROR; } cln->handler = ngx_c2h5oh_cleanup; cln->data = ctx; ctx->conn = c2h5oh_create(); if (ctx->conn == NULL) { ngx_add_timer(&ctx->timer, (ngx_msec_t)1); r->main->count++; return NGX_DONE; } if (c2h5oh_query(ctx->conn, (const char *)ctx->query.data) != 0) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "[c2h5oh] error create query"); return NGX_ERROR; } } if (c2h5oh_poll(ctx->conn) == 0) { ngx_add_timer(&ctx->timer, (ngx_msec_t)1); r->main->count++; return NGX_DONE; } ngx_c2h5oh_post_response(r, ctx); return NGX_DONE; }
static ngx_int_t ngx_http_lua_access_by_chunk(lua_State *L, ngx_http_request_t *r) { int cc_ref; ngx_int_t rc; lua_State *cc; ngx_http_lua_ctx_t *ctx; ngx_http_cleanup_t *cln; /* {{{ new coroutine to handle request */ cc = ngx_http_lua_new_thread(r, L, &cc_ref); if (cc == NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "lua: failed to create new coroutine " "to handle request"); return NGX_HTTP_INTERNAL_SERVER_ERROR; } /* move code closure to new coroutine */ lua_xmove(L, cc, 1); /* set closure's env table to new coroutine's globals table */ lua_pushvalue(cc, LUA_GLOBALSINDEX); lua_setfenv(cc, -2); /* save reference of code to ease forcing stopping */ lua_pushvalue(cc, -1); lua_setglobal(cc, GLOBALS_SYMBOL_RUNCODE); /* save nginx request in coroutine globals table */ lua_pushlightuserdata(cc, r); lua_setglobal(cc, GLOBALS_SYMBOL_REQUEST); /* }}} */ /* {{{ initialize request context */ ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module); dd("ctx = %p", ctx); if (ctx == NULL) { return NGX_ERROR; } ngx_http_lua_reset_ctx(r, L, ctx); ctx->entered_access_phase = 1; ctx->cc = cc; ctx->cc_ref = cc_ref; /* }}} */ /* {{{ register request cleanup hooks */ if (ctx->cleanup == NULL) { cln = ngx_http_cleanup_add(r, 0); if (cln == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } cln->handler = ngx_http_lua_request_cleanup; cln->data = r; ctx->cleanup = &cln->handler; } /* }}} */ rc = ngx_http_lua_run_thread(L, r, ctx, 0); dd("returned %d", (int) rc); if (rc == NGX_ERROR || rc >= NGX_HTTP_SPECIAL_RESPONSE) { return rc; } if (rc == NGX_AGAIN) { return NGX_DONE; } if (rc == NGX_DONE) { ngx_http_finalize_request(r, NGX_DONE); return NGX_DONE; } if (rc >= NGX_HTTP_OK && rc < NGX_HTTP_SPECIAL_RESPONSE) { return rc; } if (rc == NGX_OK) { return NGX_OK; } return NGX_DECLINED; }
static ngx_int_t ngx_http_v2_header_filter(ngx_http_request_t *r) { u_char status, *pos, *start, *p, *tmp; size_t len, tmp_len; ngx_str_t host, location; ngx_uint_t i, port; ngx_list_part_t *part; ngx_table_elt_t *header; ngx_connection_t *fc; ngx_http_cleanup_t *cln; ngx_http_v2_out_frame_t *frame; ngx_http_core_loc_conf_t *clcf; ngx_http_core_srv_conf_t *cscf; u_char addr[NGX_SOCKADDR_STRLEN]; static const u_char nginx[5] = "\x84\xaa\x63\x55\xe7"; #if (NGX_HTTP_GZIP) static const u_char accept_encoding[12] = "\x8b\x84\x84\x2d\x69\x5b\x05\x44\x3c\x86\xaa\x6f"; #endif static size_t nginx_ver_len = ngx_http_v2_literal_size(NGINX_VER); static u_char nginx_ver[ngx_http_v2_literal_size(NGINX_VER)]; if (!r->stream) { return ngx_http_next_header_filter(r); } ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http2 header filter"); if (r->header_sent) { return NGX_OK; } r->header_sent = 1; if (r != r->main) { return NGX_OK; } if (r->method == NGX_HTTP_HEAD) { r->header_only = 1; } switch (r->headers_out.status) { case NGX_HTTP_OK: status = ngx_http_v2_indexed(NGX_HTTP_V2_STATUS_200_INDEX); break; case NGX_HTTP_NO_CONTENT: r->header_only = 1; ngx_str_null(&r->headers_out.content_type); r->headers_out.content_length = NULL; r->headers_out.content_length_n = -1; r->headers_out.last_modified_time = -1; r->headers_out.last_modified = NULL; status = ngx_http_v2_indexed(NGX_HTTP_V2_STATUS_204_INDEX); break; case NGX_HTTP_PARTIAL_CONTENT: status = ngx_http_v2_indexed(NGX_HTTP_V2_STATUS_206_INDEX); break; case NGX_HTTP_NOT_MODIFIED: r->header_only = 1; status = ngx_http_v2_indexed(NGX_HTTP_V2_STATUS_304_INDEX); break; default: r->headers_out.last_modified_time = -1; r->headers_out.last_modified = NULL; switch (r->headers_out.status) { case NGX_HTTP_BAD_REQUEST: status = ngx_http_v2_indexed(NGX_HTTP_V2_STATUS_400_INDEX); break; case NGX_HTTP_NOT_FOUND: status = ngx_http_v2_indexed(NGX_HTTP_V2_STATUS_404_INDEX); break; case NGX_HTTP_INTERNAL_SERVER_ERROR: status = ngx_http_v2_indexed(NGX_HTTP_V2_STATUS_500_INDEX); break; default: status = 0; } } len = status ? 1 : 1 + ngx_http_v2_literal_size("418"); clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); if (r->headers_out.server == NULL) { len += 1 + (clcf->server_tokens ? nginx_ver_len : sizeof(nginx)); } if (r->headers_out.date == NULL) { len += 1 + ngx_http_v2_literal_size("Wed, 31 Dec 1986 18:00:00 GMT"); } if (r->headers_out.content_type.len) { len += 1 + NGX_HTTP_V2_INT_OCTETS + r->headers_out.content_type.len; if (r->headers_out.content_type_len == r->headers_out.content_type.len && r->headers_out.charset.len) { len += sizeof("; charset=") - 1 + r->headers_out.charset.len; } } if (r->headers_out.content_length == NULL && r->headers_out.content_length_n >= 0) { len += 1 + ngx_http_v2_integer_octets(NGX_OFF_T_LEN) + NGX_OFF_T_LEN; } if (r->headers_out.last_modified == NULL && r->headers_out.last_modified_time != -1) { len += 1 + ngx_http_v2_literal_size("Wed, 31 Dec 1986 18:00:00 GMT"); } fc = r->connection; if (r->headers_out.location && r->headers_out.location->value.len) { if (r->headers_out.location->value.data[0] == '/') { if (clcf->server_name_in_redirect) { cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module); host = cscf->server_name; } else if (r->headers_in.server.len) { host = r->headers_in.server; } else { host.len = NGX_SOCKADDR_STRLEN; host.data = addr; if (ngx_connection_local_sockaddr(fc, &host, 0) != NGX_OK) { return NGX_ERROR; } } port = ngx_inet_get_port(fc->local_sockaddr); location.len = sizeof("https://") - 1 + host.len + r->headers_out.location->value.len; if (clcf->port_in_redirect) { #if (NGX_HTTP_SSL) if (fc->ssl) port = (port == 443) ? 0 : port; else #endif port = (port == 80) ? 0 : port; } else { port = 0; } if (port) { location.len += sizeof(":65535") - 1; } location.data = ngx_pnalloc(r->pool, location.len); if (location.data == NULL) { return NGX_ERROR; } p = ngx_cpymem(location.data, "http", sizeof("http") - 1); #if (NGX_HTTP_SSL) if (fc->ssl) { *p++ = 's'; } #endif *p++ = ':'; *p++ = '/'; *p++ = '/'; p = ngx_cpymem(p, host.data, host.len); if (port) { p = ngx_sprintf(p, ":%ui", port); } p = ngx_cpymem(p, r->headers_out.location->value.data, r->headers_out.location->value.len); /* update r->headers_out.location->value for possible logging */ r->headers_out.location->value.len = p - location.data; r->headers_out.location->value.data = location.data; ngx_str_set(&r->headers_out.location->key, "Location"); } r->headers_out.location->hash = 0; len += 1 + NGX_HTTP_V2_INT_OCTETS + r->headers_out.location->value.len; } tmp_len = len; #if (NGX_HTTP_GZIP) if (r->gzip_vary) { if (clcf->gzip_vary) { len += 1 + sizeof(accept_encoding); } else { r->gzip_vary = 0; } } #endif part = &r->headers_out.headers.part; header = part->elts; for (i = 0; /* void */; i++) { if (i >= part->nelts) { if (part->next == NULL) { break; } part = part->next; header = part->elts; i = 0; } if (header[i].hash == 0) { continue; } if (header[i].key.len > NGX_HTTP_V2_MAX_FIELD) { ngx_log_error(NGX_LOG_CRIT, fc->log, 0, "too long response header name: \"%V\"", &header[i].key); return NGX_ERROR; } if (header[i].value.len > NGX_HTTP_V2_MAX_FIELD) { ngx_log_error(NGX_LOG_CRIT, fc->log, 0, "too long response header value: \"%V: %V\"", &header[i].key, &header[i].value); return NGX_ERROR; } len += 1 + NGX_HTTP_V2_INT_OCTETS + header[i].key.len + NGX_HTTP_V2_INT_OCTETS + header[i].value.len; if (header[i].key.len > tmp_len) { tmp_len = header[i].key.len; } if (header[i].value.len > tmp_len) { tmp_len = header[i].value.len; } } tmp = ngx_palloc(r->pool, tmp_len); pos = ngx_pnalloc(r->pool, len); if (pos == NULL || tmp == NULL) { return NGX_ERROR; } start = pos; ngx_log_debug1(NGX_LOG_DEBUG_HTTP, fc->log, 0, "http2 output header: \":status: %03ui\"", r->headers_out.status); if (status) { *pos++ = status; } else { *pos++ = ngx_http_v2_inc_indexed(NGX_HTTP_V2_STATUS_INDEX); *pos++ = NGX_HTTP_V2_ENCODE_RAW | 3; pos = ngx_sprintf(pos, "%03ui", r->headers_out.status); } if (r->headers_out.server == NULL) { ngx_log_debug1(NGX_LOG_DEBUG_HTTP, fc->log, 0, "http2 output header: \"server: %s\"", clcf->server_tokens ? NGINX_VER : "nginx"); *pos++ = ngx_http_v2_inc_indexed(NGX_HTTP_V2_SERVER_INDEX); if (clcf->server_tokens) { if (nginx_ver[0] == '\0') { p = ngx_http_v2_write_value(nginx_ver, (u_char *) NGINX_VER, sizeof(NGINX_VER) - 1, tmp); nginx_ver_len = p - nginx_ver; } pos = ngx_cpymem(pos, nginx_ver, nginx_ver_len); } else { pos = ngx_cpymem(pos, nginx, sizeof(nginx)); } } if (r->headers_out.date == NULL) { ngx_log_debug1(NGX_LOG_DEBUG_HTTP, fc->log, 0, "http2 output header: \"date: %V\"", &ngx_cached_http_time); *pos++ = ngx_http_v2_inc_indexed(NGX_HTTP_V2_DATE_INDEX); pos = ngx_http_v2_write_value(pos, ngx_cached_http_time.data, ngx_cached_http_time.len, tmp); } if (r->headers_out.content_type.len) { *pos++ = ngx_http_v2_inc_indexed(NGX_HTTP_V2_CONTENT_TYPE_INDEX); if (r->headers_out.content_type_len == r->headers_out.content_type.len && r->headers_out.charset.len) { len = r->headers_out.content_type.len + sizeof("; charset=") - 1 + r->headers_out.charset.len; p = ngx_pnalloc(r->pool, len); if (p == NULL) { return NGX_ERROR; } p = ngx_cpymem(p, r->headers_out.content_type.data, r->headers_out.content_type.len); p = ngx_cpymem(p, "; charset=", sizeof("; charset=") - 1); p = ngx_cpymem(p, r->headers_out.charset.data, r->headers_out.charset.len); /* updated r->headers_out.content_type is also needed for logging */ r->headers_out.content_type.len = len; r->headers_out.content_type.data = p - len; } ngx_log_debug1(NGX_LOG_DEBUG_HTTP, fc->log, 0, "http2 output header: \"content-type: %V\"", &r->headers_out.content_type); pos = ngx_http_v2_write_value(pos, r->headers_out.content_type.data, r->headers_out.content_type.len, tmp); } if (r->headers_out.content_length == NULL && r->headers_out.content_length_n >= 0) { ngx_log_debug1(NGX_LOG_DEBUG_HTTP, fc->log, 0, "http2 output header: \"content-length: %O\"", r->headers_out.content_length_n); *pos++ = ngx_http_v2_inc_indexed(NGX_HTTP_V2_CONTENT_LENGTH_INDEX); p = pos; pos = ngx_sprintf(pos + 1, "%O", r->headers_out.content_length_n); *p = NGX_HTTP_V2_ENCODE_RAW | (u_char) (pos - p - 1); } if (r->headers_out.last_modified == NULL && r->headers_out.last_modified_time != -1) { *pos++ = ngx_http_v2_inc_indexed(NGX_HTTP_V2_LAST_MODIFIED_INDEX); ngx_http_time(pos, r->headers_out.last_modified_time); len = sizeof("Wed, 31 Dec 1986 18:00:00 GMT") - 1; ngx_log_debug2(NGX_LOG_DEBUG_HTTP, fc->log, 0, "http2 output header: \"last-modified: %*s\"", len, pos); /* * Date will always be encoded using huffman in the temporary buffer, * so it's safe here to use src and dst pointing to the same address. */ pos = ngx_http_v2_write_value(pos, pos, len, tmp); } if (r->headers_out.location && r->headers_out.location->value.len) { ngx_log_debug1(NGX_LOG_DEBUG_HTTP, fc->log, 0, "http2 output header: \"location: %V\"", &r->headers_out.location->value); *pos++ = ngx_http_v2_inc_indexed(NGX_HTTP_V2_LOCATION_INDEX); pos = ngx_http_v2_write_value(pos, r->headers_out.location->value.data, r->headers_out.location->value.len, tmp); } #if (NGX_HTTP_GZIP) if (r->gzip_vary) { ngx_log_debug0(NGX_LOG_DEBUG_HTTP, fc->log, 0, "http2 output header: \"vary: Accept-Encoding\""); *pos++ = ngx_http_v2_inc_indexed(NGX_HTTP_V2_VARY_INDEX); pos = ngx_cpymem(pos, accept_encoding, sizeof(accept_encoding)); } #endif part = &r->headers_out.headers.part; header = part->elts; for (i = 0; /* void */; i++) { if (i >= part->nelts) { if (part->next == NULL) { break; } part = part->next; header = part->elts; i = 0; } if (header[i].hash == 0) { continue; } #if (NGX_DEBUG) if (fc->log->log_level & NGX_LOG_DEBUG_HTTP) { ngx_strlow(tmp, header[i].key.data, header[i].key.len); ngx_log_debug3(NGX_LOG_DEBUG_HTTP, fc->log, 0, "http2 output header: \"%*s: %V\"", header[i].key.len, tmp, &header[i].value); } #endif *pos++ = 0; pos = ngx_http_v2_write_name(pos, header[i].key.data, header[i].key.len, tmp); pos = ngx_http_v2_write_value(pos, header[i].value.data, header[i].value.len, tmp); } frame = ngx_http_v2_create_headers_frame(r, start, pos); if (frame == NULL) { return NGX_ERROR; } ngx_http_v2_queue_blocked_frame(r->stream->connection, frame); cln = ngx_http_cleanup_add(r, 0); if (cln == NULL) { return NGX_ERROR; } cln->handler = ngx_http_v2_filter_cleanup; cln->data = r->stream; r->stream->queued = 1; fc->send_chain = ngx_http_v2_send_chain; fc->need_last_buf = 1; return ngx_http_v2_filter_send(fc, r->stream); }
static ngx_int_t ngx_http_lua_body_filter(ngx_http_request_t *r, ngx_chain_t *in) { ngx_http_lua_loc_conf_t *llcf; ngx_http_lua_ctx_t *ctx; ngx_int_t rc; uint8_t old_context; ngx_http_cleanup_t *cln; ngx_http_lua_main_conf_t *lmcf; lua_State *L; ngx_chain_t *out; ngx_buf_tag_t tag; ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "lua body filter for user lua code, uri \"%V\"", &r->uri); if (in == NULL) { return ngx_http_next_body_filter(r, in); } llcf = ngx_http_get_module_loc_conf(r, ngx_http_lua_module); if (llcf->body_filter_handler == NULL) { dd("no body filter handler found"); return ngx_http_next_body_filter(r, in); } ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module); dd("ctx = %p", ctx); if (ctx == NULL) { ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_lua_ctx_t)); if (ctx == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } dd("setting new ctx: ctx = %p", ctx); ctx->entry_ref = LUA_NOREF; ctx->ctx_ref = LUA_NOREF; ngx_http_set_ctx(r, ctx, ngx_http_lua_module); } if (ctx->cleanup == NULL) { cln = ngx_http_cleanup_add(r, 0); if (cln == NULL) { return NGX_ERROR; } cln->handler = ngx_http_lua_request_cleanup; cln->data = r; ctx->cleanup = &cln->handler; } old_context = ctx->context; ctx->context = NGX_HTTP_LUA_CONTEXT_BODY_FILTER; dd("calling body filter handler"); rc = llcf->body_filter_handler(r, in); dd("calling body filter handler returned %d", (int) rc); ctx->context = old_context; if (rc != NGX_OK) { return NGX_ERROR; } lmcf = ngx_http_get_module_main_conf(r, ngx_http_lua_module); L = lmcf->lua; lua_pushlightuserdata(L, &ngx_http_lua_body_filter_chain_key); lua_rawget(L, LUA_GLOBALSINDEX); out = lua_touserdata(L, -1); lua_pop(L, 1); if (in == out) { return ngx_http_next_body_filter(r, in); } /* in != out */ rc = ngx_http_next_body_filter(r, out); if (rc == NGX_ERROR) { return NGX_ERROR; } tag = (ngx_buf_tag_t) &ngx_http_lua_module; #if nginx_version >= 1001004 ngx_chain_update_chains(r->pool, #else ngx_chain_update_chains( #endif &ctx->free_bufs, &ctx->busy_bufs, &out, tag); return rc; }
void ngx_http_upstream_dbd_init_request(ngx_http_request_t *r) { ngx_str_t *host; ngx_uint_t i; ngx_resolver_ctx_t *ctx, temp; ngx_http_cleanup_t *cln; ngx_http_upstream_t *u; ngx_http_core_loc_conf_t *clcf; ngx_http_upstream_srv_conf_t *uscf, **uscfp; ngx_http_upstream_main_conf_t *umcf; #if defined(nginx_version) && nginx_version >= 8011 if (r->aio) { return; } #endif u = r->upstream; #if 0 && (NGX_HTTP_CACHE) if (u->conf->cache) { ngx_int_t rc; rc = ngx_http_upstream_cache(r, u); if (rc == NGX_BUSY) { r->write_event_handler = ngx_http_upstream_init_request; return; } r->write_event_handler = ngx_http_request_empty_handler; if (rc == NGX_DONE) { return; } if (rc != NGX_DECLINED) { ngx_http_finalize_request(r, rc); return; } } #endif u->store = (u->conf->store || u->conf->store_lengths); if (!u->store && !r->post_action && !u->conf->ignore_client_abort) { r->read_event_handler = ngx_http_upstream_dbd_rd_check_broken_connection; r->write_event_handler = ngx_http_upstream_dbd_wr_check_broken_connection; } if (r->request_body) { u->request_bufs = r->request_body->bufs; } if (u->create_request(r) != NGX_OK) { ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); return; } #if defined(nginx_version) && nginx_version >= 8022 u->peer.local = u->conf->local; #endif clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); #if defined(nginx_version) && nginx_version >= 8011 u->output.alignment = clcf->directio_alignment; #endif u->output.pool = r->pool; u->output.bufs.num = 1; u->output.bufs.size = clcf->client_body_buffer_size; u->output.output_filter = ngx_chain_writer; u->output.filter_ctx = &u->writer; u->writer.pool = r->pool; if (r->upstream_states == NULL) { r->upstream_states = ngx_array_create(r->pool, 1, sizeof(ngx_http_upstream_state_t)); if (r->upstream_states == NULL) { ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); return; } } else { u->state = ngx_array_push(r->upstream_states); if (u->state == NULL) { ngx_http_upstream_drizzle_finalize_request(r, u, NGX_HTTP_INTERNAL_SERVER_ERROR); return; } ngx_memzero(u->state, sizeof(ngx_http_upstream_state_t)); } cln = ngx_http_cleanup_add(r, 0); if (cln == NULL) { ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); return; } cln->handler = ngx_http_upstream_dbd_cleanup; cln->data = r; u->cleanup = &cln->handler; if (u->resolved == NULL) { uscf = u->conf->upstream; } else { if (u->resolved->sockaddr) { if (ngx_http_upstream_create_round_robin_peer(r, u->resolved) != NGX_OK) { ngx_http_upstream_drizzle_finalize_request(r, u, NGX_HTTP_INTERNAL_SERVER_ERROR); return; } ngx_http_upstream_dbd_connect(r, u); return; } host = &u->resolved->host; umcf = ngx_http_get_module_main_conf(r, ngx_http_upstream_module); uscfp = umcf->upstreams.elts; for (i = 0; i < umcf->upstreams.nelts; i++) { uscf = uscfp[i]; if (uscf->host.len == host->len && ((uscf->port == 0 && u->resolved->no_port) || uscf->port == u->resolved->port) && ngx_memcmp(uscf->host.data, host->data, host->len) == 0) { goto found; } } temp.name = *host; ctx = ngx_resolve_start(clcf->resolver, &temp); if (ctx == NULL) { ngx_http_upstream_drizzle_finalize_request(r, u, NGX_HTTP_INTERNAL_SERVER_ERROR); return; } if (ctx == NGX_NO_RESOLVER) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "no resolver defined to resolve %V", host); ngx_http_upstream_drizzle_finalize_request(r, u, NGX_HTTP_BAD_GATEWAY); return; } #if 0 ctx->name = *host; ctx->type = NGX_RESOLVE_A; ctx->handler = ngx_http_upstream_resolve_handler; ctx->data = r; ctx->timeout = clcf->resolver_timeout; u->resolved->ctx = ctx; if (ngx_resolve_name(ctx) != NGX_OK) { u->resolved->ctx = NULL; ngx_http_upstream_drizzle_finalize_request(r, u, NGX_HTTP_INTERNAL_SERVER_ERROR); return; } #endif return; } found: if (uscf->peer.init(r, uscf) != NGX_OK) { ngx_http_upstream_drizzle_finalize_request(r, u, NGX_HTTP_INTERNAL_SERVER_ERROR); return; } ngx_http_upstream_dbd_connect(r, u); }
static ngx_int_t ngx_http_lua_body_filter(ngx_http_request_t *r, ngx_chain_t *in) { ngx_http_lua_loc_conf_t *llcf; ngx_http_lua_ctx_t *ctx; ngx_int_t rc; uint16_t old_context; ngx_http_cleanup_t *cln; lua_State *L; ngx_chain_t *out; ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "lua body filter for user lua code, uri \"%V\"", &r->uri); if (in == NULL) { return ngx_http_next_body_filter(r, in); } llcf = ngx_http_get_module_loc_conf(r, ngx_http_lua_module); if (llcf->body_filter_handler == NULL) { dd("no body filter handler found"); return ngx_http_next_body_filter(r, in); } ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module); dd("ctx = %p", ctx); if (ctx == NULL) { ctx = ngx_http_lua_create_ctx(r); if (ctx == NULL) { return NGX_ERROR; } } if (ctx->seen_last_in_filter) { for (/* void */; in; in = in->next) { dd("mark the buf as consumed: %d", (int) ngx_buf_size(in->buf)); in->buf->pos = in->buf->last; in->buf->file_pos = in->buf->file_last; } return NGX_OK; } if (ctx->cleanup == NULL) { cln = ngx_http_cleanup_add(r, 0); if (cln == NULL) { return NGX_ERROR; } cln->handler = ngx_http_lua_request_cleanup_handler; cln->data = ctx; ctx->cleanup = &cln->handler; } old_context = ctx->context; ctx->context = NGX_HTTP_LUA_CONTEXT_BODY_FILTER; dd("calling body filter handler"); rc = llcf->body_filter_handler(r, in); dd("calling body filter handler returned %d", (int) rc); ctx->context = old_context; if (rc != NGX_OK) { return NGX_ERROR; } L = ngx_http_lua_get_lua_vm(r, ctx); lua_getglobal(L, ngx_http_lua_chain_key); out = lua_touserdata(L, -1); lua_pop(L, 1); if (in == out) { return ngx_http_next_body_filter(r, in); } if (out == NULL) { /* do not forward NULL to the next filters because the input is * not NULL */ return NGX_OK; } /* in != out */ rc = ngx_http_next_body_filter(r, out); if (rc == NGX_ERROR) { return NGX_ERROR; } #if nginx_version >= 1001004 ngx_chain_update_chains(r->pool, #else ngx_chain_update_chains( #endif &ctx->free_bufs, &ctx->busy_bufs, &out, (ngx_buf_tag_t) &ngx_http_lua_module); return rc; }
subscriber_t *websocket_subscriber_create(ngx_http_request_t *r, nchan_msg_id_t *msg_id) { nchan_request_ctx_t *ctx = ngx_http_get_module_ctx(r, ngx_nchan_module); DBG("create for req %p", r); full_subscriber_t *fsub; if((fsub = ngx_alloc(sizeof(*fsub), ngx_cycle->log)) == NULL) { ERR("Unable to allocate"); return NULL; } nchan_subscriber_init(&fsub->sub, &new_websocket_sub, r, msg_id); fsub->cln = NULL; fsub->ctx = ctx; fsub->ws_meta_subprotocol = 0; fsub->finalize_request = 0; fsub->holding = 0; fsub->shook_hands = 0; fsub->connected = 0; fsub->pinging = 0; fsub->closing = 0; ngx_memzero(&fsub->ping_ev, sizeof(fsub->ping_ev)); nchan_subscriber_init_timeout_timer(&fsub->sub, &fsub->timeout_ev); fsub->dequeue_handler = empty_handler; fsub->dequeue_handler_data = NULL; fsub->awaiting_destruction = 0; ngx_memzero(&fsub->closing_ev, sizeof(fsub->closing_ev)); #if nginx_version >= 1008000 fsub->closing_ev.cancelable = 1; #endif //what should the buffers look like? /* //mesage buf b->last_buf = 1; b->last_in_chain = 1; b->flush = 1; b->memory = 1; b->temporary = 0; */ if(fsub->sub.cf->pub.websocket) { fsub->publish_channel_id = nchan_get_channel_id(r, PUB, 0); } fsub->upstream_stuff = NULL; websocket_init_frame(&fsub->frame); //http request sudden close cleanup if((fsub->cln = ngx_http_cleanup_add(r, 0)) == NULL) { ERR("Unable to add request cleanup for websocket subscriber"); return NULL; } fsub->cln->data = fsub; fsub->cln->handler = (ngx_http_cleanup_pt )sudden_abort_handler; DBG("%p created for request %p", &fsub->sub, r); assert(ctx != NULL); ctx->sub = &fsub->sub; //gonna need this for recv ctx->subscriber_type = fsub->sub.name; #if NCHAN_SUBSCRIBER_LEAK_DEBUG subscriber_debug_add(&fsub->sub); #endif //send-frame buffer ctx->output_str_queue = ngx_palloc(r->pool, sizeof(*ctx->output_str_queue)); nchan_reuse_queue_init(ctx->output_str_queue, offsetof(framebuf_t, prev), offsetof(framebuf_t, next), framebuf_alloc, NULL, r->pool); //bufchain pool ctx->bcp = ngx_palloc(r->pool, sizeof(nchan_bufchain_pool_t)); nchan_bufchain_pool_init(ctx->bcp, r->pool); return &fsub->sub; }