static ngx_int_t ngx_http_vhost_traffic_status_display_handler_control(ngx_http_request_t *r) { ngx_int_t size, rc; ngx_str_t type, alpha, arg_cmd, arg_group, arg_zone; ngx_buf_t *b; ngx_chain_t out; ngx_slab_pool_t *shpool; ngx_http_vhost_traffic_status_control_t *control; ngx_http_vhost_traffic_status_loc_conf_t *vtscf; vtscf = ngx_http_get_module_loc_conf(r, ngx_http_vhost_traffic_status_module); /* init control */ control = ngx_pcalloc(r->pool, sizeof(ngx_http_vhost_traffic_status_control_t)); if (control == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } control->r = r; control->command = NGX_HTTP_VHOST_TRAFFIC_STATUS_CONTROL_CMD_NONE; control->group = -2; control->zone = ngx_pcalloc(r->pool, sizeof(ngx_str_t)); if (control->zone == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } control->arg_cmd = &arg_cmd; control->arg_group = &arg_group; control->arg_zone = &arg_zone; control->range = NGX_HTTP_VHOST_TRAFFIC_STATUS_CONTROL_RANGE_NONE; control->count = 0; arg_cmd.len = 0; arg_group.len = 0; arg_zone.len = 0; if (r->args.len) { if (ngx_http_arg(r, (u_char *) "cmd", 3, &arg_cmd) == NGX_OK) { if (arg_cmd.len == 6 && ngx_strncmp(arg_cmd.data, "status", 6) == 0) { control->command = NGX_HTTP_VHOST_TRAFFIC_STATUS_CONTROL_CMD_STATUS; } else if (arg_cmd.len == 6 && ngx_strncmp(arg_cmd.data, "delete", 6) == 0) { control->command = NGX_HTTP_VHOST_TRAFFIC_STATUS_CONTROL_CMD_DELETE; } else if (arg_cmd.len == 5 && ngx_strncmp(arg_cmd.data, "reset", 5) == 0) { control->command = NGX_HTTP_VHOST_TRAFFIC_STATUS_CONTROL_CMD_RESET; } else { control->command = NGX_HTTP_VHOST_TRAFFIC_STATUS_CONTROL_CMD_NONE; } } if (ngx_http_arg(r, (u_char *) "group", 5, &arg_group) == NGX_OK) { if (arg_group.len == 1 && ngx_strncmp(arg_group.data, "*", 1) == 0) { control->group = -1; } else if (arg_group.len == 6 && ngx_strncasecmp(arg_group.data, (u_char *) "server", 6) == 0) { control->group = NGX_HTTP_VHOST_TRAFFIC_STATUS_UPSTREAM_NO; } else if (arg_group.len == 14 && ngx_strncasecmp(arg_group.data, (u_char *) "upstream@alone", 14) == 0) { control->group = NGX_HTTP_VHOST_TRAFFIC_STATUS_UPSTREAM_UA; } else if (arg_group.len == 14 && ngx_strncasecmp(arg_group.data, (u_char *) "upstream@group", 14) == 0) { control->group = NGX_HTTP_VHOST_TRAFFIC_STATUS_UPSTREAM_UG; } else if (arg_group.len == 5 && ngx_strncasecmp(arg_group.data, (u_char *) "cache", 5) == 0) { control->group = NGX_HTTP_VHOST_TRAFFIC_STATUS_UPSTREAM_CC; } else if (arg_group.len == 6 && ngx_strncasecmp(arg_group.data, (u_char *) "filter", 6) == 0) { control->group = NGX_HTTP_VHOST_TRAFFIC_STATUS_UPSTREAM_FG; } else { control->command = NGX_HTTP_VHOST_TRAFFIC_STATUS_CONTROL_CMD_NONE; } } if (ngx_http_arg(r, (u_char *) "zone", 4, &arg_zone) != NGX_OK) { if (control->group != -1) { control->command = NGX_HTTP_VHOST_TRAFFIC_STATUS_CONTROL_CMD_NONE; } } else { rc = ngx_http_vhost_traffic_status_copy_str(r->pool, control->zone, &arg_zone); if (rc != NGX_OK) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "display_handler_control::copy_str() failed"); } (void) ngx_http_vhost_traffic_status_replace_chrc(control->zone, '@', NGX_HTTP_VHOST_TRAFFIC_STATUS_KEY_SEPARATOR); ngx_str_set(&alpha, "[:alpha:]"); rc = ngx_http_vhost_traffic_status_replace_strc(control->zone, &alpha, '@'); if (rc != NGX_OK) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "display_handler_control::replace_strc() failed"); } } ngx_http_vhost_traffic_status_node_control_range_set(control); } if (control->command == NGX_HTTP_VHOST_TRAFFIC_STATUS_CONTROL_CMD_STATUS) { size = ngx_http_vhost_traffic_status_display_get_size(r, NGX_HTTP_VHOST_TRAFFIC_STATUS_FORMAT_JSON); if (size == NGX_ERROR) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "display_handler_control::display_get_size() failed"); return NGX_HTTP_INTERNAL_SERVER_ERROR; } } else { size = sizeof(NGX_HTTP_VHOST_TRAFFIC_STATUS_JSON_FMT_CONTROL) + arg_cmd.len + arg_group.len + arg_zone.len + ngx_pagesize; } ngx_str_set(&type, "application/json"); r->headers_out.content_type_len = type.len; r->headers_out.content_type = type; if (r->method == NGX_HTTP_HEAD) { r->headers_out.status = NGX_HTTP_OK; rc = ngx_http_send_header(r); if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) { return rc; } } b = ngx_create_temp_buf(r->pool, size); if (b == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } control->buf = &b->last; shpool = (ngx_slab_pool_t *) vtscf->shm_zone->shm.addr; ngx_shmtx_lock(&shpool->mutex); switch (control->command) { case NGX_HTTP_VHOST_TRAFFIC_STATUS_CONTROL_CMD_STATUS: ngx_http_vhost_traffic_status_node_status(control); break; case NGX_HTTP_VHOST_TRAFFIC_STATUS_CONTROL_CMD_DELETE: ngx_http_vhost_traffic_status_node_delete(control); break; case NGX_HTTP_VHOST_TRAFFIC_STATUS_CONTROL_CMD_RESET: ngx_http_vhost_traffic_status_node_reset(control); break; default: *control->buf = ngx_sprintf(*control->buf, NGX_HTTP_VHOST_TRAFFIC_STATUS_JSON_FMT_CONTROL, ngx_http_vhost_traffic_status_boolean_to_string(0), control->arg_cmd, control->arg_group, control->arg_zone, control->count); break; } ngx_shmtx_unlock(&shpool->mutex); if (b->last == b->pos) { b->last = ngx_sprintf(b->last, "{}"); } r->headers_out.status = NGX_HTTP_OK; r->headers_out.content_length_n = b->last - b->pos; b->last_buf = (r == r->main) ? 1 : 0; /* if subrequest 0 else 1 */ b->last_in_chain = 1; out.buf = b; out.next = NULL; rc = ngx_http_send_header(r); if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) { return rc; } return ngx_http_output_filter(r, &out); }
static ngx_int_t ngx_http_dav_ext_send_propfind(ngx_http_request_t *r) { size_t root; ngx_str_t path, spath, suri; ngx_chain_t *l = NULL, **ll = &l; DIR *dir; int depth; struct dirent *de; size_t len; ngx_http_variable_value_t vv; ngx_str_t depth_name = ngx_string("depth"); u_char *p; if (ngx_http_variable_unknown_header(&vv, &depth_name, &r->headers_in.headers.part, 0) == NGX_OK && vv.valid) { if (vv.len == sizeof("infinity") -1 && !ngx_strncasecmp(vv.data, (u_char*)"infinity", vv.len)) { depth = DAV_EXT_INFINITY; } else { depth = ngx_atoi(vv.data, vv.len); } } else { depth = DAV_EXT_INFINITY; } p = ngx_http_map_uri_to_path(r, &path, &root, 0); if (p == NULL || !path.len) { ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0, "dav_ext error mapping uri to path"); return NGX_ERROR; } path.len = p - path.data; *p = 0; ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http propfind path: \"%V\"", &path); NGX_HTTP_DAV_EXT_OUTL( "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n" "<D:multistatus xmlns:D=\"DAV:\">\n" ); ngx_http_dav_ext_flush(r, ll); ngx_http_dav_ext_send_propfind_item(r, (char*)path.data, &r->uri); if (depth) { /* treat infinite depth as 1 for performance reasons */ if ((dir = opendir((char*)path.data))) { while((de = readdir(dir))) { if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) { continue; } len = strlen(de->d_name); ngx_http_dav_ext_make_child(r->pool, &path, (u_char*)de->d_name, len, &spath); ngx_http_dav_ext_make_child(r->pool, &r->uri, (u_char*)de->d_name, len, &suri); ngx_http_dav_ext_send_propfind_item(r, (char*)spath.data, &suri); } closedir(dir); } } NGX_HTTP_DAV_EXT_OUTL( "</D:multistatus>\n" ); if (*ll && (*ll)->buf) { (*ll)->buf->last_buf = 1; } ngx_http_dav_ext_flush(r, ll); return NGX_OK; }
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]; ngx_int_t index=-1; 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; 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; ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "KEY-Value Pair: \"%V\" and \"%V\"", &header[i].key,&header[i].value); index=i; value=ngx_pstrdup(r->pool,&header[i].value); /*int count1=17; while(count1) { value++; count1--; } ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "Value is : \"%s\" ", value); valueLen=header[i].value.len - 17;*/ ngx_int_t countSlash=0; ngx_int_t countLen=0; while(*value!='\0' && countSlash!=3) { if(*value=='/') countSlash++; if(countSlash!=3) value++; countLen++; } countLen--; valueLen=header[i].value.len - countLen; if(index!=-1) { ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "key-value : %d and %d", countLen,valueLen); } } } if(!isSet) { ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "spdy serverpush module header filter !isSet cond"); return ngx_http_next_header_filter(r); } 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 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/test1.js");*/ len += ngx_http_spdy_nv_nsize("url") +ngx_http_spdy_nv_vsize(&header[index].value); 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; 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 += 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/test1.js"); #if 1 last = ngx_http_spdy_nv_write_vlen(last, header[index].value.len); last = ngx_cpymem(last, header[index].value.data, header[index].value.len); #endif 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; ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "spdy serverpush module header filter 5"); 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 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); }
static ngx_int_t ngx_http_vhost_traffic_status_display_handler_default(ngx_http_request_t *r) { size_t len; u_char *o, *s; ngx_str_t uri, type; ngx_int_t size, format, rc; ngx_buf_t *b; ngx_chain_t out; ngx_slab_pool_t *shpool; ngx_http_vhost_traffic_status_ctx_t *ctx; ngx_http_vhost_traffic_status_loc_conf_t *vtscf; 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) { return NGX_HTTP_NOT_IMPLEMENTED; } if (r->method != NGX_HTTP_GET && r->method != NGX_HTTP_HEAD) { return NGX_HTTP_NOT_ALLOWED; } uri = r->uri; format = NGX_HTTP_VHOST_TRAFFIC_STATUS_FORMAT_NONE; if (uri.len == 1) { if (ngx_strncmp(uri.data, "/", 1) == 0) { uri.len = 0; } } o = (u_char *) r->uri.data; s = o; len = r->uri.len; while(sizeof("/format/type") - 1 <= len) { if (ngx_strncasecmp(s, (u_char *) "/format/", sizeof("/format/") - 1) == 0) { uri.data = o; uri.len = (o == s) ? 0 : (size_t) (s - o); s += sizeof("/format/") - 1; if (ngx_strncasecmp(s, (u_char *) "jsonp", sizeof("jsonp") - 1) == 0) { format = NGX_HTTP_VHOST_TRAFFIC_STATUS_FORMAT_JSONP; } else if (ngx_strncasecmp(s, (u_char *) "json", sizeof("json") - 1) == 0) { format = NGX_HTTP_VHOST_TRAFFIC_STATUS_FORMAT_JSON; } else if (ngx_strncasecmp(s, (u_char *) "html", sizeof("html") - 1) == 0) { format = NGX_HTTP_VHOST_TRAFFIC_STATUS_FORMAT_HTML; } else if (ngx_strncasecmp(s, (u_char *) "prometheus", sizeof("prometheus") - 1) == 0) { format = NGX_HTTP_VHOST_TRAFFIC_STATUS_FORMAT_PROMETHEUS; } else { s -= 2; } if (format != NGX_HTTP_VHOST_TRAFFIC_STATUS_FORMAT_NONE) { break; } } if ((s = (u_char *) ngx_strchr(++s, '/')) == NULL) { break; } if (r->uri.len <= (size_t) (s - o)) { break; } len = r->uri.len - (size_t) (s - o); } format = (format == NGX_HTTP_VHOST_TRAFFIC_STATUS_FORMAT_NONE) ? vtscf->format : format; rc = ngx_http_discard_request_body(r); if (rc != NGX_OK) { return rc; } if (format == NGX_HTTP_VHOST_TRAFFIC_STATUS_FORMAT_JSON) { ngx_str_set(&type, "application/json"); } else if (format == NGX_HTTP_VHOST_TRAFFIC_STATUS_FORMAT_JSONP) { ngx_str_set(&type, "application/javascript"); } else if (format == NGX_HTTP_VHOST_TRAFFIC_STATUS_FORMAT_PROMETHEUS) { ngx_str_set(&type, "text/plain"); } else { ngx_str_set(&type, "text/html"); } r->headers_out.content_type_len = type.len; r->headers_out.content_type = type; if (r->method == NGX_HTTP_HEAD) { r->headers_out.status = NGX_HTTP_OK; rc = ngx_http_send_header(r); if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) { return rc; } } size = ngx_http_vhost_traffic_status_display_get_size(r, format); if (size == NGX_ERROR) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "display_handler_default::display_get_size() failed"); return NGX_HTTP_INTERNAL_SERVER_ERROR; } b = ngx_create_temp_buf(r->pool, size); if (b == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } if (format == NGX_HTTP_VHOST_TRAFFIC_STATUS_FORMAT_JSON) { shpool = (ngx_slab_pool_t *) vtscf->shm_zone->shm.addr; ngx_shmtx_lock(&shpool->mutex); b->last = ngx_http_vhost_traffic_status_display_set(r, b->last); ngx_shmtx_unlock(&shpool->mutex); if (b->last == b->pos) { b->last = ngx_sprintf(b->last, "{}"); } } else if (format == NGX_HTTP_VHOST_TRAFFIC_STATUS_FORMAT_JSONP) { shpool = (ngx_slab_pool_t *) vtscf->shm_zone->shm.addr; ngx_shmtx_lock(&shpool->mutex); b->last = ngx_sprintf(b->last, "%V", &vtscf->jsonp); b->last = ngx_sprintf(b->last, "("); b->last = ngx_http_vhost_traffic_status_display_set(r, b->last); b->last = ngx_sprintf(b->last, ")"); ngx_shmtx_unlock(&shpool->mutex); } else if (format == NGX_HTTP_VHOST_TRAFFIC_STATUS_FORMAT_PROMETHEUS) { shpool = (ngx_slab_pool_t *) vtscf->shm_zone->shm.addr; ngx_shmtx_lock(&shpool->mutex); b->last = ngx_http_vhost_traffic_status_display_prometheus_set(r, b->last); ngx_shmtx_unlock(&shpool->mutex); if (b->last == b->pos) { b->last = ngx_sprintf(b->last, "#"); } } else { b->last = ngx_sprintf(b->last, NGX_HTTP_VHOST_TRAFFIC_STATUS_HTML_DATA, &uri, &uri); } r->headers_out.status = NGX_HTTP_OK; r->headers_out.content_length_n = b->last - b->pos; b->last_buf = (r == r->main) ? 1 : 0; /* if subrequest 0 else 1 */ b->last_in_chain = 1; out.buf = b; out.next = NULL; rc = ngx_http_send_header(r); if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) { return rc; } return ngx_http_output_filter(r, &out); }
ngx_tcp_upstream_srv_conf_t * ngx_tcp_upstream_add(ngx_conf_t *cf, ngx_url_t *u, ngx_uint_t flags) { ngx_uint_t i; ngx_tcp_upstream_server_t *us; ngx_tcp_upstream_srv_conf_t *uscf, **uscfp; ngx_tcp_upstream_main_conf_t *umcf; if (!(flags & NGX_TCP_UPSTREAM_CREATE)) { if (ngx_parse_url(cf->pool, u) != NGX_OK) { if (u->err) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%s in upstream \"%V\"", u->err, &u->url); } return NULL; } } umcf = ngx_tcp_conf_get_module_main_conf(cf, ngx_tcp_upstream_module); uscfp = umcf->upstreams.elts; for (i = 0; i < umcf->upstreams.nelts; i++) { if (uscfp[i]->host.len != u->host.len || ngx_strncasecmp(uscfp[i]->host.data, u->host.data, u->host.len) != 0) { continue; } if ((flags & NGX_TCP_UPSTREAM_CREATE) && (uscfp[i]->flags & NGX_TCP_UPSTREAM_CREATE)) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "duplicate upstream \"%V\"", &u->host); return NULL; } if ((uscfp[i]->flags & NGX_TCP_UPSTREAM_CREATE) && u->port) { ngx_conf_log_error(NGX_LOG_WARN, cf, 0, "upstream \"%V\" may not have port %d", &u->host, u->port); return NULL; } if ((flags & NGX_TCP_UPSTREAM_CREATE) && uscfp[i]->port) { ngx_log_error(NGX_LOG_WARN, cf->log, 0, "upstream \"%V\" may not have port %d in %s:%ui", &u->host, uscfp[i]->port, uscfp[i]->file_name, uscfp[i]->line); return NULL; } if (uscfp[i]->port != u->port) { continue; } if (uscfp[i]->default_port && u->default_port && uscfp[i]->default_port != u->default_port) { continue; } return uscfp[i]; } uscf = ngx_pcalloc(cf->pool, sizeof(ngx_tcp_upstream_srv_conf_t)); if (uscf == NULL) { return NULL; } uscf->flags = flags; uscf->host = u->host; uscf->file_name = cf->conf_file->file.name.data; uscf->line = cf->conf_file->line; uscf->port = u->port; uscf->default_port = u->default_port; uscf->code.status_alive = 0; if (u->naddrs == 1) { uscf->servers = ngx_array_create(cf->pool, 1, sizeof(ngx_tcp_upstream_server_t)); if (uscf->servers == NULL) { return NGX_CONF_ERROR; } us = ngx_array_push(uscf->servers); if (us == NULL) { return NGX_CONF_ERROR; } ngx_memzero(us, sizeof(ngx_tcp_upstream_server_t)); us->addrs = u->addrs; us->naddrs = u->naddrs; } uscfp = ngx_array_push(&umcf->upstreams); if (uscfp == NULL) { return NULL; } *uscfp = uscf; return uscf; }
static ngx_int_t ngx_http_autoindex_handler(ngx_http_request_t *r) { u_char *last, *filename, scale; off_t length; size_t len, char_len, escape_html, allocated, root; ngx_tm_t tm; ngx_err_t err; ngx_buf_t *b; ngx_int_t rc, size; ngx_str_t path; ngx_dir_t dir; ngx_uint_t i, level, utf8; ngx_pool_t *pool; ngx_time_t *tp; ngx_chain_t out; ngx_array_t entries; ngx_http_autoindex_entry_t *entry; ngx_http_autoindex_loc_conf_t *alcf; static char *months[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; if (r->uri.data[r->uri.len - 1] != '/') { return NGX_DECLINED; } if (!(r->method & (NGX_HTTP_GET|NGX_HTTP_HEAD))) { return NGX_DECLINED; } alcf = ngx_http_get_module_loc_conf(r, ngx_http_autoindex_module); if (!alcf->enable) { return NGX_DECLINED; } /* NGX_DIR_MASK_LEN is lesser than NGX_HTTP_AUTOINDEX_PREALLOCATE */ last = ngx_http_map_uri_to_path(r, &path, &root, NGX_HTTP_AUTOINDEX_PREALLOCATE); if (last == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } allocated = path.len; path.len = last - path.data; if (path.len > 1) { path.len--; } path.data[path.len] = '\0'; ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http autoindex: \"%s\"", path.data); if (ngx_open_dir(&path, &dir) == NGX_ERROR) { err = ngx_errno; if (err == NGX_ENOENT || err == NGX_ENOTDIR || err == NGX_ENAMETOOLONG) { level = NGX_LOG_ERR; rc = NGX_HTTP_NOT_FOUND; } else if (err == NGX_EACCES) { level = NGX_LOG_ERR; rc = NGX_HTTP_FORBIDDEN; } else { level = NGX_LOG_CRIT; rc = NGX_HTTP_INTERNAL_SERVER_ERROR; } ngx_log_error(level, r->connection->log, err, ngx_open_dir_n " \"%s\" failed", path.data); return rc; } #if (NGX_SUPPRESS_WARN) /* MSVC thinks 'entries' may be used without having been initialized */ ngx_memzero(&entries, sizeof(ngx_array_t)); #endif /* TODO: pool should be temporary pool */ pool = r->pool; if (ngx_array_init(&entries, pool, 40, sizeof(ngx_http_autoindex_entry_t)) != NGX_OK) { return ngx_http_autoindex_error(r, &dir, &path); } r->headers_out.status = NGX_HTTP_OK; r->headers_out.content_type_len = sizeof("text/html") - 1; ngx_str_set(&r->headers_out.content_type, "text/html"); rc = ngx_http_send_header(r); if (rc == NGX_ERROR || rc > NGX_OK || r->header_only) { if (ngx_close_dir(&dir) == NGX_ERROR) { ngx_log_error(NGX_LOG_ALERT, r->connection->log, ngx_errno, ngx_close_dir_n " \"%V\" failed", &path); } return rc; } filename = path.data; filename[path.len] = '/'; if (r->headers_out.charset.len == 5 && ngx_strncasecmp(r->headers_out.charset.data, (u_char *) "utf-8", 5) == 0) { utf8 = 1; } else { utf8 = 0; } for ( ;; ) { ngx_set_errno(0); if (ngx_read_dir(&dir) == NGX_ERROR) { err = ngx_errno; if (err != NGX_ENOMOREFILES) { ngx_log_error(NGX_LOG_CRIT, r->connection->log, err, ngx_read_dir_n " \"%V\" failed", &path); return ngx_http_autoindex_error(r, &dir, &path); } break; } ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http autoindex file: \"%s\"", ngx_de_name(&dir)); len = ngx_de_namelen(&dir); if (ngx_de_name(&dir)[0] == '.') { continue; } if (!dir.valid_info) { /* 1 byte for '/' and 1 byte for terminating '\0' */ if (path.len + 1 + len + 1 > allocated) { allocated = path.len + 1 + len + 1 + NGX_HTTP_AUTOINDEX_PREALLOCATE; filename = ngx_pnalloc(pool, allocated); if (filename == NULL) { return ngx_http_autoindex_error(r, &dir, &path); } last = ngx_cpystrn(filename, path.data, path.len + 1); *last++ = '/'; } ngx_cpystrn(last, ngx_de_name(&dir), len + 1); if (ngx_de_info(filename, &dir) == NGX_FILE_ERROR) { err = ngx_errno; if (err != NGX_ENOENT) { ngx_log_error(NGX_LOG_CRIT, r->connection->log, err, ngx_de_info_n " \"%s\" failed", filename); if (err == NGX_EACCES) { continue; } return ngx_http_autoindex_error(r, &dir, &path); } if (ngx_de_link_info(filename, &dir) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno, ngx_de_link_info_n " \"%s\" failed", filename); return ngx_http_autoindex_error(r, &dir, &path); } } } entry = ngx_array_push(&entries); if (entry == NULL) { return ngx_http_autoindex_error(r, &dir, &path); } entry->name.len = len; entry->name.data = ngx_pnalloc(pool, len + 1); if (entry->name.data == NULL) { return ngx_http_autoindex_error(r, &dir, &path); } ngx_cpystrn(entry->name.data, ngx_de_name(&dir), len + 1); entry->escape = 2 * ngx_escape_uri(NULL, ngx_de_name(&dir), len, NGX_ESCAPE_URI_COMPONENT); entry->escape_html = ngx_escape_html(NULL, entry->name.data, entry->name.len); if (utf8) { entry->utf_len = ngx_utf8_length(entry->name.data, entry->name.len); } else { entry->utf_len = len; } entry->dir = ngx_de_is_dir(&dir); entry->mtime = ngx_de_mtime(&dir); entry->size = ngx_de_size(&dir); } if (ngx_close_dir(&dir) == NGX_ERROR) { ngx_log_error(NGX_LOG_ALERT, r->connection->log, ngx_errno, ngx_close_dir_n " \"%s\" failed", &path); } escape_html = ngx_escape_html(NULL, r->uri.data, r->uri.len); len = sizeof(title) - 1 + r->uri.len + escape_html + sizeof(header) - 1 + r->uri.len + escape_html + sizeof("</h1>") - 1 + sizeof("<hr><pre><a href=\"../\">../</a>" CRLF) - 1 + sizeof("</pre><hr>") - 1 + sizeof(tail) - 1; entry = entries.elts; for (i = 0; i < entries.nelts; i++) { len += sizeof("<a href=\"") - 1 + entry[i].name.len + entry[i].escape + 1 /* 1 is for "/" */ + sizeof("\">") - 1 + entry[i].name.len - entry[i].utf_len + entry[i].escape_html + NGX_HTTP_AUTOINDEX_NAME_LEN + sizeof(">") - 2 + sizeof("</a>") - 1 + sizeof(" 28-Sep-1970 12:00 ") - 1 + 20 /* the file size */ + 2; } b = ngx_create_temp_buf(r->pool, len); if (b == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } if (entries.nelts > 1) { ngx_qsort(entry, (size_t) entries.nelts, sizeof(ngx_http_autoindex_entry_t), ngx_http_autoindex_cmp_entries); } b->last = ngx_cpymem(b->last, title, sizeof(title) - 1); if (escape_html) { b->last = (u_char *) ngx_escape_html(b->last, r->uri.data, r->uri.len); b->last = ngx_cpymem(b->last, header, sizeof(header) - 1); b->last = (u_char *) ngx_escape_html(b->last, r->uri.data, r->uri.len); } else { b->last = ngx_cpymem(b->last, r->uri.data, r->uri.len); b->last = ngx_cpymem(b->last, header, sizeof(header) - 1); b->last = ngx_cpymem(b->last, r->uri.data, r->uri.len); } b->last = ngx_cpymem(b->last, "</h1>", sizeof("</h1>") - 1); b->last = ngx_cpymem(b->last, "<hr><pre><a href=\"../\">../</a>" CRLF, sizeof("<hr><pre><a href=\"../\">../</a>" CRLF) - 1); tp = ngx_timeofday(); for (i = 0; i < entries.nelts; i++) { b->last = ngx_cpymem(b->last, "<a href=\"", sizeof("<a href=\"") - 1); if (entry[i].escape) { ngx_escape_uri(b->last, entry[i].name.data, entry[i].name.len, NGX_ESCAPE_URI_COMPONENT); b->last += entry[i].name.len + entry[i].escape; } else { b->last = ngx_cpymem(b->last, entry[i].name.data, entry[i].name.len); } if (entry[i].dir) { *b->last++ = '/'; } *b->last++ = '"'; *b->last++ = '>'; len = entry[i].utf_len; if (entry[i].name.len != len) { if (len > NGX_HTTP_AUTOINDEX_NAME_LEN) { char_len = NGX_HTTP_AUTOINDEX_NAME_LEN - 3 + 1; } else { char_len = NGX_HTTP_AUTOINDEX_NAME_LEN + 1; } last = b->last; b->last = ngx_utf8_cpystrn(b->last, entry[i].name.data, char_len, entry[i].name.len + 1); if (entry[i].escape_html) { b->last = (u_char *) ngx_escape_html(last, entry[i].name.data, b->last - last); } last = b->last; } else { if (entry[i].escape_html) { if (len > NGX_HTTP_AUTOINDEX_NAME_LEN) { char_len = NGX_HTTP_AUTOINDEX_NAME_LEN - 3; } else { char_len = len; } b->last = (u_char *) ngx_escape_html(b->last, entry[i].name.data, char_len); last = b->last; } else { b->last = ngx_cpystrn(b->last, entry[i].name.data, NGX_HTTP_AUTOINDEX_NAME_LEN + 1); last = b->last - 3; } } if (len > NGX_HTTP_AUTOINDEX_NAME_LEN) { b->last = ngx_cpymem(last, "..></a>", sizeof("..></a>") - 1); } else { if (entry[i].dir && NGX_HTTP_AUTOINDEX_NAME_LEN - len > 0) { *b->last++ = '/'; len++; } b->last = ngx_cpymem(b->last, "</a>", sizeof("</a>") - 1); if (NGX_HTTP_AUTOINDEX_NAME_LEN - len > 0) { ngx_memset(b->last, ' ', NGX_HTTP_AUTOINDEX_NAME_LEN - len); b->last += NGX_HTTP_AUTOINDEX_NAME_LEN - len; } } *b->last++ = ' '; ngx_gmtime(entry[i].mtime + tp->gmtoff * 60 * alcf->localtime, &tm); b->last = ngx_sprintf(b->last, "%02d-%s-%d %02d:%02d ", tm.ngx_tm_mday, months[tm.ngx_tm_mon - 1], tm.ngx_tm_year, tm.ngx_tm_hour, tm.ngx_tm_min); if (alcf->exact_size) { if (entry[i].dir) { b->last = ngx_cpymem(b->last, " -", sizeof(" -") - 1); } else { b->last = ngx_sprintf(b->last, "%19O", entry[i].size); } } else { if (entry[i].dir) { b->last = ngx_cpymem(b->last, " -", sizeof(" -") - 1); } else { length = entry[i].size; if (length > 1024 * 1024 * 1024 - 1) { size = (ngx_int_t) (length / (1024 * 1024 * 1024)); if ((length % (1024 * 1024 * 1024)) > (1024 * 1024 * 1024 / 2 - 1)) { size++; } scale = 'G'; } else if (length > 1024 * 1024 - 1) { size = (ngx_int_t) (length / (1024 * 1024)); if ((length % (1024 * 1024)) > (1024 * 1024 / 2 - 1)) { size++; } scale = 'M'; } else if (length > 9999) { size = (ngx_int_t) (length / 1024); if (length % 1024 > 511) { size++; } scale = 'K'; } else { size = (ngx_int_t) length; scale = '\0'; } if (scale) { b->last = ngx_sprintf(b->last, "%6i%c", size, scale); } else { b->last = ngx_sprintf(b->last, " %6i", size); } } } *b->last++ = CR; *b->last++ = LF; } /* TODO: free temporary pool */ b->last = ngx_cpymem(b->last, "</pre><hr>", sizeof("</pre><hr>") - 1); b->last = ngx_cpymem(b->last, tail, sizeof(tail) - 1); if (r == r->main) { b->last_buf = 1; } b->last_in_chain = 1; out.buf = b; out.next = NULL; return ngx_http_output_filter(r, &out); }
ngx_http_tfs_upstream_t * ngx_http_tfs_upstream_add(ngx_conf_t *cf, ngx_url_t *u, ngx_uint_t flags) { ngx_uint_t i; ngx_http_tfs_upstream_t *tu, **tup; ngx_http_tfs_main_conf_t *tmcf; if (!(flags & NGX_HTTP_TFS_UPSTREAM_CREATE)) { if (ngx_parse_url(cf->pool, u) != NGX_OK) { if (u->err) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%s in tfs upstream \"%V\"", u->err, &u->url); } return NULL; } } tmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_tfs_module); tup = tmcf->upstreams.elts; for (i = 0; i < tmcf->upstreams.nelts; i++) { if (tup[i]->host.len != u->host.len || ngx_strncasecmp(tup[i]->host.data, u->host.data, u->host.len) != 0) { continue; } if (flags & NGX_HTTP_TFS_UPSTREAM_CREATE) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "duplicate tfs upstream \"%V\"", &u->host); return NULL; } return tup[i]; } if (flags & NGX_HTTP_TFS_UPSTREAM_FIND) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, " host not found in tfs upstream \"%V\"", &u->url); return NULL; } /* NGX_HTTP_TFS_UPSTREAM_CREATE */ tu = ngx_pcalloc(cf->pool, sizeof(ngx_http_tfs_upstream_t)); if (tu == NULL) { return NULL; } tu->host = u->host; tup = ngx_array_push(&tmcf->upstreams); if (tup == NULL) { return NULL; } *tup = tu; return tu; }
static ngx_int_t ngx_http_push_stream_subscriber_handler(ngx_http_request_t *r) { ngx_slab_pool_t *shpool = (ngx_slab_pool_t *)ngx_http_push_stream_shm_zone->shm.addr; ngx_http_push_stream_loc_conf_t *cf = ngx_http_get_module_loc_conf(r, ngx_http_push_stream_module); ngx_http_push_stream_subscriber_t *worker_subscriber; ngx_http_push_stream_requested_channel_t *channels_ids, *cur; ngx_http_push_stream_subscriber_ctx_t *ctx; time_t if_modified_since; ngx_str_t *last_event_id, vv_time = ngx_null_string; ngx_str_t *push_mode; ngx_flag_t polling, longpolling; ngx_int_t rc; ngx_int_t status_code; ngx_str_t *explain_error_message; // add headers to support cross domain requests if (cf->allowed_origins.len > 0) { ngx_http_push_stream_add_response_header(r, &NGX_HTTP_PUSH_STREAM_HEADER_ACCESS_CONTROL_ALLOW_ORIGIN, &cf->allowed_origins); ngx_http_push_stream_add_response_header(r, &NGX_HTTP_PUSH_STREAM_HEADER_ACCESS_CONTROL_ALLOW_METHODS, &NGX_HTTP_PUSH_STREAM_ALLOW_GET); ngx_http_push_stream_add_response_header(r, &NGX_HTTP_PUSH_STREAM_HEADER_ACCESS_CONTROL_ALLOW_HEADERS, &NGX_HTTP_PUSH_STREAM_ALLOWED_HEADERS); } if (r->method & NGX_HTTP_OPTIONS) { return ngx_http_push_stream_send_only_header_response(r, NGX_HTTP_OK, NULL); } ngx_http_push_stream_set_expires(r, NGX_HTTP_PUSH_STREAM_EXPIRES_MAX, 0); // only accept GET method if (!(r->method & NGX_HTTP_GET)) { ngx_http_push_stream_add_response_header(r, &NGX_HTTP_PUSH_STREAM_HEADER_ALLOW, &NGX_HTTP_PUSH_STREAM_ALLOW_GET); return ngx_http_push_stream_send_only_header_response(r, NGX_HTTP_NOT_ALLOWED, NULL); } if ((ctx = ngx_http_push_stream_add_request_context(r)) == NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "push stream module: unable to create request context"); return NGX_HTTP_INTERNAL_SERVER_ERROR; } //get channels ids and backtracks from path channels_ids = ngx_http_push_stream_parse_channels_ids_from_path(r, ctx->temp_pool); if ((channels_ids == NULL) || ngx_queue_empty(&channels_ids->queue)) { ngx_log_error(NGX_LOG_WARN, r->connection->log, 0, "push stream module: the $push_stream_channels_path variable is required but is not set"); return ngx_http_push_stream_send_only_header_response(r, NGX_HTTP_BAD_REQUEST, &NGX_HTTP_PUSH_STREAM_NO_CHANNEL_ID_MESSAGE); } //validate channels: name, length and quantity. check if channel exists when authorized_channels_only is on. check if channel is full of subscribers if (ngx_http_push_stream_validate_channels(r, channels_ids, &status_code, &explain_error_message) == NGX_ERROR) { return ngx_http_push_stream_send_only_header_response(r, status_code, explain_error_message); } if (cf->last_received_message_time != NULL) { ngx_http_push_stream_complex_value(r, cf->last_received_message_time, &vv_time); } else if (r->headers_in.if_modified_since != NULL) { vv_time = r->headers_in.if_modified_since->value; } // get control headers if_modified_since = vv_time.len ? ngx_http_parse_time(vv_time.data, vv_time.len) : -1; last_event_id = ngx_http_push_stream_get_header(r, &NGX_HTTP_PUSH_STREAM_HEADER_LAST_EVENT_ID); push_mode = ngx_http_push_stream_get_header(r, &NGX_HTTP_PUSH_STREAM_HEADER_MODE); polling = ((cf->location_type == NGX_HTTP_PUSH_STREAM_SUBSCRIBER_MODE_POLLING) || ((push_mode != NULL) && (push_mode->len == NGX_HTTP_PUSH_STREAM_MODE_POLLING.len) && (ngx_strncasecmp(push_mode->data, NGX_HTTP_PUSH_STREAM_MODE_POLLING.data, NGX_HTTP_PUSH_STREAM_MODE_POLLING.len) == 0))); longpolling = ((cf->location_type == NGX_HTTP_PUSH_STREAM_SUBSCRIBER_MODE_LONGPOLLING) || ((push_mode != NULL) && (push_mode->len == NGX_HTTP_PUSH_STREAM_MODE_LONGPOLLING.len) && (ngx_strncasecmp(push_mode->data, NGX_HTTP_PUSH_STREAM_MODE_LONGPOLLING.data, NGX_HTTP_PUSH_STREAM_MODE_LONGPOLLING.len) == 0))); if (polling || longpolling) { ngx_int_t result = ngx_http_push_stream_subscriber_polling_handler(r, channels_ids, if_modified_since, last_event_id, longpolling, ctx->temp_pool); if (ctx->temp_pool != NULL) { ngx_destroy_pool(ctx->temp_pool); ctx->temp_pool = NULL; } return result; } ctx->padding = ngx_http_push_stream_get_padding_by_user_agent(r); // stream access if ((worker_subscriber = ngx_http_push_stream_subscriber_prepare_request_to_keep_connected(r)) == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } ngx_http_push_stream_add_response_header(r, &NGX_HTTP_PUSH_STREAM_HEADER_TRANSFER_ENCODING, &NGX_HTTP_PUSH_STREAM_HEADER_CHUNCKED); ngx_http_send_header(r); // sending response content header if (ngx_http_push_stream_send_response_content_header(r, cf) == NGX_ERROR) { ngx_log_error(NGX_LOG_ERR, (r)->connection->log, 0, "push stream module: could not send content header to subscriber"); return NGX_HTTP_INTERNAL_SERVER_ERROR; } ngx_shmtx_lock(&shpool->mutex); rc = ngx_http_push_stream_registry_subscriber_locked(r, worker_subscriber); ngx_shmtx_unlock(&shpool->mutex); if (rc == NGX_ERROR) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } // adding subscriber to channel(s) and send backtrack messages cur = channels_ids; while ((cur = (ngx_http_push_stream_requested_channel_t *) ngx_queue_next(&cur->queue)) != channels_ids) { if (ngx_http_push_stream_subscriber_assign_channel(shpool, cf, r, cur, if_modified_since, last_event_id, worker_subscriber, ctx->temp_pool) != NGX_OK) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } } if (ctx->temp_pool != NULL) { ngx_destroy_pool(ctx->temp_pool); ctx->temp_pool = NULL; } return NGX_DONE; }
ngx_stream_variable_t * ngx_stream_add_variable(ngx_conf_t *cf, ngx_str_t *name, ngx_uint_t flags) { ngx_int_t rc; ngx_uint_t i; ngx_hash_key_t *key; ngx_stream_variable_t *v; ngx_stream_core_main_conf_t *cmcf; if (name->len == 0) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid variable name \"$\""); return NULL; } if (flags & NGX_STREAM_VAR_PREFIX) { return ngx_stream_add_prefix_variable(cf, name, flags); } cmcf = ngx_stream_conf_get_module_main_conf(cf, ngx_stream_core_module); key = cmcf->variables_keys->keys.elts; for (i = 0; i < cmcf->variables_keys->keys.nelts; i++) { if (name->len != key[i].key.len || ngx_strncasecmp(name->data, key[i].key.data, name->len) != 0) { continue; } v = key[i].value; if (!(v->flags & NGX_STREAM_VAR_CHANGEABLE)) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "the duplicate \"%V\" variable", name); return NULL; } v->flags &= flags | ~NGX_STREAM_VAR_WEAK; return v; } v = ngx_palloc(cf->pool, sizeof(ngx_stream_variable_t)); if (v == NULL) { return NULL; } v->name.len = name->len; v->name.data = ngx_pnalloc(cf->pool, name->len); if (v->name.data == NULL) { return NULL; } ngx_strlow(v->name.data, name->data, name->len); v->set_handler = NULL; v->get_handler = NULL; v->data = 0; v->flags = flags; v->index = 0; rc = ngx_hash_add_key(cmcf->variables_keys, &v->name, v, 0); if (rc == NGX_ERROR) { return NULL; } if (rc == NGX_BUSY) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "conflicting variable name \"%V\"", name); return NULL; } return v; }
static ngx_int_t hexin_http_percn_set_content_length_header(ngx_http_request_t *r, off_t len) { ngx_table_elt_t *h, *header; u_char *p; ngx_list_part_t *part; ngx_http_request_t *pr; ngx_uint_t i; r->headers_in.content_length_n = len; if (ngx_list_init(&r->headers_in.headers, r->pool, 20, sizeof(ngx_table_elt_t)) != NGX_OK) { return NGX_ERROR; } h = ngx_list_push(&r->headers_in.headers); if (h == NULL) { return NGX_ERROR; } h->key = hexin_http_percn_content_length_header_key; h->lowcase_key = ngx_pnalloc(r->pool, h->key.len); if (h->lowcase_key == NULL) { return NGX_ERROR; } ngx_strlow(h->lowcase_key, h->key.data, h->key.len); r->headers_in.content_length = h; p = ngx_palloc(r->pool, NGX_OFF_T_LEN); if (p == NULL) { return NGX_ERROR; } h->value.data = p; h->value.len = ngx_sprintf(h->value.data, "%O", len) - h->value.data; h->hash = ngx_hash(ngx_hash(ngx_hash(ngx_hash(ngx_hash(ngx_hash(ngx_hash( ngx_hash(ngx_hash(ngx_hash(ngx_hash(ngx_hash( ngx_hash('C', 'o'), 'n'), 't'), 'e'), 'n'), 't'), '-'), 'L'), 'e'),'n'), 'g'), 't'), 'h'); pr = r->parent; if (pr == NULL) { return NGX_OK; } part = &pr->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[i].key.len == sizeof("Content-Length") - 1 && ngx_strncasecmp(header[i].key.data, (u_char *) "Content-Length", sizeof("Content-Length") - 1) == 0) { continue; } h = ngx_list_push(&r->headers_in.headers); if (h == NULL) { return NGX_ERROR; } *h = header[i]; } return NGX_OK; }
static ngx_int_t ngx_rtmp_notify_play_handle(ngx_rtmp_session_t *s, void *arg, ngx_chain_t *in) { ngx_rtmp_play_t *v = arg; ngx_int_t rc; ngx_str_t local_name; ngx_str_t local_args; ngx_rtmp_relay_target_t target; ngx_url_t *u; ngx_rtmp_notify_app_conf_t *nacf; u_char name[NGX_RTMP_MAX_NAME]; static ngx_str_t location = ngx_string("location"); rc = ngx_rtmp_notify_parse_http_retcode(s, in); if (rc == NGX_ERROR) { ngx_rtmp_notify_clear_flag(s, NGX_RTMP_NOTIFY_PLAYING); return NGX_ERROR; } if (rc != NGX_AGAIN) { goto next; } /* HTTP 3xx */ ngx_log_debug0(NGX_LOG_DEBUG_RTMP, s->connection->log, 0, "notify: play redirect received"); rc = ngx_rtmp_notify_parse_http_header(s, in, &location, name, sizeof(name) - 1); if (rc <= 0) { goto next; } if (ngx_strncasecmp(name, (u_char *) "rtmp://", 7)) { *ngx_cpymem(v->name, name, rc) = 0; ngx_log_error(NGX_LOG_INFO, s->connection->log, 0, "notify: play redirect to '%s'", v->name); goto next; } /* pull */ nacf = ngx_rtmp_get_module_app_conf(s, ngx_rtmp_notify_module); if (nacf->relay_redirect) { ngx_rtmp_notify_set_name(v->name, NGX_RTMP_MAX_NAME, name, (size_t) rc); } ngx_log_error(NGX_LOG_INFO, s->connection->log, 0, "notify: pull '%s' from '%*s'", v->name, rc, name); local_name.data = v->name; local_name.len = ngx_strlen(v->name); local_args.data = v->args; local_args.len = ngx_strlen(v->args); ngx_memzero(&target, sizeof(target)); u = &target.url; u->url = local_name; u->url.data = name + 7; u->url.len = rc - 7; u->default_port = 1935; u->uri_part = 1; u->no_resolve = 1; /* want ip here */ if (ngx_parse_url(s->connection->pool, u) != NGX_OK) { ngx_log_error(NGX_LOG_INFO, s->connection->log, 0, "notify: pull failed '%V'", &local_name); return NGX_ERROR; } ngx_rtmp_relay_pull(s, &local_name, &local_args, &target); next: return next_play(s, v); }
static ngx_int_t ngx_http_session_sticky_insert(ngx_http_request_t *r) { u_char *p; ngx_uint_t i; ngx_list_part_t *part; ngx_table_elt_t *set_cookie, *table; ngx_http_ss_ctx_t *ctx; ctx = ngx_http_get_module_ctx(r, ngx_http_upstream_session_sticky_module); if (ctx->frist != 1 && ctx->sscf->maxidle == NGX_CONF_UNSET) { return NGX_OK; } set_cookie = NULL; if (ctx->sscf->flag & NGX_HTTP_SESSION_STICKY_INDIRECT) { part = &r->headers_out.headers.part; while (part && set_cookie == NULL) { table = (ngx_table_elt_t *) part->elts; for (i = 0; i < part->nelts; i++) { if (table[i].key.len == (sizeof("set-cookie") - 1) && ngx_strncasecmp(table[i].key.data, (u_char *) "set-cookie", table[i].key.len) == 0) { p = ngx_strlcasestrn(table[i].value.data, table[i].value.data + table[i].value.len, ctx->sscf->cookie.data, ctx->sscf->cookie.len - 1); if (p != NULL) { set_cookie = &table[i]; break; } } } part = part->next; } } if (set_cookie == NULL) { set_cookie = ngx_list_push(&r->headers_out.headers); if (set_cookie == NULL) { return NGX_ERROR; } set_cookie->hash = 1; ngx_str_set(&set_cookie->key, "Set-Cookie"); } set_cookie->value.len = ctx->sscf->cookie.len + sizeof("=") - 1 + ctx->sid.len + sizeof(";Domain=") - 1 + ctx->sscf->domain.len + sizeof(";Path=") - 1 + ctx->sscf->path.len; if (ctx->sscf->maxidle != NGX_CONF_UNSET) { set_cookie->value.len = set_cookie->value.len + ctx->s_lastseen.len + ctx->s_firstseen.len + 2; /* '|' and '|' */ } else { set_cookie->value.len = set_cookie->value.len + sizeof(";Max-Age=") - 1 + ctx->sscf->maxage.len; } p = ngx_pnalloc(r->pool, set_cookie->value.len); if (p == NULL) { return NGX_ERROR; } set_cookie->value.data = p; p = ngx_cpymem(p, ctx->sscf->cookie.data, ctx->sscf->cookie.len); *p++ = '='; p = ngx_cpymem(p, ctx->sid.data, ctx->sid.len); if (ctx->sscf->maxidle != NGX_CONF_UNSET) { *(p++) = NGX_HTTP_SESSION_STICKY_DELIMITER; p = ngx_cpymem(p, ctx->s_lastseen.data, ctx->s_lastseen.len); *(p++) = NGX_HTTP_SESSION_STICKY_DELIMITER; p = ngx_cpymem(p, ctx->s_firstseen.data, ctx->s_firstseen.len); } if (ctx->sscf->domain.len) { p = ngx_cpymem(p, ";Domain=", sizeof(";Domain=") - 1); p = ngx_cpymem(p, ctx->sscf->domain.data, ctx->sscf->domain.len); } if (ctx->sscf->path.len) { p = ngx_cpymem(p, ";Path=", sizeof(";Path=") - 1); p = ngx_cpymem(p, ctx->sscf->path.data, ctx->sscf->path.len); } if (ctx->sscf->maxidle == NGX_CONF_UNSET && ctx->sscf->maxage.len) { p = ngx_cpymem(p, ";Max-Age=", sizeof(";Max-Age=") - 1); p = ngx_cpymem(p, ctx->sscf->maxage.data, ctx->sscf->maxage.len); } set_cookie->value.len = p - set_cookie->value.data; return NGX_OK; }
static ngx_int_t ngx_http_session_sticky_header_filter(ngx_http_request_t *r) { ngx_int_t rc; ngx_uint_t i; ngx_list_part_t *part; ngx_table_elt_t *table; ngx_http_ss_ctx_t *ctx; ngx_http_ss_loc_conf_t *slcf; if (r->headers_out.status >= NGX_HTTP_BAD_REQUEST) { return ngx_http_ss_next_header_filter(r); } slcf = ngx_http_get_module_loc_conf(r, ngx_http_upstream_session_sticky_module); ctx = ngx_http_get_module_ctx(r, ngx_http_upstream_session_sticky_module); if (ctx == NULL || ctx->sscf == NULL || ctx->sscf->flag == 0) { return ngx_http_ss_next_header_filter(r); } if ((slcf->uscf == NGX_CONF_UNSET_PTR) && !(ctx->sscf->flag & NGX_HTTP_SESSION_STICKY_REWRITE)) { return ngx_http_ss_next_header_filter(r); } if (ctx->sscf->flag & (NGX_HTTP_SESSION_STICKY_PREFIX | NGX_HTTP_SESSION_STICKY_REWRITE)) { part = &r->headers_out.headers.part; while (part) { table = (ngx_table_elt_t *) part->elts; for (i = 0; i < part->nelts; i++) { if (table[i].key.len == (sizeof("set-cookie") - 1) && ngx_strncasecmp(table[i].key.data, (u_char *) "set-cookie", table[i].key.len) == 0) { if (ctx->sscf->flag & NGX_HTTP_SESSION_STICKY_REWRITE) { rc = ngx_http_session_sticky_rewrite(r, &table[i]); if (rc == NGX_AGAIN) { continue; } else if (rc == NGX_ERROR) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "session_sticky [rewrite]" "set-cookie failed"); } ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "session_sticky [rewrite] set-cookie:%V", &table[i].value); return ngx_http_ss_next_header_filter(r); } rc = ngx_http_session_sticky_prefix(r, &table[i]); if (rc == NGX_AGAIN) { continue; } else if (rc == NGX_ERROR) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "session_sticky [prefix]" "set-cookie failed"); } ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "session_sticky [prefix]" "set-cookie: %V", &table[i].value); return ngx_http_ss_next_header_filter(r); } } part = part->next; } } else if (ctx->sscf->flag & NGX_HTTP_SESSION_STICKY_INSERT) { ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "session_sticky [insert]"); rc = ngx_http_session_sticky_insert(r); if (rc != NGX_OK) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "session_sticky [insert] failed"); } } return ngx_http_ss_next_header_filter(r); }
ngx_int_t ngx_http_parse_multi_header_lines(ngx_array_t *headers, ngx_str_t *name, ngx_str_t *value) { syslog(LOG_INFO, "[%s:%s:%d]\n", __FILE__, __func__, __LINE__); ngx_uint_t i; u_char *start, *last, *end, ch; ngx_table_elt_t **h; h = headers->elts; for (i = 0; i < headers->nelts; i++) { ngx_log_debug4(NGX_LOG_DEBUG_HTTP, headers->pool->log, 0, "[%s:%d]parse header: \"%V: %V\"", __func__, __LINE__, &h[i]->key, &h[i]->value); if (name->len > h[i]->value.len) { continue; } start = h[i]->value.data; end = h[i]->value.data + h[i]->value.len; while (start < end) { if (ngx_strncasecmp(start, name->data, name->len) != 0) { goto skip; } for (start += name->len; start < end && *start == ' '; start++) { /* void */ } if (value == NULL) { if (start == end || *start == ',') { return i; } goto skip; } if (start == end || *start++ != '=') { /* the invalid header value */ goto skip; } while (start < end && *start == ' ') { start++; } for (last = start; last < end && *last != ';'; last++) { /* void */ } value->len = last - start; value->data = start; return i; skip: while (start < end) { ch = *start++; if (ch == ';' || ch == ',') { break; } } while (start < end && *start == ' ') { start++; } } } return NGX_DECLINED; }
static char * ngx_http_tfs_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { ngx_int_t add; ngx_str_t *value, s; ngx_url_t u; ngx_http_tfs_loc_conf_t *tlcf; ngx_http_tfs_main_conf_t *tmcf; ngx_http_core_loc_conf_t *clcf; value = cf->args->elts; clcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_core_module); tmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_tfs_module); tlcf = ngx_http_conf_get_module_loc_conf(cf, ngx_http_tfs_module); if (ngx_strncasecmp(value[1].data, (u_char *) "tfs://", 6) == 0) { add = 6; } else { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid URL prefix in tfs_pass"); return NGX_CONF_ERROR; } ngx_memzero(&u, sizeof(ngx_url_t)); u.url.len = value[1].len - add; u.url.data = value[1].data + add; u.uri_part = 1; u.no_resolve = 1; tlcf->upstream = ngx_http_tfs_upstream_add(cf, &u, NGX_HTTP_TFS_UPSTREAM_FIND); if (tlcf->upstream == NULL) { return NGX_CONF_ERROR; } clcf->handler = ngx_http_tfs_handler; if (clcf->name.data[clcf->name.len - 1] == '/') { clcf->auto_redirect = 1; } if (tlcf->upstream->enable_rcs) { if (tlcf->upstream->local_addr_text[0] == '\0') { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "in tfs module must assign net device name, " "use directives \"rcs_interface\" "); return NGX_CONF_ERROR; } tlcf->upstream->rcs_shm_zone = ngx_shared_memory_add(cf, &tlcf->upstream->rcs_zone_name, 0, &ngx_http_tfs_module); if (tlcf->upstream->rcs_shm_zone == NULL) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "in tfs module must assign rcs shm zone," "use directives \"rcs_zone\" "); return NGX_CONF_ERROR; } } if (tmcf->local_block_cache_ctx != NULL) { s.data = (u_char *) NGX_HTTP_TFS_BLOCK_CACHE_ZONE_NAME; s.len = sizeof(NGX_HTTP_TFS_BLOCK_CACHE_ZONE_NAME) - 1; tmcf->block_cache_shm_zone = ngx_shared_memory_add(cf, &s, 0, &ngx_http_tfs_module); if (tmcf->block_cache_shm_zone == NULL) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "in tfs module must assign block cache shm zone," "use directives \"tfs_block_cache_zone\" "); return NGX_CONF_ERROR; } } tlcf->upstream->used = 1; return NGX_CONF_OK; }
int ngx_http_lua_ffi_get_resp_header(ngx_http_request_t *r, const u_char *key, size_t key_len, u_char *key_buf, ngx_http_lua_ffi_str_t *values, int max_nvalues) { int found; u_char c, *p; ngx_uint_t i; ngx_table_elt_t *h; ngx_list_part_t *part; ngx_http_lua_loc_conf_t *llcf; if (r->connection->fd == (ngx_socket_t) -1) { return NGX_HTTP_LUA_FFI_BAD_CONTEXT; } llcf = ngx_http_get_module_loc_conf(r, ngx_http_lua_module); if (llcf->transform_underscores_in_resp_headers && memchr(key, '_', key_len) != NULL) { for (i = 0; i < key_len; i++) { c = key[i]; if (c == '_') { c = '-'; } key_buf[i] = c; } } else { key_buf = (u_char *) key; } switch (key_len) { case 14: if (r->headers_out.content_length == NULL && r->headers_out.content_length_n >= 0 && ngx_strncasecmp(key_buf, (u_char *) "Content-Length", 14) == 0) { p = ngx_palloc(r->pool, NGX_OFF_T_LEN); if (p == NULL) { return NGX_ERROR; } values[0].data = p; values[0].len = (int) (ngx_snprintf(p, NGX_OFF_T_LEN, "%O", r->headers_out.content_length_n) - p); return 1; } break; case 12: if (r->headers_out.content_type.len && ngx_strncasecmp(key_buf, (u_char *) "Content-Type", 12) == 0) { values[0].data = r->headers_out.content_type.data; values[0].len = r->headers_out.content_type.len; return 1; } break; default: break; } dd("not a built-in output header"); #if 1 if (r->headers_out.location && r->headers_out.location->value.len && r->headers_out.location->value.data[0] == '/') { /* XXX ngx_http_core_find_config_phase, for example, * may not initialize the "key" and "hash" fields * for a nasty optimization purpose, and * we have to work-around it here */ r->headers_out.location->hash = ngx_http_lua_location_hash; ngx_str_set(&r->headers_out.location->key, "Location"); } #endif found = 0; part = &r->headers_out.headers.part; h = part->elts; for (i = 0; /* void */; i++) { if (i >= part->nelts) { if (part->next == NULL) { break; } part = part->next; h = part->elts; i = 0; } if (h[i].hash == 0) { continue; } dd("checking (%d) \"%.*s\"", (int) h[i].key.len, (int) h[i].key.len, h[i].key.data); if (h[i].key.len == key_len && ngx_strncasecmp(key_buf, h[i].key.data, key_len) == 0) { values[found].data = h[i].value.data; values[found].len = (int) h[i].value.len; if (++found >= max_nvalues) { break; } } } return found; }
static ngx_int_t ngx_http_set_header_helper(ngx_http_request_t *r, ngx_http_lua_header_val_t *hv, ngx_str_t *value, ngx_table_elt_t **output_header, unsigned no_create) { ngx_table_elt_t *h; ngx_list_part_t *part; ngx_uint_t i; unsigned matched = 0; if (hv->no_override) { goto new_header; } part = &r->headers_out.headers.part; h = part->elts; for (i = 0; /* void */; i++) { if (i >= part->nelts) { if (part->next == NULL) { break; } part = part->next; h = part->elts; i = 0; } if (h[i].key.len == hv->key.len && ngx_strncasecmp(hv->key.data, h[i].key.data, h[i].key.len) == 0) { dd("found out header %.*s", (int) h[i].key.len, h[i].key.data); if (value->len == 0 || matched) { dd("clearing normal header for %.*s", (int) hv->key.len, hv->key.data); h[i].value.len = 0; h[i].hash = 0; } else { dd("setting header to value %.*s", (int) value->len, value->data); h[i].value = *value; h[i].hash = 1; } if (output_header) { *output_header = &h[i]; } /* return NGX_OK; */ matched = 1; } } if (matched){ return NGX_OK; } if (no_create && value->len == 0) { return NGX_OK; } new_header: /* XXX we still need to create header slot even if the value * is empty because some builtin headers like Last-Modified * relies on this to get cleared */ h = ngx_list_push(&r->headers_out.headers); if (h == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } if (value->len == 0) { h->hash = 0; } else { h->hash = hv->hash; } h->key = hv->key; h->value = *value; h->lowcase_key = ngx_pnalloc(r->pool, h->key.len); if (h->lowcase_key == NULL) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } ngx_strlow(h->lowcase_key, h->key.data, h->key.len); if (output_header) { *output_header = h; } return NGX_OK; }