void ngx_http_file_cache_create_key(ngx_http_request_t *r) { size_t len; ngx_str_t *key; ngx_uint_t i; ngx_md5_t md5; ngx_http_cache_t *c; c = r->cache; len = 0; ngx_crc32_init(c->crc32); ngx_md5_init(&md5); key = c->keys.elts; for (i = 0; i < c->keys.nelts; i++) { ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http cache key: \"%V\"", &key[i]); len += key[i].len; ngx_crc32_update(&c->crc32, key[i].data, key[i].len); ngx_md5_update(&md5, key[i].data, key[i].len); } c->header_start = sizeof(ngx_http_file_cache_header_t) + sizeof(ngx_http_file_cache_key) + len + 1; ngx_crc32_final(c->crc32); ngx_md5_final(c->key, &md5); }
void ngx_http_file_cache_create_key(ngx_http_request_t *r) { size_t len; ngx_str_t *key; ngx_uint_t i; ngx_md5_t md5; ngx_http_cache_t *c; c = r->cache; len = 0; ngx_crc32_init(c->crc32); //Here,we do the crc get a key! ngx_md5_init(&md5); //Here,we get the md5 key = c->keys.elts; //Means how much elements we used to caculate the key! for (i = 0; i < c->keys.nelts; i++) { ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http cache key: \"%V\"", &key[i]); len += key[i].len; ngx_crc32_update(&c->crc32, key[i].data, key[i].len); //do the crc32 ngx_md5_update(&md5, key[i].data, key[i].len); //do the md5 } c->header_start = sizeof(ngx_http_file_cache_header_t) + sizeof(ngx_http_file_cache_key) + len + 1; ngx_crc32_final(c->crc32); ngx_md5_final(c->key, &md5); }
static ngx_int_t ngx_http_limit_req2_handler(ngx_http_request_t *r) { size_t n, total_len; uint32_t hash; ngx_int_t rc; ngx_msec_t delay_time; ngx_uint_t excess, delay_excess, delay_postion, nodelay, i; ngx_time_t *tp; ngx_rbtree_node_t *node; ngx_http_limit_req2_t *limit_req2; ngx_http_limit_req2_ctx_t *ctx; ngx_http_limit_req2_node_t *lr; ngx_http_limit_req2_conf_t *lrcf; delay_excess = 0; excess = 0; delay_postion = 0; nodelay = 0; ctx = NULL; rc = NGX_DECLINED; if (r->main->limit_req_set) { return NGX_DECLINED; } lrcf = ngx_http_get_module_loc_conf(r, ngx_http_limit_req2_module); if (lrcf->rules == NULL) { return NGX_DECLINED; } if (!lrcf->enable) { return NGX_DECLINED; } /* filter whitelist */ if (ngx_http_limit_req2_ip_filter(r, lrcf) == NGX_OK) { return NGX_DECLINED; } /* to match limit_req2 rule*/ limit_req2 = lrcf->rules->elts; for (i = 0; i < lrcf->rules->nelts; i++) { ctx = limit_req2[i].shm_zone->data; ngx_crc32_init(hash); total_len = 0; total_len = ngx_http_limit_req2_copy_variables(r, &hash, ctx, NULL); if (total_len == 0) { continue; } ngx_crc32_final(hash); ngx_shmtx_lock(&ctx->shpool->mutex); ngx_http_limit_req2_expire(r, ctx, 1); rc = ngx_http_limit_req2_lookup(r, &limit_req2[i], hash, &excess); ngx_log_debug5(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "limit_req2 module: %i %ui.%03ui " "hash is %ui total_len is %i", rc, excess / 1000, excess % 1000, hash, total_len); /* first limit_req2 */ if (rc == NGX_DECLINED) { n = offsetof(ngx_rbtree_node_t, color) + offsetof(ngx_http_limit_req2_node_t, data) + total_len; node = ngx_slab_alloc_locked(ctx->shpool, n); if (node == NULL) { ngx_http_limit_req2_expire(r, ctx, 0); node = ngx_slab_alloc_locked(ctx->shpool, n); if (node == NULL) { ngx_shmtx_unlock(&ctx->shpool->mutex); return NGX_HTTP_SERVICE_UNAVAILABLE; } } lr = (ngx_http_limit_req2_node_t *) &node->color; node->key = hash; lr->len = (u_char) total_len; tp = ngx_timeofday(); lr->last = (ngx_msec_t) (tp->sec * 1000 + tp->msec); lr->excess = 0; ngx_http_limit_req2_copy_variables(r, &hash, ctx, lr); ngx_queue_insert_head(&ctx->sh->queue, &lr->queue); ngx_rbtree_insert(&ctx->sh->rbtree, node); ngx_shmtx_unlock(&ctx->shpool->mutex); continue; } ngx_shmtx_unlock(&ctx->shpool->mutex); if (rc == NGX_BUSY || rc == NGX_ERROR) { break; } /* NGX_AGAIN or NGX_OK */ if (delay_excess < excess) { delay_excess = excess; nodelay = limit_req2[i].nodelay; delay_postion = i; } } r->main->limit_req_set = 1; if (rc == NGX_BUSY || rc == NGX_ERROR) { if (rc == NGX_BUSY) { ngx_log_error(lrcf->limit_log_level, r->connection->log, 0, "limiting requests, excess: %ui.%03ui by zone \"%V\"", excess / 1000, excess % 1000, &limit_req2[i].shm_zone->shm.name); } if (rc == NGX_ERROR || limit_req2[i].forbid_action.len == 0) { return NGX_HTTP_SERVICE_UNAVAILABLE; } else if (limit_req2[i].forbid_action.data[0] == '@') { ngx_log_error(lrcf->limit_log_level, r->connection->log, 0, "limiting requests, forbid_action is %V", &limit_req2[i].forbid_action); (void) ngx_http_named_location(r, &limit_req2[i].forbid_action); } else { ngx_log_error(lrcf->limit_log_level, r->connection->log, 0, "limiting requests, forbid_action is %V", &limit_req2[i].forbid_action); (void) ngx_http_internal_redirect(r, &limit_req2[i].forbid_action, &r->args); } ngx_http_finalize_request(r, NGX_DONE); return NGX_DONE; } /* rc = NGX_AGAIN */ if (delay_excess != 0) { if (nodelay) { return NGX_DECLINED; } delay_time = (ngx_msec_t) delay_excess * 1000 / ctx->rate; ngx_log_error(lrcf->delay_log_level, r->connection->log, 0, "delaying request," "excess: %ui.%03ui, by zone \"%V\", delay \"%ui\" s", delay_excess / 1000, delay_excess % 1000, &limit_req2[delay_postion].shm_zone->shm.name, delay_time); if (ngx_handle_read_event(r->connection->read, 0) != NGX_OK) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } r->read_event_handler = ngx_http_test_reading; r->write_event_handler = ngx_http_limit_req2_delay; ngx_add_timer(r->connection->write, delay_time); return NGX_AGAIN; } /* rc == NGX_OK or rc == NGX_DECLINED */ return NGX_DECLINED; }
static ngx_int_t ngx_http_zip_send_piece(ngx_http_request_t *r, ngx_http_zip_ctx_t *ctx, ngx_http_zip_piece_t *piece, ngx_http_zip_range_t *range) { ngx_chain_t *link; ngx_http_request_t *sr; ngx_http_zip_sr_ctx_t *sr_ctx; ngx_int_t rc; if (piece->type == zip_header_piece) { if ((link = ngx_http_zip_file_header_chain_link(r, ctx, piece, range)) == NULL) return NGX_ERROR; return ngx_http_next_body_filter(r, link); } // need to check if the context has something going on.... if (piece->type == zip_file_piece) { ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "mod_zip: subrequest for \"%V?%V\"", &piece->file->uri, &piece->file->args); if (ctx->wait) { ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "mod_zip: have a wait context for \"%V?%V\"", &ctx->wait->uri, &ctx->wait->args); if (ctx->wait->done) { ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "mod_zip: wait \"%V?%V\" done", &ctx->wait->uri, &ctx->wait->args); ctx->wait = NULL; } else { ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "mod_zip: wait NOT DONE \"%V?%V\"", &ctx->wait->uri, &ctx->wait->args); return NGX_AGAIN; } } rc = ngx_http_subrequest(r, &piece->file->uri, &piece->file->args, &sr, NULL, NGX_HTTP_SUBREQUEST_WAITED); ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "mod_zip: subrequest for \"%V?%V\" result %d, allocating some mem on main request's pool", &piece->file->uri, &piece->file->args, rc); if (rc == NGX_ERROR) { return NGX_ERROR; } if ((sr_ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_zip_ctx_t))) == NULL) return NGX_ERROR; sr_ctx->requesting_file = piece->file; sr_ctx->subrequest_pos = piece->range.start; sr_ctx->range = range; ngx_http_set_ctx(sr, sr_ctx, ngx_http_zip_module); ngx_log_debug3(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "mod_zip: subrequest for \"%V?%V\" result %d", &piece->file->uri, &piece->file->args, rc); if (ctx->wait == NULL) { ctx->wait = sr; return NGX_AGAIN; // must be NGX_AGAIN } else { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "mod_zip : only one subrequest may be waited at the same time; "); } return NGX_ERROR; } if (piece->type == zip_trailer_piece) { if (piece->file->missing_crc32) // should always be true, but if we somehow needed trailer piece - go on ngx_crc32_final(piece->file->crc32); if ((link = ngx_http_zip_data_descriptor_chain_link(r, piece, range)) == NULL) { ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "mod_zip: data descriptor failed"); return NGX_ERROR; } return ngx_http_next_body_filter(r, link); } if (piece->type == zip_central_directory_piece) { if ((link = ngx_http_zip_central_directory_chain_link(r, ctx, piece, range)) == NULL) { ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "mod_zip: CD piece failed"); return NGX_ERROR; } return ngx_http_next_body_filter(r, link); } return NGX_ERROR; }
ngx_int_t ngx_selective_cache_purge_file_cache_lookup_on_disk(ngx_http_request_t *r, ngx_http_file_cache_t *cache, ngx_str_t *cache_key, u_char *md5_key) { #if NGX_HTTP_CACHE ngx_http_cache_t *c; ngx_str_t *key; ngx_int_t rc; c = r->cache; if ((c = ngx_pcalloc(r->pool, sizeof(ngx_http_cache_t))) == NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "ngx_selective_cache_purge: could not alloc memory to ngx_http_cache_t structure"); return NGX_ERROR; } ngx_memzero(c, sizeof(ngx_http_cache_t)); rc = ngx_array_init(&c->keys, r->pool, 1, sizeof(ngx_str_t)); if (rc != NGX_OK) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "ngx_selective_cache_purge: could not alloc memory to keys array"); return NGX_ERROR; } key = ngx_array_push(&c->keys); if (key == NULL) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "ngx_selective_cache_purge: could not alloc memory to key item"); return NGX_ERROR; } key->data = cache_key->data; key->len = cache_key->len; r->cache = c; c->body_start = ngx_pagesize; c->file_cache = cache; c->file.log = r->connection->log; ngx_crc32_init(c->crc32); ngx_crc32_update(&c->crc32, cache_key->data, cache_key->len); ngx_crc32_final(c->crc32); c->header_start = sizeof(ngx_http_file_cache_header_t) + NGX_HTTP_FILE_CACHE_KEY_LEN + cache_key->len + 1; ngx_memcpy(c->key, md5_key, NGX_HTTP_CACHE_KEY_LEN); switch (ngx_http_file_cache_open(r)) { case NGX_OK: case NGX_HTTP_CACHE_STALE: case NGX_HTTP_CACHE_UPDATING: return NGX_OK; break; case NGX_DECLINED: return NGX_DECLINED; # if (NGX_HAVE_FILE_AIO) case NGX_AGAIN: return NGX_AGAIN; # endif default: return NGX_ERROR; } #else return NGX_OK; #endif }
static ngx_int_t ngx_http_limit_req_handler(ngx_http_request_t *r) { size_t len; uint32_t hash; ngx_int_t rc; ngx_uint_t n, excess; ngx_msec_t delay; ngx_http_limit_req_ctx_t *ctx; ngx_http_limit_req_conf_t *lrcf; ngx_http_limit_req_limit_t *limit, *limits; if (r->main->limit_req_set) { return NGX_DECLINED; } lrcf = ngx_http_get_module_loc_conf(r, ngx_http_limit_req_module); limits = lrcf->limits.elts; /* filter whitelist */ if (ngx_http_limit_req_ip_filter(r, lrcf) == NGX_OK) { return NGX_DECLINED; } excess = 0; rc = NGX_DECLINED; #if (NGX_SUPPRESS_WARN) limit = NULL; #endif for (n = 0; n < lrcf->limits.nelts; n++) { limit = &limits[n]; ctx = limit->shm_zone->data; ngx_crc32_init(hash); len = ngx_http_limit_req_copy_variables(r, &hash, ctx, NULL); if (len == 0) { continue; } ngx_crc32_final(hash); ngx_shmtx_lock(&ctx->shpool->mutex); rc = ngx_http_limit_req_lookup(r, limit, hash, len, &excess, (n == lrcf->limits.nelts - 1)); ngx_shmtx_unlock(&ctx->shpool->mutex); ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "limits[%ui]: %i %ui.%03ui", n, rc, excess / 1000, excess % 1000); if (rc != NGX_AGAIN) { break; } } if (rc == NGX_DECLINED) { return NGX_DECLINED; } r->main->limit_req_set = 1; if (rc == NGX_BUSY || rc == NGX_ERROR) { if (rc == NGX_BUSY) { ngx_log_error(lrcf->limit_log_level, r->connection->log, 0, "limiting requests, excess: %ui.%03ui by zone \"%V\"", excess / 1000, excess % 1000, &limit->shm_zone->shm.name); } while (n--) { ctx = limits[n].shm_zone->data; if (ctx->node == NULL) { continue; } ngx_shmtx_lock(&ctx->shpool->mutex); ctx->node->count--; ngx_shmtx_unlock(&ctx->shpool->mutex); ctx->node = NULL; } if (rc == NGX_ERROR || limit->forbid_action.len == 0) { return lrcf->status_code; } else if (limit->forbid_action.data[0] == '@') { ngx_log_error(lrcf->limit_log_level, r->connection->log, 0, "limiting requests, forbid_action is %V", &limit->forbid_action); (void) ngx_http_named_location(r, &limit->forbid_action); } else { ngx_log_error(lrcf->limit_log_level, r->connection->log, 0, "limiting requests, forbid_action is %V", &limit->forbid_action); (void) ngx_http_internal_redirect(r, &limit->forbid_action, &r->args); } ngx_http_finalize_request(r, NGX_DONE); return NGX_DONE; } /* rc == NGX_AGAIN || rc == NGX_OK */ if (rc == NGX_AGAIN) { excess = 0; } delay = ngx_http_limit_req_account(limits, n, &excess, &limit); if (!delay) { return NGX_DECLINED; } ngx_log_error(lrcf->delay_log_level, r->connection->log, 0, "delaying request, excess: %ui.%03ui, by zone \"%V\"", excess / 1000, excess % 1000, &limit->shm_zone->shm.name); if (ngx_handle_read_event(r->connection->read, 0) != NGX_OK) { return NGX_HTTP_INTERNAL_SERVER_ERROR; } r->read_event_handler = ngx_http_test_reading; r->write_event_handler = ngx_http_limit_req_delay; ngx_add_timer(r->connection->write, delay); return NGX_AGAIN; }