static ngx_int_t ngx_http_status_codes_statistics(ngx_http_request_t *r) { ngx_http_traffic_status_rule_t *rucf = NULL; rucf = ngx_http_get_module_srv_conf(r, ngx_http_traffic_status_module); if (NULL == rucf) { return NGX_ERROR; } ngx_int_t index = r->headers_out.status; if (index >= NGX_HTTP_OK && index < NGX_HTTP_LAST_LEVEL_500) { ++rucf->status_codes_cnt[index - NGX_HTTP_OK]; } /* request times */ ++rucf->request_cnt; /* recevie packet bytes */ rucf->recv_bytes += r->request_length; /* send packet bytes */ rucf->send_bytes += r->connection->sent; return NGX_HTTP_OK; }
static void ngx_http_zm_sso_cert_auth_on_failure(ngx_zm_lookup_work_t *w) { ngx_http_request_t *r; ngx_http_ssl_srv_conf_t *hscf; ngx_int_t rc; r = w->data; hscf = ngx_http_get_module_srv_conf(r, ngx_http_ssl_module); if (w->result == ZM_LOOKUP_LOGIN_FAILED) { ngx_log_error (NGX_LOG_WARN, w->log, 0, "login failed for subject dn %V during client cert auth" ", reason:%V", &w->username, &w->err); if (hscf->verify == 1) { // verify client cert mode is on ngx_http_zm_sso_finalize_request(r, NGX_HTTP_FORBIDDEN); } else { // verify client cert mode is optional rc = ngx_http_zm_sso_redirect (r); ngx_http_zm_sso_finalize_request(r, rc); } } else { ngx_http_zm_sso_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); } }
static ngx_int_t ngx_http_vhost_traffic_status_handler(ngx_http_request_t *r) { ngx_int_t rc; ngx_http_vhost_traffic_status_ctx_t *ctx; ngx_http_vhost_traffic_status_loc_conf_t *vtscf; ngx_http_core_srv_conf_t *cscf; ctx = ngx_http_get_module_main_conf(r, ngx_http_vhost_traffic_status_module); vtscf = ngx_http_get_module_loc_conf(r, ngx_http_vhost_traffic_status_module); if (!ctx->enable || !vtscf->enable) { return NGX_DECLINED; } if (vtscf->shm_zone == NULL) { return NGX_DECLINED; } cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module); rc = ngx_http_vhost_traffic_status_shm_add_server(r, ctx, cscf, vtscf); if (rc != NGX_OK) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "shm_add_server failed"); } rc = ngx_http_vhost_traffic_status_shm_add_upstream(r, ctx, cscf, vtscf); if (rc != NGX_OK) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "shm_add_upstream failed"); } return NGX_DECLINED; }
static void ngx_http_proxy_connect_read_hello_data(ngx_http_request_t *r) { ngx_int_t n; ngx_buf_t *buf; ngx_connection_t *c; ngx_http_core_srv_conf_t *cscf; ngx_http_proxy_connect_ctx_t *ctx; c = r->connection; ctx = ngx_http_get_module_ctx(r,ngx_http_proxy_connect_module); buf = ctx->client_hello; if (c->read->timedout) { c->timedout = 1; ngx_connection_error(c, NGX_ETIMEDOUT, "client timed out"); ngx_http_finalize_request(r, NGX_HTTP_REQUEST_TIME_OUT); return; } if (c->read->ready) { n = c->recv(c, buf->start, 4096); } else { return; } if (n == NGX_AGAIN) { if (!c->read->timer_set) { cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module); ngx_add_timer(c->read, cscf->client_header_timeout); } if (ngx_handle_read_event(c->read, 0) != NGX_OK) { ngx_http_finalize_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); return; } return; } if (n == 0) { ngx_log_error(NGX_LOG_INFO, c->log, 0, "client prematurely closed connection"); } if (n == 0 || n == NGX_ERROR) { c->error = 1; c->log->action = "reading https client hello data"; ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST); return; } if (c->read->timer_set) { ngx_del_timer(c->read); } buf->last = buf->pos + n; ngx_http_proxy_connect_upstream(r); }
static ngx_http_google_ctx_t * ngx_http_google_create_ctx(ngx_http_request_t * r) { ngx_http_google_loc_conf_t * glcf; glcf = ngx_http_get_module_loc_conf(r, ngx_http_google_filter_module); ngx_http_google_ctx_t * ctx; ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_google_ctx_t)); if (!ctx) return NULL; ctx->host = ngx_pcalloc(r->pool, sizeof(ngx_str_t)); if (!ctx->host) return NULL; ctx->pass = ngx_pcalloc(r->pool, sizeof(ngx_str_t)); if (!ctx->pass) return NULL; ctx->arg = ngx_pcalloc(r->pool, sizeof(ngx_str_t)); if (!ctx->arg) return NULL; ctx->domain = ngx_pcalloc(r->pool, sizeof(ngx_str_t)); if (!ctx->domain) return NULL; ctx->uri = &r->unparsed_uri; ctx->host = &r->headers_in.host->value; ctx->lang = &glcf->language; ctx->type = ngx_http_google_type_main; ngx_str_t domain = *ctx->host; u_char * last = domain.data + domain.len, * find; if ((find = ngx_strlchr(domain.data, last, ':'))) { domain.len = find - domain.data; } ctx->domain->len = domain.len + 1; ctx->domain->data = ngx_pcalloc(r->pool, ctx->domain->len); if (!ctx->domain->data) return NULL; ngx_snprintf(ctx->domain->data, ctx->domain->len, ".%V", &domain); if (ngx_inet_addr(domain.data, domain.len) != INADDR_NONE) { ctx->domain->data++; ctx->domain->len --; } // default language if (!ctx->lang->len) { ngx_str_set(ctx->lang, "zh-CN"); } ctx->robots = (ctx->uri->len == 11 && !ngx_strncmp(ctx->uri->data, "/robots.txt", 11)); #if (NGX_HTTP_SSL) ngx_http_ssl_srv_conf_t * sscf; sscf = ngx_http_get_module_srv_conf(r, ngx_http_ssl_module); if (sscf->enable == 1) ctx->ssl = 1; #endif return ctx; }
static ngx_int_t ngx_http_rewrite_handler(ngx_http_request_t *r) { ngx_int_t index; ngx_http_script_code_pt code; ngx_http_script_engine_t *e; ngx_http_core_srv_conf_t *cscf; ngx_http_core_main_conf_t *cmcf; ngx_http_rewrite_loc_conf_t *rlcf; cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module); cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module); index = cmcf->phase_engine.location_rewrite_index; if (r->phase_handler == index && r->loc_conf == cscf->ctx->loc_conf) { /* skipping location rewrite phase for server null location */ return NGX_DECLINED; } rlcf = ngx_http_get_module_loc_conf(r, ngx_http_rewrite_module); if (rlcf->codes == NULL) { return NGX_DECLINED; } e = ngx_pcalloc(r->pool, sizeof(ngx_http_script_engine_t)); if (e == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } e->sp = ngx_pcalloc(r->pool, rlcf->stack_size * sizeof(ngx_http_variable_value_t)); if (e->sp == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } e->ip = rlcf->codes->elts; e->request = r; e->quote = 1; e->log = rlcf->log; e->status = NGX_DECLINED; while (*(uintptr_t *) e->ip) { code = *(ngx_http_script_code_pt *) e->ip; code(e); } if (e->status < NGX_HTTP_BAD_REQUEST) { return e->status; } if (r->err_status == 0) { return e->status; } return r->err_status; }
static ngx_int_t ngx_http_variable_server_name(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data) { ngx_http_core_srv_conf_t *cscf; cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module); v->len = cscf->server_name.len; v->valid = 1; v->no_cacheable = 0; v->not_found = 0; v->data = cscf->server_name.data; return NGX_OK; }
static ngx_int_t ngx_http_variable_host(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data) { ngx_http_core_srv_conf_t *cscf; if (r->headers_in.server.len) { v->len = r->headers_in.server.len; v->data = r->headers_in.server.data; } else { cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module); v->len = cscf->server_name.len; v->data = cscf->server_name.data; } v->valid = 1; v->no_cacheable = 0; v->not_found = 0; return NGX_OK; }
static int ngx_http_ssl_npn_advertised(ngx_ssl_conn_t *ssl_conn, const unsigned char **out, unsigned int *outlen, void *arg) { #if (NGX_HTTP_SPDY || NGX_DEBUG) ngx_connection_t *c; c = ngx_ssl_get_connection(ssl_conn); ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "SSL NPN advertised"); #endif #if (NGX_HTTP_SPDY) { ngx_http_connection_t *hc; ngx_http_spdy_srv_conf_t *sscf; hc = c->data; sscf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_spdy_module); if (hc->addr_conf->spdy) { if (sscf->version == NGX_SPDY_VERSION_V3) { *out = (unsigned char *) NGX_SPDY_V3_NPN_ADVERTISE NGX_HTTP_NPN_ADVERTISE; *outlen = sizeof(NGX_SPDY_V3_NPN_ADVERTISE NGX_HTTP_NPN_ADVERTISE) - 1; } else { *out = (unsigned char *) NGX_SPDY_NPN_ADVERTISE NGX_HTTP_NPN_ADVERTISE; *outlen = sizeof(NGX_SPDY_NPN_ADVERTISE NGX_HTTP_NPN_ADVERTISE) - 1; } return SSL_TLSEXT_ERR_OK; } } #endif *out = (unsigned char *) NGX_HTTP_NPN_ADVERTISE; *outlen = sizeof(NGX_HTTP_NPN_ADVERTISE) - 1; return SSL_TLSEXT_ERR_OK; }
static ngx_int_t ngx_http_session_cookie_hash(ngx_http_request_t *r, ngx_str_t *cookie) { unsigned long h = 0, g, ha; ngx_http_core_srv_conf_t *cscf; u_char *k; ngx_uint_t len; cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module); len = cookie->len + cscf->virtual_server_name.len; k = ngx_pcalloc(r->pool, len); if (!k) { return 0; } memcpy(k, cookie->data, cookie->len); memcpy(k + cookie->len, cscf->virtual_server_name.data, cscf->virtual_server_name.len); while (len) { h = (h << 4) + *k++; g = h & 0xf0000000l; if (g) h ^= g >> 24; h &= ~g; len--; } ha = h % NGX_HTTP_SESSION_DEFAULT_NUMBER; ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "session hash: %u\n", ha); return ha; }
static ngx_int_t ngx_http_zm_sso_handler(ngx_http_request_t *r) { ngx_http_zm_sso_loc_conf_t *zlcf; ngx_http_ssl_srv_conf_t *hscf; ngx_zm_lookup_work_t *w; zlcf = ngx_http_get_module_loc_conf(r, ngx_http_zm_sso_module); hscf = ngx_http_get_module_srv_conf(r, ngx_http_ssl_module); if (hscf->verify == 0) { /* ssl_verify_client is off */ ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, "client has to enable client cert auth when accessing this url. " "please set this server block's \"ssl_verify_client\" to \"on\" " "or \"optional\""); return NGX_HTTP_FORBIDDEN; } w = ngx_pcalloc (r->pool, sizeof(ngx_zm_lookup_work_t)); if (w == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } w->data = r; w->pool = r->pool; w->log = r->connection->log; if (zlcf->type == NGX_ZM_SSO_CERTAUTH || zlcf->type == NGX_ZM_SSO_CERTAUTH_ADMIN) { return ngx_http_zm_sso_cert_auth(r, w); } else { /* Should never execute here */ return NGX_HTTP_INTERNAL_SERVER_ERROR; } }
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_tfs_handler(ngx_http_request_t *r) { ngx_int_t rc; ngx_http_tfs_t *t; ngx_http_tfs_loc_conf_t *tlcf; ngx_http_tfs_srv_conf_t *tscf; ngx_http_tfs_main_conf_t *tmcf; tlcf = ngx_http_get_module_loc_conf(r, ngx_http_tfs_module); tscf = ngx_http_get_module_srv_conf(r, ngx_http_tfs_module); tmcf = ngx_http_get_module_main_conf(r, ngx_http_tfs_module); t = ngx_pcalloc(r->pool, sizeof(ngx_http_tfs_t)); if (t == NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "alloc ngx_http_tfs_t failed"); return NGX_HTTP_INTERNAL_SERVER_ERROR; } t->pool = r->pool; t->data = r; t->log = r->connection->log; t->loc_conf = tlcf; t->srv_conf = tscf; t->main_conf = tmcf; t->output.tag = (ngx_buf_tag_t) &ngx_http_tfs_module; if (tmcf->local_block_cache_ctx != NULL) { t->block_cache_ctx.use_cache |= NGX_HTTP_TFS_LOCAL_BLOCK_CACHE; t->block_cache_ctx.local_ctx = tmcf->local_block_cache_ctx; } if (tmcf->enable_remote_block_cache == NGX_HTTP_TFS_YES) { t->block_cache_ctx.use_cache |= NGX_HTTP_TFS_REMOTE_BLOCK_CACHE; } t->block_cache_ctx.remote_ctx.data = t; t->block_cache_ctx.remote_ctx.tair_instance = &tmcf->remote_block_cache_instance; t->block_cache_ctx.curr_lookup_cache = NGX_HTTP_TFS_LOCAL_BLOCK_CACHE; rc = ngx_http_restful_parse(r, &t->r_ctx); if (rc != NGX_OK) { return rc; } t->header_only = r->header_only; if (!tmcf->enable_rcs && t->r_ctx.version == 2) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "custom file requires tfs_enable_rcs on," " and make sure you have MetaServer and RootServer!"); return NGX_HTTP_BAD_REQUEST; } switch (t->r_ctx.action.code) { case NGX_HTTP_TFS_ACTION_CREATE_DIR: case NGX_HTTP_TFS_ACTION_CREATE_FILE: case NGX_HTTP_TFS_ACTION_REMOVE_DIR: case NGX_HTTP_TFS_ACTION_REMOVE_FILE: case NGX_HTTP_TFS_ACTION_MOVE_DIR: case NGX_HTTP_TFS_ACTION_MOVE_FILE: case NGX_HTTP_TFS_ACTION_LS_DIR: case NGX_HTTP_TFS_ACTION_LS_FILE: case NGX_HTTP_TFS_ACTION_STAT_FILE: case NGX_HTTP_TFS_ACTION_KEEPALIVE: case NGX_HTTP_TFS_ACTION_READ_FILE: case NGX_HTTP_TFS_ACTION_GET_APPID: rc = ngx_http_discard_request_body(r); if (rc != NGX_OK) { return rc; } r->headers_out.content_length_n = -1; ngx_http_set_ctx(r, t, ngx_http_tfs_module); r->main->count++; ngx_http_tfs_read_body_handler(r); break; case NGX_HTTP_TFS_ACTION_WRITE_FILE: r->headers_out.content_length_n = -1; ngx_http_set_ctx(r, t, ngx_http_tfs_module); rc = ngx_http_read_client_request_body(r, ngx_http_tfs_read_body_handler); if (rc >= NGX_HTTP_SPECIAL_RESPONSE) { return rc; } break; } return NGX_DONE; }
static ngx_inline ngx_int_t ngx_http_modsecurity_save_request_body(ngx_http_request_t *r) { ngx_http_modsecurity_ctx_t *ctx; apr_off_t content_length; ngx_buf_t *buf; ngx_http_core_srv_conf_t *cscf; size_t size; ngx_http_connection_t *hc; ctx = ngx_http_get_module_ctx(r, ngx_http_modsecurity); apr_brigade_length(ctx->brigade, 0, &content_length); if (r->header_in->end - r->header_in->last >= content_length) { /* use r->header_in */ if (ngx_buf_size(r->header_in)) { /* move to the end */ ngx_memmove(r->header_in->pos + content_length, r->header_in->pos, ngx_buf_size(r->header_in)); } if (apr_brigade_flatten(ctx->brigade, (char *)r->header_in->pos, (apr_size_t *)&content_length) != APR_SUCCESS) { return NGX_ERROR; } apr_brigade_cleanup(ctx->brigade); r->header_in->last += content_length; return NGX_OK; } if (ngx_buf_size(r->header_in)) { /* * ngx_http_set_keepalive will reuse r->header_in if * (r->header_in != c->buffer && r->header_in.last != r->header_in.end), * so we need this code block. * see ngx_http_set_keepalive, ngx_http_alloc_large_header_buffer */ cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module); size = ngx_max(cscf->large_client_header_buffers.size, (size_t)content_length + ngx_buf_size(r->header_in)); hc = r->http_connection; if (hc->nfree && size == cscf->large_client_header_buffers.size) { buf = hc->free[--hc->nfree]; ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "ModSecurity: use http free large header buffer: %p %uz", buf->pos, buf->end - buf->last); } else if (hc->nbusy < cscf->large_client_header_buffers.num) { if (hc->busy == NULL) { hc->busy = ngx_palloc(r->connection->pool, cscf->large_client_header_buffers.num * sizeof(ngx_buf_t *)); } if (hc->busy == NULL) { return NGX_ERROR; } else { buf = ngx_create_temp_buf(r->connection->pool, size); } } else { /* TODO: how to deal this case ? */ return NGX_ERROR; } } else { buf = ngx_create_temp_buf(r->pool, (size_t) content_length); } if (buf == NULL) { return NGX_ERROR; } if (apr_brigade_flatten(ctx->brigade, (char *)buf->pos, (apr_size_t *)&content_length) != APR_SUCCESS) { return NGX_ERROR; } apr_brigade_cleanup(ctx->brigade); buf->last += content_length; ngx_memcpy(buf->last, r->header_in->pos, ngx_buf_size(r->header_in)); buf->last += ngx_buf_size(r->header_in); r->header_in = buf; return NGX_OK; }
static void ngx_tcp2http_init_session(ngx_event_t *rev) { size_t size; ssize_t n; ngx_buf_t *b; ngx_connection_t *c; ngx_http_connection_t *hc; ngx_http_core_srv_conf_t *cscf; c = rev->data; //ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, "http wait request handler"); ngx_log_error(NGX_LOG_ERR, c->log, 0, "init session"); if (rev->timedout) { ngx_log_error(NGX_LOG_INFO, c->log, NGX_ETIMEDOUT, "client timed out"); ngx_http_close_connection(c); return; } if (c->close) { ngx_http_close_connection(c); return; } hc = c->data; cscf = ngx_http_get_module_srv_conf(hc->conf_ctx, ngx_http_core_module); size = cscf->client_header_buffer_size; b = c->buffer; if (b == NULL) { b = ngx_create_temp_buf(c->pool, size); if (b == NULL) { ngx_http_close_connection(c); return; } c->buffer = b; } else if (b->start == NULL) { b->start = ngx_palloc(c->pool, size); if (b->start == NULL) { ngx_http_close_connection(c); return; } b->pos = b->start; b->last = b->start; b->end = b->last + size; } c->data = ngx_http_create_request(c); if (c->data == NULL) { ngx_http_close_connection(c); return; } rev->handler = ngx_tcp2http_process_session; ngx_tcp2http_process_session(rev); }
/*=wait_request*/ static void ngx_tcp2http_process_session(ngx_event_t *rev) { ssize_t n; ngx_int_t rc, rv; ngx_str_t host; ngx_connection_t *c; ngx_http_request_t *r; ngx_http_core_srv_conf_t *cscf; c = rev->data; r = c->data; cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module); ngx_log_error(NGX_LOG_DEBUG, c->log, 0, "http request line: \"%V\"", &r->request_line); rc = NGX_AGAIN; char * request="GET /\r\n\r\n"; sprintf(r->header_in->last,request); r->header_in->last += ngx_strlen(request); rc = ngx_http_parse_request_line(r, r->header_in); if (rc == NGX_OK) { /* the request line has been parsed successfully */ r->request_line.len = r->request_end - r->request_start; r->request_line.data = r->request_start; r->request_length = r->header_in->pos - r->request_start; ngx_http_probe_read_req_line_done(r); ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0, "http request line: \"%V\"", &r->request_line); r->method_name.len = r->method_end - r->request_start + 1; r->method_name.data = r->request_line.data; if (r->http_protocol.data) { r->http_protocol.len = r->request_end - r->http_protocol.data; } if (ngx_http_process_request_uri(r) != NGX_OK) { return; } if (r->host_start && r->host_end) { host.len = r->host_end - r->host_start; host.data = r->host_start; rc = ngx_http_validate_host(&host, r->pool, 0); if (rc == NGX_DECLINED) { ngx_log_error(NGX_LOG_INFO, c->log, 0, "client sent invalid host in request line"); ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST); return; } if (rc == NGX_ERROR) { ngx_tcp2http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); return; } if (ngx_http_set_virtual_server(r, &host) == NGX_ERROR) { return; } r->headers_in.server = host; } if (r->http_version < NGX_HTTP_VERSION_10) { if (r->headers_in.server.len == 0 && ngx_http_set_virtual_server(r, &r->headers_in.server) == NGX_ERROR) { return; } ngx_http_process_request(r); return; } if (ngx_list_init(&r->headers_in.headers, r->pool, 20, sizeof(ngx_table_elt_t)) != NGX_OK) { ngx_tcp2http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); return; } c->log->action = "reading client request headers"; /*rev->handler = ngx_http_process_request_headers; ngx_http_process_request_headers(rev);*/ return; }else{ ngx_tcp2http_close_request(r, NGX_HTTP_REQUEST_TIME_OUT); } /*ngx_http_process_request(r);*/ /* process the ACL */ /*if (ngx_tcp_access_handler(s) == NGX_ERROR) { ngx_tcp2http_finalize_session(s); return; }*/ /* if (cscf->protocol == NULL || cscf->protocol->init_session == NULL) { dd("protocol not initialized"); ngx_tcp2http_finalize_session(s); return; } c->read->handler= ngx_tcp2http_session_handler; c->write->handler= ngx_tcp2http_session_handler; r->read_event_handler = tcp2http_block_reading; rev->handler(rev);*/ }
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 create_request(ngx_http_request_t *r) { u_char ch; const char * helper_agent_request_socket_password_data; unsigned int helper_agent_request_socket_password_len; u_char buf[sizeof("4294967296") + 1]; size_t len, size, key_len, val_len; const u_char *app_type_string; size_t app_type_string_len; int server_name_len; ngx_str_t escaped_uri; ngx_str_t *union_station_filters = NULL; void *tmp; ngx_uint_t i, n; ngx_buf_t *b; ngx_chain_t *cl, *body; ngx_list_part_t *part; ngx_table_elt_t *header; ngx_http_script_code_pt code; ngx_http_script_engine_t e, le; ngx_http_core_srv_conf_t *cscf; passenger_loc_conf_t *slcf; passenger_context_t *context; ngx_http_script_len_code_pt lcode; cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module); slcf = ngx_http_get_module_loc_conf(r, ngx_http_passenger_module); context = ngx_http_get_module_ctx(r, ngx_http_passenger_module); if (context == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } app_type_string = (const u_char *) pp_get_app_type_name(context->app_type); app_type_string_len = strlen((const char *) app_type_string) + 1; /* include null terminator */ /* * Nginx unescapes URI's before passing them to Phusion Passenger, * but backend processes expect the escaped version. * http://code.google.com/p/phusion-passenger/issues/detail?id=404 */ escaped_uri.len = 2 * ngx_escape_uri(NULL, r->uri.data, r->uri.len, NGX_ESCAPE_URI) + r->uri.len; escaped_uri.data = ngx_pnalloc(r->pool, escaped_uri.len + 1); escaped_uri.data[escaped_uri.len] = '\0'; ngx_escape_uri(escaped_uri.data, r->uri.data, r->uri.len, NGX_ESCAPE_URI); /************************************************** * Determine the request header length. **************************************************/ len = 0; /* Length of the Content-Length header. A value of -1 means that the content * length is unspecified, which is the case for e.g. WebSocket requests. */ if (r->headers_in.content_length_n >= 0) { len += sizeof("CONTENT_LENGTH") + uint_to_str(r->headers_in.content_length_n, buf, sizeof(buf)) + 1; /* +1 for trailing null */ } /* DOCUMENT_ROOT, SCRIPT_NAME, RAILS_RELATIVE_URL_ROOT, PATH_INFO and REQUEST_URI. */ len += sizeof("DOCUMENT_ROOT") + context->public_dir.len + 1; if (context->base_uri.len > 0) { len += sizeof("SCRIPT_NAME") + context->base_uri.len + 1; len += sizeof("RAILS_RELATIVE_URL_ROOT") + context->base_uri.len + 1; len += sizeof("PATH_INFO") + escaped_uri.len - context->base_uri.len + 1; } else { len += sizeof("SCRIPT_NAME") + sizeof(""); len += sizeof("PATH_INFO") + escaped_uri.len + 1; } len += sizeof("REQUEST_URI") + escaped_uri.len + 1; if (r->args.len > 0) { len += 1 + r->args.len; } /* SERVER_NAME; must be equal to HTTP_HOST without the port part */ if (r->headers_in.host != NULL) { tmp = memchr(r->headers_in.host->value.data, ':', r->headers_in.host->value.len); if (tmp == NULL) { server_name_len = r->headers_in.host->value.len; } else { server_name_len = (int) ((const u_char *) tmp - r->headers_in.host->value.data); } } else { server_name_len = cscf->server_name.len; } len += sizeof("SERVER_NAME") + server_name_len + 1; /* Various other HTTP headers. */ if (r->headers_in.content_type != NULL && r->headers_in.content_type->value.len > 0) { len += sizeof("CONTENT_TYPE") + r->headers_in.content_type->value.len + 1; } #if (NGX_HTTP_SSL) if (r->http_connection->ssl) { len += sizeof("HTTPS") + sizeof("on"); } #endif /* Lengths of Passenger application pool options. */ len += slcf->options_cache.len; len += sizeof("PASSENGER_APP_TYPE") + app_type_string_len; if (slcf->union_station_filters != NGX_CONF_UNSET_PTR && slcf->union_station_filters->nelts > 0) { len += sizeof("UNION_STATION_FILTERS"); union_station_filters = (ngx_str_t *) slcf->union_station_filters->elts; for (i = 0; i < slcf->union_station_filters->nelts; i++) { if (i != 0) { len++; } len += union_station_filters[i].len; } len++; } /***********************/ /***********************/ /* Lengths of various CGI variables. */ if (slcf->vars_len) { ngx_memzero(&le, sizeof(ngx_http_script_engine_t)); ngx_http_script_flush_no_cacheable_variables(r, slcf->flushes); le.flushed = 1; le.ip = slcf->vars_len->elts; le.request = r; while (*(uintptr_t *) le.ip) { lcode = *(ngx_http_script_len_code_pt *) le.ip; key_len = lcode(&le); for (val_len = 0; *(uintptr_t *) le.ip; val_len += lcode(&le)) { lcode = *(ngx_http_script_len_code_pt *) le.ip; } le.ip += sizeof(uintptr_t); len += key_len + val_len; } } /* Lengths of HTTP headers. */ if (slcf->upstream_config.pass_request_headers) { part = &r->headers_in.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_is_transfer_encoding(&header[i].key)) { len += sizeof("HTTP_") - 1 + header[i].key.len + 1 + header[i].value.len + 1; } } } /************************************************** * Build the request header data. **************************************************/ helper_agent_request_socket_password_data = pp_agents_starter_get_request_socket_password(pp_agents_starter, &helper_agent_request_socket_password_len); size = helper_agent_request_socket_password_len + /* netstring length + ":" + trailing "," */ /* note: 10 == sizeof("4294967296") - 1 */ len + 10 + 1 + 1; b = ngx_create_temp_buf(r->pool, size); if (b == NULL) { return NGX_ERROR; } cl = ngx_alloc_chain_link(r->pool); if (cl == NULL) { return NGX_ERROR; } cl->buf = b; /* Build SCGI header netstring length part. */ b->last = ngx_copy(b->last, helper_agent_request_socket_password_data, helper_agent_request_socket_password_len); b->last = ngx_snprintf(b->last, 10, "%ui", len); *b->last++ = (u_char) ':'; if (r->headers_in.content_length_n >= 0) { b->last = ngx_copy(b->last, "CONTENT_LENGTH", sizeof("CONTENT_LENGTH")); b->last = ngx_snprintf(b->last, 10, "%ui", r->headers_in.content_length_n); *b->last++ = (u_char) 0; } /* Build DOCUMENT_ROOT, SCRIPT_NAME, RAILS_RELATIVE_URL_ROOT, PATH_INFO and REQUEST_URI. */ b->last = ngx_copy(b->last, "DOCUMENT_ROOT", sizeof("DOCUMENT_ROOT")); b->last = ngx_copy(b->last, context->public_dir.data, context->public_dir.len + 1); if (context->base_uri.len > 0) { b->last = ngx_copy(b->last, "SCRIPT_NAME", sizeof("SCRIPT_NAME")); b->last = ngx_copy(b->last, context->base_uri.data, context->base_uri.len + 1); b->last = ngx_copy(b->last, "RAILS_RELATIVE_URL_ROOT", sizeof("RAILS_RELATIVE_URL_ROOT")); b->last = ngx_copy(b->last, context->base_uri.data, context->base_uri.len + 1); b->last = ngx_copy(b->last, "PATH_INFO", sizeof("PATH_INFO")); b->last = ngx_copy(b->last, escaped_uri.data + context->base_uri.len, escaped_uri.len - context->base_uri.len); b->last = ngx_copy(b->last, "", 1); } else { b->last = ngx_copy(b->last, "SCRIPT_NAME", sizeof("SCRIPT_NAME")); b->last = ngx_copy(b->last, "", sizeof("")); b->last = ngx_copy(b->last, "PATH_INFO", sizeof("PATH_INFO")); b->last = ngx_copy(b->last, escaped_uri.data, escaped_uri.len); b->last = ngx_copy(b->last, "", 1); } b->last = ngx_copy(b->last, "REQUEST_URI", sizeof("REQUEST_URI")); b->last = ngx_copy(b->last, escaped_uri.data, escaped_uri.len); if (r->args.len > 0) { b->last = ngx_copy(b->last, "?", 1); b->last = ngx_copy(b->last, r->args.data, r->args.len); } b->last = ngx_copy(b->last, "", 1); /* SERVER_NAME */ b->last = ngx_copy(b->last, "SERVER_NAME", sizeof("SERVER_NAME")); if (r->headers_in.host != NULL) { b->last = ngx_copy(b->last, r->headers_in.host->value.data, server_name_len); } else { b->last = ngx_copy(b->last, cscf->server_name.data, server_name_len); } b->last = ngx_copy(b->last, "", 1); /* Various other HTTP headers. */ if (r->headers_in.content_type != NULL && r->headers_in.content_type->value.len > 0) { b->last = ngx_copy(b->last, "CONTENT_TYPE", sizeof("CONTENT_TYPE")); b->last = ngx_copy(b->last, r->headers_in.content_type->value.data, r->headers_in.content_type->value.len); b->last = ngx_copy(b->last, "", 1); } #if (NGX_HTTP_SSL) if (r->http_connection->ssl) { b->last = ngx_copy(b->last, "HTTPS", sizeof("HTTPS")); b->last = ngx_copy(b->last, "on", sizeof("on")); } #endif /* Build Passenger application pool option headers. */ b->last = ngx_copy(b->last, slcf->options_cache.data, slcf->options_cache.len); b->last = ngx_copy(b->last, "PASSENGER_APP_TYPE", sizeof("PASSENGER_APP_TYPE")); b->last = ngx_copy(b->last, app_type_string, app_type_string_len); if (slcf->union_station_filters != NGX_CONF_UNSET_PTR && slcf->union_station_filters->nelts > 0) { b->last = ngx_copy(b->last, "UNION_STATION_FILTERS", sizeof("UNION_STATION_FILTERS")); for (i = 0; i < slcf->union_station_filters->nelts; i++) { if (i != 0) { b->last = ngx_copy(b->last, "\1", 1); } b->last = ngx_copy(b->last, union_station_filters[i].data, union_station_filters[i].len); } b->last = ngx_copy(b->last, "\0", 1); } /***********************/ /***********************/ if (slcf->vars_len) { ngx_memzero(&e, sizeof(ngx_http_script_engine_t)); e.ip = slcf->vars->elts; e.pos = b->last; e.request = r; e.flushed = 1; le.ip = slcf->vars_len->elts; while (*(uintptr_t *) le.ip) { lcode = *(ngx_http_script_len_code_pt *) le.ip; (void) lcode(&le); for (val_len = 0; *(uintptr_t *) le.ip; val_len += lcode(&le)) { lcode = *(ngx_http_script_len_code_pt *) le.ip; } le.ip += sizeof(uintptr_t); while (*(uintptr_t *) e.ip) { code = *(ngx_http_script_code_pt *) e.ip; code((ngx_http_script_engine_t *) &e); } e.ip += sizeof(uintptr_t); } b->last = e.pos; } if (slcf->upstream_config.pass_request_headers) { part = &r->headers_in.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_is_transfer_encoding(&header[i].key)) { continue; } b->last = ngx_cpymem(b->last, "HTTP_", sizeof("HTTP_") - 1); for (n = 0; n < header[i].key.len; n++) { ch = header[i].key.data[n]; if (ch >= 'a' && ch <= 'z') { ch &= ~0x20; } else if (ch == '-') { ch = '_'; } *b->last++ = ch; } *b->last++ = (u_char) 0; b->last = ngx_copy(b->last, header[i].value.data, header[i].value.len); *b->last++ = (u_char) 0; } } *b->last++ = (u_char) ','; if (slcf->upstream_config.pass_request_body) { body = r->upstream->request_bufs; r->upstream->request_bufs = cl; while (body) { b = ngx_alloc_buf(r->pool); if (b == NULL) { return NGX_ERROR; } ngx_memcpy(b, body->buf, sizeof(ngx_buf_t)); cl->next = ngx_alloc_chain_link(r->pool); if (cl->next == NULL) { return NGX_ERROR; } cl = cl->next; cl->buf = b; body = body->next; } b->flush = 1; } else { r->upstream->request_bufs = cl; } cl->next = NULL; return NGX_OK; }
static ngx_int_t ngx_http_rewrite_handler(ngx_http_request_t *r) { int *matches; u_char *p; size_t len; uintptr_t data; ngx_int_t rc; ngx_uint_t i, m, n; ngx_str_t uri; ngx_http_rewrite_op_t *op; ngx_http_rewrite_rule_t *rule; ngx_http_rewrite_srv_conf_t *scf; ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http rewrite handler"); scf = ngx_http_get_module_srv_conf(r, ngx_http_rewrite_module); rule = scf->rules.elts; for (i = 0; i < scf->rules.nelts; i++) { if (rule[i].msize) { if (!(matches = ngx_palloc(r->pool, rule[i].msize * sizeof(int)))) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } } else { matches = NULL; } rc = ngx_regex_exec(rule[i].regex, &r->uri, matches, rule[i].msize); if (rc == NGX_DECLINED) { if (scf->log) { ngx_log_error(NGX_LOG_NOTICE, r->connection->log, 0, "\"%s\" does not match \"%s\"", rule[i].re_name.data, r->uri.data); } continue; } if (rc < 0) { ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0, ngx_regex_exec_n " failed: %d on \"%s\" using \"%s\"", rc, r->uri.data, rule[i].re_name.data); return NGX_HTTP_INTERNAL_SERVER_ERROR; } if (scf->log) { ngx_log_error(NGX_LOG_NOTICE, r->connection->log, 0, "\"%s\" matches \"%s\"", rule[i].re_name.data, r->uri.data); } if (rule[i].status) { return rule[i].status; } uri.len = rule[i].size; for (n = 1; n < (ngx_uint_t) rc; n++) { uri.len += matches[2 * n + 1] - matches[2 * n]; } if (!(uri.data = ngx_palloc(r->pool, uri.len + 1))) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } p = uri.data; op = rule[i].ops.elts; for (n = 0; n < rule[i].ops.nelts; n++) { if (op[n].op == NGX_HTTP_REWRITE_COPY_SHORT) { len = op[n].len; data = op[n].data; while (len--) { *p++ = (char) (data & 0xff); data >>= 8; } } else if (op[n].op == NGX_HTTP_REWRITE_COPY_LONG) { p = ngx_cpymem(p, (void *) op[n].data, op[n].len); } else { /* NGX_HTTP_REWRITE_COPY_MATCH */ m = 2 * op[n].data; p = ngx_cpymem(p, &r->uri.data[matches[m]], matches[m + 1] - matches[m]); } }
/* callback for new session caching, to be set with SSL_CTX_sess_set_new_cb */ int ngx_http_lua_ssl_sess_store_handler(ngx_ssl_conn_t *ssl_conn, ngx_ssl_session_t *sess) { lua_State *L; ngx_int_t rc; #if OPENSSL_VERSION_NUMBER >= 0x1010005fL unsigned int len; #endif ngx_connection_t *c, *fc = NULL; ngx_http_request_t *r = NULL; ngx_http_connection_t *hc; ngx_http_lua_ssl_ctx_t *cctx; ngx_http_lua_srv_conf_t *lscf; ngx_http_core_loc_conf_t *clcf; c = ngx_ssl_get_connection(ssl_conn); dd("c = %p", c); cctx = ngx_http_lua_ssl_get_ctx(c->ssl->connection); dd("ssl sess_store handler, sess_store-ctx=%p", cctx); hc = c->data; fc = ngx_http_lua_create_fake_connection(NULL); if (fc == NULL) { goto failed; } fc->log->handler = ngx_http_lua_log_ssl_sess_store_error; fc->log->data = fc; fc->addr_text = c->addr_text; fc->listening = c->listening; r = ngx_http_lua_create_fake_request(fc); if (r == NULL) { goto failed; } r->main_conf = hc->conf_ctx->main_conf; r->srv_conf = hc->conf_ctx->srv_conf; r->loc_conf = hc->conf_ctx->loc_conf; fc->log->file = c->log->file; fc->log->log_level = c->log->log_level; fc->ssl = c->ssl; clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); #if defined(nginx_version) && nginx_version >= 1003014 # if nginx_version >= 1009000 ngx_set_connection_log(fc, clcf->error_log); # else ngx_http_set_connection_log(fc, clcf->error_log); # endif #else fc->log->file = clcf->error_log->file; if (!(fc->log->log_level & NGX_LOG_DEBUG_CONNECTION)) { fc->log->log_level = clcf->error_log->log_level; } #endif if (cctx == NULL) { cctx = ngx_pcalloc(c->pool, sizeof(ngx_http_lua_ssl_ctx_t)); if (cctx == NULL) { goto failed; /* error */ } } cctx->connection = c; cctx->request = r; cctx->session = sess; #if OPENSSL_VERSION_NUMBER < 0x1010005fL cctx->session_id.data = sess->session_id; cctx->session_id.len = sess->session_id_length; #else cctx->session_id.data = (u_char *)SSL_SESSION_get_id(sess, &len); cctx->session_id.len = len; #endif cctx->done = 0; dd("setting cctx"); if (SSL_set_ex_data(c->ssl->connection, ngx_http_lua_ssl_ctx_index, cctx) == 0) { ngx_ssl_error(NGX_LOG_ALERT, c->log, 0, "SSL_set_ex_data() failed"); goto failed; } lscf = ngx_http_get_module_srv_conf(r, ngx_http_lua_module); /* TODO honor lua_code_cache off */ L = ngx_http_lua_get_lua_vm(r, NULL); c->log->action = "storing SSL session by lua"; rc = lscf->srv.ssl_sess_store_handler(r, lscf, L); if (rc >= NGX_OK || rc == NGX_ERROR) { cctx->done = 1; ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, "ssl_session_store_by_lua*: handler return value: %i, " "sess new cb exit code: %d", rc, cctx->exit_code); c->log->action = "SSL handshaking"; /* Return value is a flag indicating whether the passed-in session * has been freed by this callback; always return 0 so OpenSSL will * free the session. Nginx's own session caching logic has the same * practice. */ return 0; } /* impossible to reach here */ ngx_http_lua_assert(0); failed: if (r && r->pool) { ngx_http_lua_free_fake_request(r); } if (fc) { ngx_http_lua_close_fake_connection(fc); } return 0; }
static ngx_int_t ngx_http_v2_header_filter(ngx_http_request_t *r) { u_char status, *pos, *start, *p; size_t 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; struct sockaddr_in *sin; #if (NGX_HAVE_INET6) struct sockaddr_in6 *sin6; #endif u_char addr[NGX_SOCKADDR_STRLEN]; 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 ? ngx_http_v2_literal_size(TENGINE_VER) : ngx_http_v2_literal_size("tengine"); } 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; } } switch (fc->local_sockaddr->sa_family) { #if (NGX_HAVE_INET6) case AF_INET6: sin6 = (struct sockaddr_in6 *) fc->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 *) fc->local_sockaddr; port = ntohs(sin->sin_port); break; } 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; } #if (NGX_HTTP_GZIP) if (r->gzip_vary) { if (clcf->gzip_vary) { len += 1 + ngx_http_v2_literal_size("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, r->connection->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, r->connection->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; } pos = ngx_palloc(r->pool, len); if (pos == NULL) { return NGX_ERROR; } start = pos; 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) { *pos++ = ngx_http_v2_inc_indexed(NGX_HTTP_V2_SERVER_INDEX); if (clcf->server_tokens) { *pos++ = NGX_HTTP_V2_ENCODE_RAW | (sizeof(TENGINE_VER) - 1); pos = ngx_cpymem(pos, TENGINE_VER, sizeof(TENGINE_VER) - 1); } else { *pos++ = NGX_HTTP_V2_ENCODE_RAW | (sizeof("nginx") - 1); pos = ngx_cpymem(pos, "nginx", sizeof("nginx") - 1); } } if (r->headers_out.date == NULL) { *pos++ = ngx_http_v2_inc_indexed(NGX_HTTP_V2_DATE_INDEX); *pos++ = (u_char) ngx_cached_http_time.len; pos = ngx_cpymem(pos, ngx_cached_http_time.data, ngx_cached_http_time.len); } 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) { *pos = NGX_HTTP_V2_ENCODE_RAW; pos = ngx_http_v2_write_int(pos, ngx_http_v2_prefix(7), r->headers_out.content_type.len + sizeof("; charset=") - 1 + r->headers_out.charset.len); p = pos; pos = ngx_cpymem(pos, r->headers_out.content_type.data, r->headers_out.content_type.len); pos = ngx_cpymem(pos, "; charset=", sizeof("; charset=") - 1); pos = ngx_cpymem(pos, 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 = pos - p; r->headers_out.content_type.data = p; } else { *pos = NGX_HTTP_V2_ENCODE_RAW; pos = ngx_http_v2_write_int(pos, ngx_http_v2_prefix(7), r->headers_out.content_type.len); pos = ngx_cpymem(pos, r->headers_out.content_type.data, r->headers_out.content_type.len); } } if (r->headers_out.content_length == NULL && r->headers_out.content_length_n >= 0) { *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); *pos++ = NGX_HTTP_V2_ENCODE_RAW | (sizeof("Wed, 31 Dec 1986 18:00:00 GMT") - 1); pos = ngx_http_time(pos, r->headers_out.last_modified_time); } if (r->headers_out.location && r->headers_out.location->value.len) { *pos++ = ngx_http_v2_inc_indexed(NGX_HTTP_V2_LOCATION_INDEX); *pos = NGX_HTTP_V2_ENCODE_RAW; pos = ngx_http_v2_write_int(pos, ngx_http_v2_prefix(7), r->headers_out.location->value.len); pos = ngx_cpymem(pos, r->headers_out.location->value.data, r->headers_out.location->value.len); } #if (NGX_HTTP_GZIP) if (r->gzip_vary) { *pos++ = ngx_http_v2_inc_indexed(NGX_HTTP_V2_VARY_INDEX); *pos++ = NGX_HTTP_V2_ENCODE_RAW | (sizeof("Accept-Encoding") - 1); pos = ngx_cpymem(pos, "Accept-Encoding", sizeof("Accept-Encoding") - 1); } #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; } *pos++ = 0; *pos = NGX_HTTP_V2_ENCODE_RAW; pos = ngx_http_v2_write_int(pos, ngx_http_v2_prefix(7), header[i].key.len); ngx_strlow(pos, header[i].key.data, header[i].key.len); pos += header[i].key.len; *pos = NGX_HTTP_V2_ENCODE_RAW; pos = ngx_http_v2_write_int(pos, ngx_http_v2_prefix(7), header[i].value.len); pos = ngx_cpymem(pos, header[i].value.data, header[i].value.len); } 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_header_filter(ngx_http_request_t *r) { u_char *p; size_t len; ngx_str_t host; ngx_buf_t *b; ngx_uint_t status, i; ngx_chain_t out; ngx_list_part_t *part; ngx_table_elt_t *header; ngx_http_core_loc_conf_t *clcf; ngx_http_core_srv_conf_t *cscf; /* AF_INET only */ u_char addr[INET_ADDRSTRLEN]; r->header_sent = 1; if (r != r->main) { return NGX_OK; } if (r->http_version < NGX_HTTP_VERSION_10) { return NGX_OK; } if (r->method == NGX_HTTP_HEAD) { r->header_only = 1; } if (r->headers_out.last_modified_time != -1) { if (r->headers_out.status != NGX_HTTP_OK && r->headers_out.status != NGX_HTTP_PARTIAL_CONTENT && r->headers_out.status != NGX_HTTP_NOT_MODIFIED) { r->headers_out.last_modified_time = -1; r->headers_out.last_modified = NULL; } } len = sizeof("HTTP/1.x ") - 1 + sizeof(CRLF) - 1 /* the end of the header */ + sizeof(CRLF) - 1; /* status line */ if (r->headers_out.status_line.len) { len += r->headers_out.status_line.len; #if (NGX_SUPPRESS_WARN) status = NGX_INVALID_ARRAY_INDEX; #endif } else { if (r->headers_out.status < NGX_HTTP_MOVED_PERMANENTLY) { /* 2XX */ status = r->headers_out.status - NGX_HTTP_OK; if (r->headers_out.status == NGX_HTTP_NO_CONTENT) { r->header_only = 1; r->headers_out.content_type.len = 0; r->headers_out.content_type.data = NULL; r->headers_out.last_modified_time = -1; r->headers_out.last_modified = NULL; r->headers_out.content_length = NULL; r->headers_out.content_length_n = -1; } } else if (r->headers_out.status < NGX_HTTP_BAD_REQUEST) { /* 3XX */ status = r->headers_out.status - NGX_HTTP_MOVED_PERMANENTLY + NGX_HTTP_LEVEL_200; if (r->headers_out.status == NGX_HTTP_NOT_MODIFIED) { r->header_only = 1; } } else if (r->headers_out.status < NGX_HTTP_INTERNAL_SERVER_ERROR) { /* 4XX */ status = r->headers_out.status - NGX_HTTP_BAD_REQUEST + NGX_HTTP_LEVEL_200 + NGX_HTTP_LEVEL_300; } else { /* 5XX */ status = r->headers_out.status - NGX_HTTP_INTERNAL_SERVER_ERROR + NGX_HTTP_LEVEL_200 + NGX_HTTP_LEVEL_300 + NGX_HTTP_LEVEL_400; } len += ngx_http_status_lines[status].len; } clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); if (r->headers_out.server == NULL) { len += clcf->server_tokens ? sizeof(ngx_http_server_full_string) - 1: sizeof(ngx_http_server_string) - 1; } if (r->headers_out.date == NULL) { len += sizeof("Date: Mon, 28 Sep 1970 06:00:00 GMT" CRLF) - 1; } if (r->headers_out.content_type.len) { len += sizeof("Content-Type: ") - 1 + r->headers_out.content_type.len + 2; 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 += sizeof("Content-Length: ") - 1 + NGX_OFF_T_LEN + 2; } if (r->headers_out.last_modified == NULL && r->headers_out.last_modified_time != -1) { len += sizeof("Last-Modified: Mon, 28 Sep 1970 06:00:00 GMT" CRLF) - 1; } 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.data = addr; if (ngx_http_server_addr(r, &host) != NGX_OK) { return NGX_ERROR; } } #if (NGX_HTTP_SSL) if (r->connection->ssl) { len += sizeof("Location: https://") - 1 + host.len + r->headers_out.location->value.len + 2; if (clcf->port_in_redirect && r->port != 443) { len += r->port_text->len; } } else #endif { len += sizeof("Location: http://") - 1 + host.len + r->headers_out.location->value.len + 2; if (clcf->port_in_redirect && r->port != 80) { len += r->port_text->len; } } } else { host.len = 0; host.data = NULL; } if (r->chunked) { len += sizeof("Transfer-Encoding: chunked" CRLF) - 1; } if (r->keepalive) { len += sizeof("Connection: keep-alive" CRLF) - 1; /* * MSIE and Opera ignore the "Keep-Alive: timeout=<N>" header. * MSIE keeps the connection alive for about 60-65 seconds. * Opera keeps the connection alive very long. * Mozilla keeps the connection alive for N plus about 1-10 seconds. * Konqueror keeps the connection alive for about N seconds. */ if (clcf->keepalive_header) { len += sizeof("Keep-Alive: timeout=") - 1 + NGX_TIME_T_LEN + 2; } } else { len += sizeof("Connection: closed" CRLF) - 1; } #if (NGX_HTTP_GZIP) if (r->gzip && clcf->gzip_vary) { len += sizeof("Vary: Accept-Encoding" CRLF) - 1; } #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; } len += header[i].key.len + sizeof(": ") - 1 + header[i].value.len + sizeof(CRLF) - 1; } b = ngx_create_temp_buf(r->pool, len); if (b == NULL) { return NGX_ERROR; } /* "HTTP/1.x " */ b->last = ngx_cpymem(b->last, "HTTP/1.1 ", sizeof("HTTP/1.x ") - 1); /* status line */ if (r->headers_out.status_line.len) { b->last = ngx_copy(b->last, r->headers_out.status_line.data, r->headers_out.status_line.len); } else { b->last = ngx_copy(b->last, ngx_http_status_lines[status].data, ngx_http_status_lines[status].len); } *b->last++ = CR; *b->last++ = LF; if (r->headers_out.server == NULL) { if (clcf->server_tokens) { p = (u_char *) ngx_http_server_full_string; len = sizeof(ngx_http_server_full_string) - 1; } else { p = (u_char *) ngx_http_server_string; len = sizeof(ngx_http_server_string) - 1; } b->last = ngx_cpymem(b->last, p, len); } if (r->headers_out.date == NULL) { b->last = ngx_cpymem(b->last, "Date: ", sizeof("Date: ") - 1); b->last = ngx_cpymem(b->last, ngx_cached_http_time.data, ngx_cached_http_time.len); *b->last++ = CR; *b->last++ = LF; } if (r->headers_out.content_type.len) { b->last = ngx_cpymem(b->last, "Content-Type: ", sizeof("Content-Type: ") - 1); p = b->last; b->last = ngx_copy(b->last, 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) { b->last = ngx_cpymem(b->last, "; charset=", sizeof("; charset=") - 1); b->last = ngx_copy(b->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 = b->last - p; r->headers_out.content_type.data = p; } *b->last++ = CR; *b->last++ = LF; } if (r->headers_out.content_length == NULL && r->headers_out.content_length_n >= 0) { b->last = ngx_sprintf(b->last, "Content-Length: %O" CRLF, r->headers_out.content_length_n); } if (r->headers_out.last_modified == NULL && r->headers_out.last_modified_time != -1) { b->last = ngx_cpymem(b->last, "Last-Modified: ", sizeof("Last-Modified: ") - 1); b->last = ngx_http_time(b->last, r->headers_out.last_modified_time); *b->last++ = CR; *b->last++ = LF; } if (host.data) { p = b->last + sizeof("Location: ") - 1; b->last = ngx_cpymem(b->last, "Location: http", sizeof("Location: http") - 1); #if (NGX_HTTP_SSL) if (r->connection->ssl) { *b->last++ ='s'; } #endif *b->last++ = ':'; *b->last++ = '/'; *b->last++ = '/'; b->last = ngx_copy(b->last, host.data, host.len); if (clcf->port_in_redirect) { #if (NGX_HTTP_SSL) if (r->connection->ssl) { if (r->port != 443) { b->last = ngx_copy(b->last, r->port_text->data, r->port_text->len); } } else #endif { if (r->port != 80) { b->last = ngx_copy(b->last, r->port_text->data, r->port_text->len); } } } b->last = ngx_copy(b->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 = b->last - p; r->headers_out.location->value.data = p; r->headers_out.location->key.len = sizeof("Location: ") - 1; r->headers_out.location->key.data = (u_char *) "Location: "; *b->last++ = CR; *b->last++ = LF; } if (r->chunked) { b->last = ngx_cpymem(b->last, "Transfer-Encoding: chunked" CRLF, sizeof("Transfer-Encoding: chunked" CRLF) - 1); } if (r->keepalive) { b->last = ngx_cpymem(b->last, "Connection: keep-alive" CRLF, sizeof("Connection: keep-alive" CRLF) - 1); if (clcf->keepalive_header) { b->last = ngx_sprintf(b->last, "Keep-Alive: timeout=%T" CRLF, clcf->keepalive_header); } } else { b->last = ngx_cpymem(b->last, "Connection: close" CRLF, sizeof("Connection: close" CRLF) - 1); } #if (NGX_HTTP_GZIP) if (r->gzip && clcf->gzip_vary) { b->last = ngx_cpymem(b->last, "Vary: Accept-Encoding" CRLF, sizeof("Vary: Accept-Encoding" CRLF) - 1); } #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; } b->last = ngx_copy(b->last, header[i].key.data, header[i].key.len); *b->last++ = ':'; *b->last++ = ' '; b->last = ngx_copy(b->last, header[i].value.data, header[i].value.len); *b->last++ = CR; *b->last++ = LF; } ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "%*s\n", (size_t) (b->last - b->pos), b->pos); /* the end of HTTP header */ *b->last++ = CR; *b->last++ = LF; r->header_size = b->last - b->pos; if (r->header_only) { b->last_buf = 1; } out.buf = b; out.next = NULL; return ngx_http_write_filter(r, &out); }
static ngx_http_spdy_stream_t * ngx_http_spdy_create_stream(ngx_http_spdy_connection_t *sc, ngx_uint_t id, ngx_uint_t priority) { ngx_log_t *log; ngx_uint_t index; ngx_event_t *rev, *wev; ngx_connection_t *fc; ngx_http_log_ctx_t *ctx; ngx_http_request_t *r; ngx_http_spdy_stream_t *stream; ngx_http_core_srv_conf_t *cscf; ngx_http_spdy_srv_conf_t *sscf; fc = sc->free_fake_connections; if (fc) { sc->free_fake_connections = fc->data; rev = fc->read; wev = fc->write; log = fc->log; ctx = log->data; } else { fc = ngx_palloc(sc->pool, sizeof(ngx_connection_t)); if (fc == NULL) { return NULL; } rev = ngx_palloc(sc->pool, sizeof(ngx_event_t)); if (rev == NULL) { return NULL; } wev = ngx_palloc(sc->pool, sizeof(ngx_event_t)); if (wev == NULL) { return NULL; } log = ngx_palloc(sc->pool, sizeof(ngx_log_t)); if (log == NULL) { return NULL; } ctx = ngx_palloc(sc->pool, sizeof(ngx_http_log_ctx_t)); if (ctx == NULL) { return NULL; } ctx->connection = fc; ctx->request = NULL; } ngx_memcpy(log, sc->connection->log, sizeof(ngx_log_t)); log->data = ctx; ngx_memzero(rev, sizeof(ngx_event_t)); rev->data = fc; rev->ready = 1; rev->handler = ngx_http_empty_handler; rev->log = log; ngx_memcpy(wev, rev, sizeof(ngx_event_t)); wev->write = 1; ngx_memcpy(fc, sc->connection, sizeof(ngx_connection_t)); fc->data = sc->http_connection; fc->read = rev; fc->write = wev; fc->sent = 0; fc->log = log; fc->buffered = 0; fc->sndlowat = 1; fc->tcp_nodelay = NGX_TCP_NODELAY_DISABLED; r = ngx_http_create_request(fc); if (r == NULL) { return NULL; } r->valid_location = 1; fc->data = r; sc->connection->requests++; cscf = ngx_http_get_module_srv_conf(r, ngx_http_core_module); r->header_in = ngx_create_temp_buf(r->pool, cscf->client_header_buffer_size); if (r->header_in == NULL) { ngx_http_free_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); return NULL; } r->headers_in.connection_type = NGX_HTTP_CONNECTION_CLOSE; stream = ngx_pcalloc(r->pool, sizeof(ngx_http_spdy_stream_t)); if (stream == NULL) { ngx_http_free_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); return NULL; } r->spdy_stream = stream; stream->id = id; stream->request = r; stream->connection = sc; stream->priority = priority; sscf = ngx_http_get_module_srv_conf(r, ngx_http_spdy_module); index = ngx_http_spdy_stream_index(sscf, id); stream->index = sc->streams_index[index]; sc->streams_index[index] = stream; sc->processing++; return stream; }
static ngx_int_t ngx_http_small_light_header_filter(ngx_http_request_t *r) { ngx_http_small_light_conf_t *srv_conf; ngx_http_small_light_conf_t *loc_conf; ngx_http_small_light_ctx_t *ctx; ngx_hash_init_t hash; ngx_str_t define_pattern; if (r->headers_out.status == NGX_HTTP_NOT_MODIFIED) { return ngx_http_next_header_filter(r); } srv_conf = ngx_http_get_module_srv_conf(r, ngx_http_small_light_module); loc_conf = ngx_http_get_module_loc_conf(r, ngx_http_small_light_module); if (!loc_conf->enable) { return ngx_http_next_header_filter(r); } if(ngx_http_small_light_parse_define_pattern(r, &r->unparsed_uri, &define_pattern) != NGX_OK) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "%s:%d", __FUNCTION__, __LINE__); return ngx_http_next_header_filter(r); } ctx = ngx_http_get_module_ctx(r, ngx_http_small_light_module); if (ctx) { ngx_http_set_ctx(r, NULL, ngx_http_small_light_module); return ngx_http_next_header_filter(r); } if ((ctx = ngx_pcalloc(r->pool, sizeof(*ctx))) == NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "%s:%d", __FUNCTION__, __LINE__); return NGX_ERROR; } ngx_memzero(ctx, sizeof(ngx_http_small_light_ctx_t)); ctx->params.keys.pool = r->pool; ctx->params.temp_pool = r->pool; if (ngx_hash_keys_array_init(&ctx->params, NGX_HASH_SMALL) != NGX_OK) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "%s:%d", __FUNCTION__, __LINE__); return NGX_ERROR; } if (ngx_http_small_light_init_params(r, ctx, &define_pattern, srv_conf) != NGX_OK) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "%s:%d", __FUNCTION__, __LINE__); return NGX_ERROR; } hash.hash = &ctx->hash; hash.key = ngx_hash_key_lc; hash.max_size = 128; hash.bucket_size = ngx_cacheline_size; hash.name = "small_light_init_params"; hash.pool = ctx->params.keys.pool; hash.temp_pool = NULL; if (ngx_hash_init(&hash, ctx->params.keys.elts, ctx->params.keys.nelts) != NGX_OK) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "%s:%d", __FUNCTION__, __LINE__); return NGX_ERROR; } ctx->inf = r->headers_out.content_type.data; ctx->content_length = r->headers_out.content_length_n; ngx_http_set_ctx(r, ctx, ngx_http_small_light_module); if (r->headers_out.refresh) { r->headers_out.refresh->hash = 0; } r->main_filter_need_in_memory = 1; r->allow_ranges = 0; return NGX_OK; }
static ngx_int_t ngx_http_small_light_body_filter(ngx_http_request_t *r, ngx_chain_t *in) { ngx_http_small_light_conf_t *srv_conf; ngx_http_small_light_conf_t *loc_conf; ngx_http_small_light_ctx_t *ctx; ngx_chain_t out; ngx_int_t rc; if (in == NULL) { return ngx_http_next_body_filter(r, in); } srv_conf = ngx_http_get_module_srv_conf(r, ngx_http_small_light_module); loc_conf = ngx_http_get_module_loc_conf(r, ngx_http_small_light_module); if (!loc_conf->enable) { return ngx_http_next_body_filter(r, in); } ctx = ngx_http_get_module_ctx(r, ngx_http_small_light_module); if (ctx == NULL) { return ngx_http_next_body_filter(r, in); } if (ctx->ictx == NULL) { ctx->ictx = ngx_pcalloc(r->pool, sizeof(ngx_http_small_light_imagemagick_ctx_t)); if (ctx->ictx == NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "%s:%d", __FUNCTION__, __LINE__); return NGX_ERROR; } } if((rc = ngx_http_small_light_image_read(r, in, ctx)) != NGX_OK) { if (rc == NGX_AGAIN) { return NGX_OK; } ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "%s:%d", __FUNCTION__, __LINE__); return NGX_ERROR; } r->connection->buffered &= ~NGX_HTTP_SMALL_LIGHT_IMAGE_BUFFERED; ngx_http_small_light_imagemagick_init(ctx); rc = ngx_http_small_light_imagemagick_process(r, ctx); ngx_http_small_light_imagemagick_term(ctx); if (rc != NGX_OK) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "%s:%d", __FUNCTION__, __LINE__); return NGX_ERROR; } ngx_buf_t *b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t)); if (b == NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "%s:%d", __FUNCTION__, __LINE__); return NGX_ERROR; } b->pos = ctx->content; b->last = ctx->content + ctx->content_length; b->memory = 1; b->last_buf = 1; out.buf = b; out.next = NULL; r->headers_out.content_length_n = b->last - b->pos; if (r->headers_out.content_length) { r->headers_out.content_length->hash = 0; } r->headers_out.content_length = NULL; ngx_pool_cleanup_t *cln; cln = ngx_pool_cleanup_add(r->pool, 0); if (cln == NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "%s:%d", __FUNCTION__, __LINE__); return NGX_ERROR; } cln->handler = ngx_http_small_light_cleanup; cln->data = ctx; return ngx_http_small_light_finish(r, &out); }
static ngx_int_t ngx_http_header_filter(ngx_http_request_t *r) { u_char *p; size_t len; ngx_str_t host, *status_line; ngx_buf_t *b; ngx_uint_t status, i, port; ngx_chain_t out; ngx_list_part_t *part; ngx_table_elt_t *header; ngx_connection_t *c; ngx_http_core_loc_conf_t *clcf; ngx_http_core_srv_conf_t *cscf; struct sockaddr_in *sin; #if (NGX_HAVE_INET6) struct sockaddr_in6 *sin6; #endif u_char addr[NGX_SOCKADDR_STRLEN]; if (r->header_sent) { return NGX_OK; } r->header_sent = 1; if (r != r->main) { return NGX_OK; } if (r->http_version < NGX_HTTP_VERSION_10) { return NGX_OK; } if (r->method == NGX_HTTP_HEAD) { r->header_only = 1; } if (r->headers_out.last_modified_time != -1) { if (r->headers_out.status != NGX_HTTP_OK && r->headers_out.status != NGX_HTTP_PARTIAL_CONTENT && r->headers_out.status != NGX_HTTP_NOT_MODIFIED) { r->headers_out.last_modified_time = -1; r->headers_out.last_modified = NULL; } } len = sizeof("HTTP/1.x ") - 1 + sizeof(CRLF) - 1 /* the end of the header */ + sizeof(CRLF) - 1; /* status line */ if (r->headers_out.status_line.len) { len += r->headers_out.status_line.len; status_line = &r->headers_out.status_line; #if (NGX_SUPPRESS_WARN) status = 0; #endif } else { status = r->headers_out.status; if (status >= NGX_HTTP_OK && status < NGX_HTTP_LAST_2XX) { /* 2XX */ if (status == NGX_HTTP_NO_CONTENT) { r->header_only = 1; ngx_str_null(&r->headers_out.content_type); r->headers_out.last_modified_time = -1; r->headers_out.last_modified = NULL; r->headers_out.content_length = NULL; r->headers_out.content_length_n = -1; } status -= NGX_HTTP_OK; status_line = &ngx_http_status_lines[status]; len += ngx_http_status_lines[status].len; } else if (status >= NGX_HTTP_MOVED_PERMANENTLY && status < NGX_HTTP_LAST_3XX) { /* 3XX */ if (status == NGX_HTTP_NOT_MODIFIED) { r->header_only = 1; } status = status - NGX_HTTP_MOVED_PERMANENTLY + NGX_HTTP_OFF_3XX; status_line = &ngx_http_status_lines[status]; len += ngx_http_status_lines[status].len; } else if (status >= NGX_HTTP_BAD_REQUEST && status < NGX_HTTP_LAST_4XX) { /* 4XX */ status = status - NGX_HTTP_BAD_REQUEST + NGX_HTTP_OFF_4XX; status_line = &ngx_http_status_lines[status]; len += ngx_http_status_lines[status].len; } else if (status >= NGX_HTTP_INTERNAL_SERVER_ERROR && status < NGX_HTTP_LAST_5XX) { /* 5XX */ status = status - NGX_HTTP_INTERNAL_SERVER_ERROR + NGX_HTTP_OFF_5XX; status_line = &ngx_http_status_lines[status]; len += ngx_http_status_lines[status].len; } else { len += NGX_INT_T_LEN + 1 /* SP */; status_line = NULL; } if (status_line && status_line->len == 0) { status = r->headers_out.status; len += NGX_INT_T_LEN + 1 /* SP */; status_line = NULL; } } clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); if (r->headers_out.server == NULL) { len += clcf->server_tokens ? sizeof(ngx_http_server_full_string) - 1: sizeof(ngx_http_server_string) - 1; } if (r->headers_out.date == NULL) { len += sizeof("Date: Mon, 28 Sep 1970 06:00:00 GMT" CRLF) - 1; } if (r->headers_out.content_type.len) { len += sizeof("Content-Type: ") - 1 + r->headers_out.content_type.len + 2; 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 += sizeof("Content-Length: ") - 1 + NGX_OFF_T_LEN + 2; } if (r->headers_out.last_modified == NULL && r->headers_out.last_modified_time != -1) { len += sizeof("Last-Modified: Mon, 28 Sep 1970 06:00:00 GMT" CRLF) - 1; } c = r->connection; 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 += sizeof("Location: https://") - 1 + host.len + r->headers_out.location->value.len + 2; 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; } if (r->chunked) { len += sizeof("Transfer-Encoding: chunked" CRLF) - 1; } if (r->headers_out.status == NGX_HTTP_SWITCHING_PROTOCOLS) { len += sizeof("Connection: upgrade" CRLF) - 1; } else if (r->keepalive) { len += sizeof("Connection: keep-alive" CRLF) - 1; /* * MSIE and Opera ignore the "Keep-Alive: timeout=<N>" header. * MSIE keeps the connection alive for about 60-65 seconds. * Opera keeps the connection alive very long. * Mozilla keeps the connection alive for N plus about 1-10 seconds. * Konqueror keeps the connection alive for about N seconds. */ if (clcf->keepalive_header) { len += sizeof("Keep-Alive: timeout=") - 1 + NGX_TIME_T_LEN + 2; } } else { len += sizeof("Connection: close" CRLF) - 1; } #if (NGX_HTTP_GZIP) if (r->gzip_vary) { if (clcf->gzip_vary) { len += sizeof("Vary: Accept-Encoding" CRLF) - 1; } 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; } len += header[i].key.len + sizeof(": ") - 1 + header[i].value.len + sizeof(CRLF) - 1; } b = ngx_create_temp_buf(r->pool, len); if (b == NULL) { return NGX_ERROR; } /* "HTTP/1.x " */ b->last = ngx_cpymem(b->last, "HTTP/1.1 ", sizeof("HTTP/1.x ") - 1); /* status line */ if (status_line) { b->last = ngx_copy(b->last, status_line->data, status_line->len); } else { b->last = ngx_sprintf(b->last, "%03ui ", status); } *b->last++ = CR; *b->last++ = LF; if (r->headers_out.server == NULL) { if (clcf->server_tokens) { p = (u_char *) ngx_http_server_full_string; len = sizeof(ngx_http_server_full_string) - 1; } else { p = (u_char *) ngx_http_server_string; len = sizeof(ngx_http_server_string) - 1; } b->last = ngx_cpymem(b->last, p, len); } if (r->headers_out.date == NULL) { b->last = ngx_cpymem(b->last, "Date: ", sizeof("Date: ") - 1); b->last = ngx_cpymem(b->last, ngx_cached_http_time.data, ngx_cached_http_time.len); *b->last++ = CR; *b->last++ = LF; } if (r->headers_out.content_type.len) { b->last = ngx_cpymem(b->last, "Content-Type: ", sizeof("Content-Type: ") - 1); p = b->last; b->last = ngx_copy(b->last, 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) { b->last = ngx_cpymem(b->last, "; charset=", sizeof("; charset=") - 1); b->last = ngx_copy(b->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 = b->last - p; r->headers_out.content_type.data = p; } *b->last++ = CR; *b->last++ = LF; } if (r->headers_out.content_length == NULL && r->headers_out.content_length_n >= 0) { b->last = ngx_sprintf(b->last, "Content-Length: %O" CRLF, r->headers_out.content_length_n); } if (r->headers_out.last_modified == NULL && r->headers_out.last_modified_time != -1) { b->last = ngx_cpymem(b->last, "Last-Modified: ", sizeof("Last-Modified: ") - 1); b->last = ngx_http_time(b->last, r->headers_out.last_modified_time); *b->last++ = CR; *b->last++ = LF; } if (host.data) { p = b->last + sizeof("Location: ") - 1; b->last = ngx_cpymem(b->last, "Location: http", sizeof("Location: http") - 1); #if (NGX_HTTP_SSL) if (c->ssl) { *b->last++ ='s'; } #endif *b->last++ = ':'; *b->last++ = '/'; *b->last++ = '/'; b->last = ngx_copy(b->last, host.data, host.len); if (port) { b->last = ngx_sprintf(b->last, ":%ui", port); } b->last = ngx_copy(b->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 = b->last - p; r->headers_out.location->value.data = p; ngx_str_set(&r->headers_out.location->key, "Location"); *b->last++ = CR; *b->last++ = LF; } if (r->chunked) { b->last = ngx_cpymem(b->last, "Transfer-Encoding: chunked" CRLF, sizeof("Transfer-Encoding: chunked" CRLF) - 1); } if (r->headers_out.status == NGX_HTTP_SWITCHING_PROTOCOLS) { b->last = ngx_cpymem(b->last, "Connection: upgrade" CRLF, sizeof("Connection: upgrade" CRLF) - 1); } else if (r->keepalive) { b->last = ngx_cpymem(b->last, "Connection: keep-alive" CRLF, sizeof("Connection: keep-alive" CRLF) - 1); if (clcf->keepalive_header) { b->last = ngx_sprintf(b->last, "Keep-Alive: timeout=%T" CRLF, clcf->keepalive_header); } } else { b->last = ngx_cpymem(b->last, "Connection: close" CRLF, sizeof("Connection: close" CRLF) - 1); } #if (NGX_HTTP_GZIP) if (r->gzip_vary) { b->last = ngx_cpymem(b->last, "Vary: Accept-Encoding" CRLF, sizeof("Vary: Accept-Encoding" CRLF) - 1); } #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; } b->last = ngx_copy(b->last, header[i].key.data, header[i].key.len); *b->last++ = ':'; *b->last++ = ' '; b->last = ngx_copy(b->last, header[i].value.data, header[i].value.len); *b->last++ = CR; *b->last++ = LF; } ngx_log_debug2(NGX_LOG_DEBUG_HTTP, c->log, 0, "%*s", (size_t) (b->last - b->pos), b->pos); /* the end of HTTP header */ *b->last++ = CR; *b->last++ = LF; r->header_size = b->last - b->pos; if (r->header_only) { b->last_buf = 1; } out.buf = b; out.next = NULL; return ngx_http_write_filter(r, &out); }
static ngx_int_t ngx_http_set_virtual_server(ngx_http_request_t *r, ngx_str_t *host) { ngx_int_t rc; ngx_http_connection_t *hc; ngx_http_core_loc_conf_t *clcf; ngx_http_core_srv_conf_t *cscf = NULL; hc = r->http_connection; #if (NGX_HTTP_SSL && defined SSL_CTRL_SET_TLSEXT_HOSTNAME) if (hc->ssl_servername) { if (hc->ssl_servername->len == host->len && ngx_strncmp(hc->ssl_servername->data, host->data, host->len) == 0) { #if (NGX_PCRE) if (hc->ssl_servername_regex && ngx_http_regex_exec(r, hc->ssl_servername_regex, hc->ssl_servername) != NGX_OK) { ngx_tcp2http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); return NGX_ERROR; } #endif return NGX_OK; } } #endif rc = ngx_http_find_virtual_server(r->connection, hc->addr_conf->virtual_names, host, r, &cscf); if (rc == NGX_ERROR) { ngx_tcp2http_close_request(r, NGX_HTTP_INTERNAL_SERVER_ERROR); return NGX_ERROR; } #if (NGX_HTTP_SSL && defined SSL_CTRL_SET_TLSEXT_HOSTNAME) if (hc->ssl_servername) { ngx_http_ssl_srv_conf_t *sscf; if (rc == NGX_DECLINED) { cscf = hc->addr_conf->default_server; rc = NGX_OK; } sscf = ngx_http_get_module_srv_conf(cscf->ctx, ngx_http_ssl_module); if (sscf->verify) { ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, "client attempted to request the server name " "different from that one was negotiated"); ngx_http_finalize_request(r, NGX_HTTP_BAD_REQUEST); return NGX_ERROR; } } #endif if (rc == NGX_DECLINED) { return NGX_OK; } r->srv_conf = cscf->ctx->srv_conf; r->loc_conf = cscf->ctx->loc_conf; clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); ngx_http_set_connection_log(r->connection, clcf->error_log); return NGX_OK; }
static ngx_int_t create_request(ngx_http_request_t *r) { u_char ch; u_char buf[sizeof("4294967296")]; size_t len, size, key_len, val_len, content_length; const u_char *app_type_string; size_t app_type_string_len; u_char framework_spawner_idle_time_string[12]; u_char app_spawner_idle_time_string[12]; u_char *end; ngx_uint_t i, n; ngx_buf_t *b; ngx_chain_t *cl, *body; ngx_list_part_t *part; ngx_table_elt_t *header; ngx_http_script_code_pt code; ngx_http_script_engine_t e, le; passenger_loc_conf_t *slcf; passenger_main_conf_t *main_conf; passenger_context_t *context; ngx_http_script_len_code_pt lcode; #if (NGX_HTTP_SSL) ngx_http_ssl_srv_conf_t *ssl_conf; #endif slcf = ngx_http_get_module_loc_conf(r, ngx_http_passenger_module); main_conf = &passenger_main_conf; context = ngx_http_get_module_ctx(r, ngx_http_passenger_module); if (context == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } switch (context->app_type) { case AP_RAILS: app_type_string = (const u_char *) "rails"; app_type_string_len = sizeof("rails"); break; case AP_RACK: app_type_string = (const u_char *) "rack"; app_type_string_len = sizeof("rack"); break; case AP_WSGI: app_type_string = (const u_char *) "wsgi"; app_type_string_len = sizeof("wsgi"); break; default: app_type_string = (const u_char *) "rails"; app_type_string_len = sizeof("rails"); break; } /************************************************** * Determine the request header length. **************************************************/ /* Length of the Content-Length header. */ if (r->headers_in.content_length_n < 0) { content_length = 0; } else { content_length = r->headers_in.content_length_n; } uint_to_str(content_length, buf, sizeof(buf)); /* +1 for trailing null */ len = sizeof("CONTENT_LENGTH") + ngx_strlen(buf) + 1; /* DOCUMENT_ROOT, SCRIPT_NAME and base URI */ len += sizeof("DOCUMENT_ROOT") + context->public_dir.len + 1; if (context->base_uri.len > 0) { len += sizeof("SCRIPT_NAME") + context->base_uri.len + 1; len += sizeof("RAILS_RELATIVE_URL_ROOT") + context->base_uri.len + 1; } else { len += sizeof("SCRIPT_NAME") + sizeof(""); } /* Various other HTTP headers. */ if (r->headers_in.content_type != NULL && r->headers_in.content_type->value.len > 0) { len += sizeof("CONTENT_TYPE") + r->headers_in.content_type->value.len + 1; } #if (NGX_HTTP_SSL) ssl_conf = ngx_http_get_module_srv_conf(r, ngx_http_ssl_module); if (ssl_conf->enable) { len += sizeof("HTTPS") + sizeof("on"); } #endif /* Lengths of Passenger application pool options. */ if (slcf->use_global_queue) { len += sizeof("PASSENGER_USE_GLOBAL_QUEUE") + sizeof("true"); } else { len += sizeof("PASSENGER_USE_GLOBAL_QUEUE") + sizeof("false"); } len += sizeof("PASSENGER_ENVIRONMENT") + slcf->environment.len + 1; len += sizeof("PASSENGER_SPAWN_METHOD") + slcf->spawn_method.len + 1; len += sizeof("PASSENGER_APP_TYPE") + app_type_string_len; end = ngx_snprintf(framework_spawner_idle_time_string, sizeof(framework_spawner_idle_time_string) - 1, "%d", slcf->framework_spawner_idle_time); *end = '\0'; len += sizeof("PASSENGER_FRAMEWORK_SPAWNER_IDLE_TIME") + ngx_strlen(framework_spawner_idle_time_string) + 1; end = ngx_snprintf(app_spawner_idle_time_string, sizeof(app_spawner_idle_time_string) - 1, "%d", slcf->app_spawner_idle_time); *end = '\0'; len += sizeof("PASSENGER_APP_SPAWNER_IDLE_TIME") + ngx_strlen(app_spawner_idle_time_string) + 1; /* Lengths of various CGI variables. */ if (slcf->vars_len) { ngx_memzero(&le, sizeof(ngx_http_script_engine_t)); ngx_http_script_flush_no_cacheable_variables(r, slcf->flushes); le.flushed = 1; le.ip = slcf->vars_len->elts; le.request = r; while (*(uintptr_t *) le.ip) { lcode = *(ngx_http_script_len_code_pt *) le.ip; key_len = lcode(&le); for (val_len = 0; *(uintptr_t *) le.ip; val_len += lcode(&le)) { lcode = *(ngx_http_script_len_code_pt *) le.ip; } le.ip += sizeof(uintptr_t); len += key_len + val_len; } } /* Lengths of HTTP headers. */ if (slcf->upstream.pass_request_headers) { part = &r->headers_in.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; } len += sizeof("HTTP_") - 1 + header[i].key.len + 1 + header[i].value.len + 1; } } /* Trailing dummy header. * * If the last header value is an empty string, then the buffer * will end with "\0\0". For example, if 'SSL_CLIENT_CERT' * is the last header and it has an empty value, then the SCGI header * will end with: * * "SSL_CLIENT_CERT\0\0" * * The data in the buffer will be processed by the AbstractRequestHandler class, * which is implemented in Ruby. But it uses Hash[*data.split("\0")] to * unserialize the data. Unfortunately String#split will not transform * the trailing "\0\0" into an empty string: * * "SSL_CLIENT_CERT\0\0".split("\0") * # => desired result: ["SSL_CLIENT_CERT", ""] * # => actual result: ["SSL_CLIENT_CERT"] * * When that happens, Hash[..] will raise an ArgumentError because * data.split("\0") does not return an array with a length that is a * multiple of 2. * * So here, we add a dummy header to prevent situations like that from * happening. */ len += sizeof("_") + sizeof("_"); /************************************************** * Build the request header data. **************************************************/ size = passenger_helper_server_password.len + /* netstring length + ":" + trailing "," */ /* note: 10 == sizeof("4294967296") - 1 */ len + 10 + 1 + 1; b = ngx_create_temp_buf(r->pool, size); if (b == NULL) { return NGX_ERROR; } cl = ngx_alloc_chain_link(r->pool); if (cl == NULL) { return NGX_ERROR; } cl->buf = b; /* Build SCGI header netstring length part. */ b->last = ngx_copy(b->last, passenger_helper_server_password.data, passenger_helper_server_password.len); b->last = ngx_snprintf(b->last, 10, "%ui", len); *b->last++ = (u_char) ':'; /* Build CONTENT_LENGTH header. This must always be sent, even if 0. */ b->last = ngx_copy(b->last, "CONTENT_LENGTH", sizeof("CONTENT_LENGTH")); b->last = ngx_snprintf(b->last, 10, "%ui", content_length); *b->last++ = (u_char) 0; /* Build DOCUMENT_ROOT, SCRIPT_NAME and base URI. */ b->last = ngx_copy(b->last, "DOCUMENT_ROOT", sizeof("DOCUMENT_ROOT")); b->last = ngx_copy(b->last, context->public_dir.data, context->public_dir.len + 1); if (context->base_uri.len > 0) { b->last = ngx_copy(b->last, "SCRIPT_NAME", sizeof("SCRIPT_NAME")); b->last = ngx_copy(b->last, context->base_uri.data, context->base_uri.len + 1); b->last = ngx_copy(b->last, "RAILS_RELATIVE_URL_ROOT", sizeof("RAILS_RELATIVE_URL_ROOT")); b->last = ngx_copy(b->last, context->base_uri.data, context->base_uri.len + 1); } else { b->last = ngx_copy(b->last, "SCRIPT_NAME", sizeof("SCRIPT_NAME")); b->last = ngx_copy(b->last, "", sizeof("")); } /* Various other HTTP headers. */ if (r->headers_in.content_type != NULL && r->headers_in.content_type->value.len > 0) { b->last = ngx_copy(b->last, "CONTENT_TYPE", sizeof("CONTENT_TYPE")); b->last = ngx_copy(b->last, r->headers_in.content_type->value.data, r->headers_in.content_type->value.len + 1); } #if (NGX_HTTP_SSL) ssl_conf = ngx_http_get_module_srv_conf(r, ngx_http_ssl_module); if (ssl_conf->enable) { b->last = ngx_copy(b->last, "HTTPS", sizeof("HTTPS")); b->last = ngx_copy(b->last, "on", sizeof("on")); } #endif /* Build Passenger application pool option headers. */ b->last = ngx_copy(b->last, "PASSENGER_USE_GLOBAL_QUEUE", sizeof("PASSENGER_USE_GLOBAL_QUEUE")); if (slcf->use_global_queue) { b->last = ngx_copy(b->last, "true", sizeof("true")); } else { b->last = ngx_copy(b->last, "false", sizeof("false")); } b->last = ngx_copy(b->last, "PASSENGER_ENVIRONMENT", sizeof("PASSENGER_ENVIRONMENT")); b->last = ngx_copy(b->last, slcf->environment.data, slcf->environment.len + 1); b->last = ngx_copy(b->last, "PASSENGER_SPAWN_METHOD", sizeof("PASSENGER_SPAWN_METHOD")); b->last = ngx_copy(b->last, slcf->spawn_method.data, slcf->spawn_method.len + 1); b->last = ngx_copy(b->last, "PASSENGER_APP_TYPE", sizeof("PASSENGER_APP_TYPE")); b->last = ngx_copy(b->last, app_type_string, app_type_string_len); b->last = ngx_copy(b->last, "PASSENGER_FRAMEWORK_SPAWNER_IDLE_TIME", sizeof("PASSENGER_FRAMEWORK_SPAWNER_IDLE_TIME")); b->last = ngx_copy(b->last, framework_spawner_idle_time_string, ngx_strlen(framework_spawner_idle_time_string) + 1); b->last = ngx_copy(b->last, "PASSENGER_APP_SPAWNER_IDLE_TIME", sizeof("PASSENGER_APP_SPAWNER_IDLE_TIME")); b->last = ngx_copy(b->last, app_spawner_idle_time_string, ngx_strlen(app_spawner_idle_time_string) + 1); if (slcf->vars_len) { ngx_memzero(&e, sizeof(ngx_http_script_engine_t)); e.ip = slcf->vars->elts; e.pos = b->last; e.request = r; e.flushed = 1; le.ip = slcf->vars_len->elts; while (*(uintptr_t *) le.ip) { lcode = *(ngx_http_script_len_code_pt *) le.ip; (void) lcode(&le); for (val_len = 0; *(uintptr_t *) le.ip; val_len += lcode(&le)) { lcode = *(ngx_http_script_len_code_pt *) le.ip; } le.ip += sizeof(uintptr_t); while (*(uintptr_t *) e.ip) { code = *(ngx_http_script_code_pt *) e.ip; code((ngx_http_script_engine_t *) &e); } e.ip += sizeof(uintptr_t); } b->last = e.pos; } if (slcf->upstream.pass_request_headers) { part = &r->headers_in.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; } b->last = ngx_cpymem(b->last, "HTTP_", sizeof("HTTP_") - 1); for (n = 0; n < header[i].key.len; n++) { ch = header[i].key.data[n]; if (ch >= 'a' && ch <= 'z') { ch &= ~0x20; } else if (ch == '-') { ch = '_'; } *b->last++ = ch; } *b->last++ = (u_char) 0; b->last = ngx_copy(b->last, header[i].value.data, header[i].value.len); *b->last++ = (u_char) 0; } } /* Trailing dummy header. See earlier comment for explanation. */ b->last = ngx_copy(b->last, "_\0_", sizeof("_\0_")); *b->last++ = (u_char) ','; if (slcf->upstream.pass_request_body) { body = r->upstream->request_bufs; r->upstream->request_bufs = cl; while (body) { b = ngx_alloc_buf(r->pool); if (b == NULL) { return NGX_ERROR; } ngx_memcpy(b, body->buf, sizeof(ngx_buf_t)); cl->next = ngx_alloc_chain_link(r->pool); if (cl->next == NULL) { return NGX_ERROR; } cl = cl->next; cl->buf = b; body = body->next; } b->flush = 1; } else { r->upstream->request_bufs = cl; } cl->next = NULL; return NGX_OK; }
static ngx_int_t ngx_http_small_light_header_filter(ngx_http_request_t *r) { ngx_http_small_light_conf_t *srv_conf; ngx_http_small_light_conf_t *loc_conf; ngx_http_small_light_ctx_t *ctx; ngx_hash_init_t hash_init; ngx_str_t define_pattern; char *converter; if (r->headers_out.status == NGX_HTTP_NOT_MODIFIED || r->headers_out.content_length_n == 0) { return ngx_http_next_header_filter(r); } srv_conf = ngx_http_get_module_srv_conf(r, ngx_http_small_light_module); loc_conf = ngx_http_get_module_loc_conf(r, ngx_http_small_light_module); if (!loc_conf->enable) { return ngx_http_next_header_filter(r); } if (!loc_conf->enable_getparam_mode) { if(ngx_http_small_light_parse_define_pattern(r, &r->unparsed_uri, &define_pattern) != NGX_OK) { return ngx_http_next_header_filter(r); } } ctx = ngx_http_get_module_ctx(r, ngx_http_small_light_module); if (ctx) { ngx_http_set_ctx(r, NULL, ngx_http_small_light_module); return ngx_http_next_header_filter(r); } if ((ctx = ngx_pcalloc(r->pool, sizeof(*ctx))) == NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "failed to allocate memory from r->pool %s:%d", __FUNCTION__, __LINE__); return NGX_ERROR; } ctx->params.keys.pool = r->pool; ctx->params.temp_pool = r->pool; if (ngx_hash_keys_array_init(&ctx->params, NGX_HASH_SMALL) != NGX_OK) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "failed to init hash keys for parameters %s:%d", __FUNCTION__, __LINE__); return NGX_ERROR; } if (loc_conf->enable_getparam_mode) { if (ngx_http_small_light_init_getparams(r, ctx, srv_conf) != NGX_OK) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "failed to analyze parameters:%V %s:%d", &define_pattern, __FUNCTION__, __LINE__); return NGX_ERROR; } } else { if (ngx_http_small_light_init_params(r, ctx, &define_pattern, srv_conf) != NGX_OK) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "failed to analyze parameters:%V %s:%d", &define_pattern, __FUNCTION__, __LINE__); return NGX_ERROR; } } hash_init.hash = &ctx->hash; hash_init.key = ngx_hash_key_lc; hash_init.max_size = 128; hash_init.bucket_size = ngx_cacheline_size; hash_init.name = "small_light_init_params"; hash_init.pool = ctx->params.keys.pool; hash_init.temp_pool = NULL; if (ngx_hash_init(&hash_init, ctx->params.keys.elts, ctx->params.keys.nelts) != NGX_OK) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "failed to init hash table for parameters %s:%d", __FUNCTION__, __LINE__); return NGX_ERROR; } ctx->inf = (char *)r->headers_out.content_type.data; ctx->material_dir = &srv_conf->material_dir; ctx->imlib2_temp_dir = loc_conf->imlib2_temp_dir; if (r->headers_out.content_length_n < 0) { ctx->content_length = loc_conf->buffer_size; } else { ctx->content_length = r->headers_out.content_length_n; } converter = NGX_HTTP_SMALL_LIGHT_PARAM_GET_LIT(&ctx->hash, "e"); if (ngx_strcmp(converter, NGX_HTTP_SMALL_LIGHT_CONVERTER_IMAGEMAGICK) == 0) { ctx->converter.init = ngx_http_small_light_imagemagick_init; ctx->converter.term = ngx_http_small_light_imagemagick_term; ctx->converter.process = ngx_http_small_light_imagemagick_process; ctx->ictx = ngx_pcalloc(r->pool, sizeof(ngx_http_small_light_imagemagick_ctx_t)); #ifdef NGX_HTTP_SMALL_LIGHT_IMLIB2_ENABLED } else if (ngx_strcmp(converter, NGX_HTTP_SMALL_LIGHT_CONVERTER_IMLIB2) == 0) { ctx->converter.init = ngx_http_small_light_imlib2_init; ctx->converter.term = ngx_http_small_light_imlib2_term; ctx->converter.process = ngx_http_small_light_imlib2_process; ctx->ictx = ngx_pcalloc(r->pool, sizeof(ngx_http_small_light_imlib2_ctx_t)); #endif #ifdef NGX_HTTP_SMALL_LIGHT_GD_ENABLED } else if (ngx_strcmp(converter, NGX_HTTP_SMALL_LIGHT_CONVERTER_GD) == 0) { ctx->converter.init = ngx_http_small_light_gd_init; ctx->converter.term = ngx_http_small_light_gd_term; ctx->converter.process = ngx_http_small_light_gd_process; ctx->ictx = ngx_pcalloc(r->pool, sizeof(ngx_http_small_light_gd_ctx_t)); #endif } else { ctx->converter.init = ngx_http_small_light_imagemagick_init; ctx->converter.term = ngx_http_small_light_imagemagick_term; ctx->converter.process = ngx_http_small_light_imagemagick_process; ctx->ictx = ngx_pcalloc(r->pool, sizeof(ngx_http_small_light_imagemagick_ctx_t)); } if (ctx->ictx == NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "failed to allocate memory from r->pool %s:%d", __FUNCTION__, __LINE__); return NGX_ERROR; } ngx_http_set_ctx(r, ctx, ngx_http_small_light_module); if (r->headers_out.refresh) { r->headers_out.refresh->hash = 0; } r->main_filter_need_in_memory = 1; r->allow_ranges = 0; return NGX_OK; }
static ngx_int_t ngx_http_traffic_status_handler(ngx_http_request_t *r) { ngx_int_t rc; ngx_buf_t *b; ngx_chain_t out; u_char ngx_traffic_status_string[1024] = {0}; ngx_uint_t i; ngx_http_traffic_status_rule_t *rucf = NULL; ngx_http_traffic_status_local_conf_t *local_conf = NULL; ngx_int_t offset = 0; ngx_log_error(NGX_LOG_EMERG, r->connection->log, 0, "ngx_http_traffic_status_handler is called!"); /* we response to 'GET' and 'HEAD' requests only */ if (!(r->method & (NGX_HTTP_GET|NGX_HTTP_HEAD))) { return NGX_HTTP_NOT_ALLOWED; } rucf = ngx_http_get_module_srv_conf(r, ngx_http_traffic_status_module); if (NULL == rucf) { return NGX_ERROR; } local_conf = ngx_http_get_module_loc_conf(r, ngx_http_traffic_status_module); /* not enable */ if (!(local_conf->req_flag | local_conf->pkt_flag | local_conf->status_flag)) { return NGX_HTTP_NOT_ALLOWED; } /* request times calculate */ if (local_conf->req_flag) { ngx_sprintf(ngx_traffic_status_string + offset, "http request times: %d\n", rucf->request_cnt); offset += ngx_strlen(ngx_traffic_status_string); } if (local_conf->pkt_flag) { /* recevie bytes */ ngx_sprintf(ngx_traffic_status_string + offset, "recevie packet bytes: %d\n", rucf->recv_bytes); offset += ngx_strlen(ngx_traffic_status_string); /* send bytes */ ngx_sprintf(ngx_traffic_status_string + offset, "send packet bytes: %d\n", rucf->send_bytes); offset += ngx_strlen(ngx_traffic_status_string); } if (local_conf->status_flag) { ngx_sprintf(ngx_traffic_status_string + offset, "---- http status ----\n"); offset += ngx_strlen(ngx_traffic_status_string); ngx_sprintf(ngx_traffic_status_string + offset, "---------------------\n"); offset += ngx_strlen(ngx_traffic_status_string); for (i = 0; i < NGX_HTTP_STATUS_CODES_NUM; i++) { if (rucf->status_codes_cnt[i] > 0) { ngx_sprintf(ngx_traffic_status_string + offset, "%d: %d\n", i + NGX_HTTP_OK, rucf->status_codes_cnt[i]); offset += ngx_strlen(ngx_traffic_status_string); } } ngx_sprintf(ngx_traffic_status_string + offset, "---------------------\n"); offset += ngx_strlen(ngx_traffic_status_string); } /* discard request body, since we don't need it here */ rc = ngx_http_discard_request_body(r); if (rc != NGX_OK) { return rc; } /* set the 'Content-type' header */ ngx_str_set(&r->headers_out.content_type, "text/html"); /* send the header only, if the request type is http 'HEAD' */ if (r->method == NGX_HTTP_HEAD) { r->headers_out.status = NGX_HTTP_OK; r->headers_out.content_length_n = offset; return ngx_http_send_header(r); } /* allocate a buffer for your response body */ b = ngx_pcalloc(r->pool, sizeof(ngx_buf_t)); if (b == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } /* attach this buffer to the buffer chain */ out.buf = b; out.next = NULL; /* adjust the pointers of the buffer */ b->pos = ngx_traffic_status_string; b->last = ngx_traffic_status_string + offset; b->memory = 1; /* this buffer is in memory */ b->last_buf = 1; /* this is the last buffer in the buffer chain */ /* set the status line */ r->headers_out.status = NGX_HTTP_OK; r->headers_out.content_length_n = offset; /* send the headers of your response */ rc = ngx_http_send_header(r); if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) { return rc; } /* send the buffer chain of your response */ return ngx_http_output_filter(r, &out); }