Inspect Cache-Control header, fixes #11
1 parent 9e38566 commit c3d0cfd4a25b2adcb8fe78802f626ce3c722775f
@Andreas Jaggi Andreas Jaggi authored on 24 Sep 2011
x-way committed on 24 Sep 2011
Showing 2 changed files
View
2
■■■
README
Expires, Content-Language, Content-Encoding, Allow, Host,
Accept, Connection, Content-Range, User-Agent, Upgrade, Via,
From, Pragma, Content-Type, Content-MD5, Authorization, Expect,
Proxy-Authorization, Warning, Trailer, Transfer-Encoding, TE,
Referer, Content-Location
Referer, Content-Location, Cache-Control
 
Report Bugs
Create a ticket on the issue tracking interface of GitHub:
http://github.com/x-way/ngx_http_header_inspect/issues
View
107
ngx_http_header_inspect.c
static ngx_int_t ngx_header_inspect_warning_header(ngx_header_inspect_loc_conf_t *conf, ngx_log_t *log, ngx_str_t value);
static ngx_int_t ngx_header_inspect_trailer_header(ngx_header_inspect_loc_conf_t *conf, ngx_log_t *log, ngx_str_t value);
static ngx_int_t ngx_header_inspect_transferencoding_header(char* header, ngx_header_inspect_loc_conf_t *conf, ngx_log_t *log, ngx_str_t value);
static ngx_int_t ngx_header_inspect_referer_header(char* header, ngx_header_inspect_loc_conf_t *conf, ngx_log_t *log, ngx_str_t value);
static ngx_int_t ngx_header_inspect_cachecontrol_header(ngx_header_inspect_loc_conf_t *conf, ngx_log_t *log, ngx_str_t value);
static ngx_int_t ngx_header_inspect_process_request(ngx_http_request_t *r);
 
static void *ngx_header_inspect_create_conf(ngx_conf_t *cf);
static char *ngx_header_inspect_merge_conf(ngx_conf_t *cf, void *parent, void *child);
 
return rc;
}
 
static ngx_int_t ngx_header_inspect_parse_cache_directive(u_char *data, ngx_uint_t maxlen, ngx_uint_t *len) {
ngx_uint_t i = 0;
if ( (maxlen >= 8) && (ngx_strncmp("no-cache", data, 8) == 0) ) {
*len = 8;
return NGX_OK;
}
if ( (maxlen >= 8) && (ngx_strncmp("no-store", data, 8) == 0) ) {
*len = 8;
return NGX_OK;
}
if ( (maxlen >= 12) && (ngx_strncmp("no-transform", data, 12) == 0) ) {
*len = 12;
return NGX_OK;
}
if ( (maxlen >= 14) && (ngx_strncmp("only-if-cached", data, 14) == 0) ) {
*len = 14;
return NGX_OK;
}
if ( (maxlen >= 9) && (ngx_strncmp("max-stale", data, 9) == 0) ) {
*len = 9;
if ( maxlen >= 11 ) {
if ( (data[9] == '=') && (data[10] >= '0') && (data[10] <= '9') ) {
i = 11;
while ( (i <= maxlen) && (data[i] >= '0') && (data[i] <= '9') ) {
i++;
}
*len = i;
}
}
return NGX_OK;
}
if ( (maxlen >= 9) && (ngx_strncmp("max-age=", data, 8) == 0) && (data[8] >= '0') && (data[8] <= '9') ) {
i = 9;
while ( (i < maxlen) && (data[i] >= '0') &&(data[i] <= '9') ) {
i++;
}
*len = i;
return NGX_OK;
}
if ( (maxlen >= 11) && (ngx_strncmp("min-fresh=", data, 10) == 0) && (data[10] >= '0') && (data[10] <= '9') ) {
i = 11;
while ( (i < maxlen) && (data[i] >= '0') &&(data[i] <= '9') ) {
i++;
}
*len = i;
return NGX_OK;
}
 
return NGX_ERROR;
}
 
static ngx_int_t ngx_header_inspect_cachecontrol_header(ngx_header_inspect_loc_conf_t *conf, ngx_log_t *log, ngx_str_t value) {
ngx_int_t rc = NGX_AGAIN;
ngx_uint_t i = 0;
ngx_uint_t v;
 
if (value.len < 1) {
if ( conf->log ) {
ngx_log_error(NGX_LOG_ALERT, log, 0, "header_inspect: Cache-Control header \"%s\" too short", value.data);
}
return NGX_ERROR;
}
 
while ( i < value.len ) {
if ( ngx_header_inspect_parse_cache_directive(&(value.data[i]), value.len-i, &v) != NGX_OK ) {
if ( conf->log ) {
ngx_log_error(NGX_LOG_ALERT, log, 0, "header_inspect: invalid cache-directive at position %d in Cache-Control header \"%s\"", i, value.data);
}
rc = NGX_ERROR;
break;
}
i += v;
if ((value.data[i] == ' ') && (i < value.len)) {
i++;
}
if (i == value.len) {
rc = NGX_OK;
break;
}
if (value.data[i] != ',') {
if ( conf->log ) {
ngx_log_error(NGX_LOG_ALERT, log, 0, "header_inspect: illegal char at position %d in Cache-Control header \"%s\"", i, value.data);
}
rc = NGX_ERROR;
break;
}
i++;
if ((value.data[i] == ' ') && (i < value.len)) {
i++;
}
}
if ( rc == NGX_AGAIN ) {
if ( conf->log ) {
ngx_log_error(NGX_LOG_ALERT, log, 0, "header_inspect: unexpected end of Cache-Control header \"%s\"", value.data);
}
rc = NGX_ERROR;
}
 
return rc;
}
 
static ngx_int_t ngx_header_inspect_referer_header(char* header, ngx_header_inspect_loc_conf_t *conf, ngx_log_t *log, ngx_str_t value) {
enum referer_header_states { RS_START, RS_SCHEME, RS_COLON, RS_SLASH1, RS_SLASH2, RS_HOST, RS_BR1, RS_IP6, RS_BR2, RS_COLON2, RS_PORT, RS_PATH } state;
ngx_uint_t i;
ngx_int_t rc = NGX_OK;
rc = ngx_header_inspect_referer_header("Content-Location", conf, r->connection->log, h[i].value);
if ((rc != NGX_OK) && conf->block) {
return NGX_HTTP_BAD_REQUEST;
}
} else if ((h[i].key.len == 13) && (ngx_strcmp("Cache-Control", h[i].key.data) == 0) ) {
rc = ngx_header_inspect_cachecontrol_header(conf, r->connection->log, h[i].value);
if ((rc != NGX_OK) && conf->block) {
return NGX_HTTP_BAD_REQUEST;
}
} else {
/* TODO: support for other headers */
if (conf->log_uninspected) {
ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0, "header_inspect: uninspected header \"%s: %s\"", h[i].key.data, h[i].value.data);