#include #include #include static ngx_http_output_header_filter_pt ngx_http_next_header_filter; static ngx_int_t ngx_http_key_header_filter(ngx_http_request_t*); static ngx_int_t ngx_http_key_header_init(ngx_conf_t*); static void* ngx_http_key_header_create_conf(ngx_conf_t*); static char* ngx_http_key_header_merge_loc_conf(ngx_conf_t*, void* parent, void* child); typedef struct { ngx_flag_t enabled; } ngx_http_key_header_loc_conf_t; static ngx_command_t ngx_http_key_header_filter_commands[] = { { ngx_string("send_cache_key"), NGX_HTTP_MAIN_CONF | NGX_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF | NGX_CONF_FLAG, ngx_conf_set_flag_slot, NGX_HTTP_LOC_CONF_OFFSET, offsetof(ngx_http_key_header_loc_conf_t, enabled), NULL }, ngx_null_command }; static ngx_http_module_t ngx_http_key_header_filter_module_ctx = { NULL, /* Pre config */ ngx_http_key_header_init, /* Post config */ NULL, /* Create main config */ NULL, /* Init main config */ NULL, /* Create server config */ NULL, /* Merge server config */ ngx_http_key_header_create_conf, /* Create loc config */ ngx_http_key_header_merge_loc_conf /* Merge loc config */ }; static ngx_int_t ngx_http_key_header_init(ngx_conf_t*) { ngx_http_next_header_filter = ngx_http_top_header_filter; ngx_http_top_header_filter = ngx_http_key_header_filter; return NGX_OK; } static void* ngx_http_key_header_create_conf(ngx_conf_t *cf) { ngx_http_key_header_loc_conf_t *conf; conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_key_header_loc_conf_t)); if(conf == NULL) { return NGX_CONF_ERROR; } conf->enabled = NGX_CONF_UNSET; return conf; } static char* ngx_http_key_header_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) { ngx_http_key_header_loc_conf_t *prev = parent; ngx_http_key_header_loc_conf_t *conf = child; ngx_conf_merge_value(conf->enabled, prev->enabled, 0); return NGX_CONF_OK; } ngx_module_t ngx_http_key_header_module = { NGX_MODULE_V1, &ngx_http_key_header_filter_module_ctx, /* module context */ ngx_http_key_header_filter_commands, /* module directives */ NGX_HTTP_MODULE, /* module type */ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NGX_MODULE_V1_PADDING }; static ngx_int_t ngx_http_key_header_filter(ngx_http_request_t *r ) { if(r->loc_conf != NULL) { ngx_http_key_header_loc_conf_t *conf = ngx_http_get_module_loc_conf(r, ngx_http_key_header_module); if(conf->enabled) { ngx_table_elt_t *h; h = ngx_list_push(&r->headers_out.headers); if(h == NULL) { return NGX_ERROR; } u_char hexKey[2 * NGX_HTTP_CACHE_KEY_LEN + 1]; ngx_hex_dump(hexKey, r->cache->key, NGX_HTTP_CACHE_KEY_LEN); h->hash = 1; ngx_str_set(&h->key, "X-Cache-Key"); ngx_str_set(&h->value, hexKey); } } return ngx_http_next_header_filter(r); }