changeset 2138:fb3b084e7d42

test Content-Type via hash: *) ngx_http_test_content_type() *) ngx_http_types_slot() *) ngx_http_merge_types()
author Igor Sysoev <igor@sysoev.ru>
date Mon, 04 Aug 2008 11:29:09 +0000
parents 76d5af541412
children dad4423ef56a
files src/http/ngx_http.c src/http/ngx_http.h src/http/ngx_http_core_module.c src/http/ngx_http_core_module.h src/http/ngx_http_request.h
diffstat 5 files changed, 182 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/src/http/ngx_http.c
+++ b/src/http/ngx_http.c
@@ -1687,3 +1687,135 @@ ngx_http_init_listening(ngx_conf_t *cf, 
 
     return NGX_OK;
 }
+
+
+char *
+ngx_http_types_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
+{
+    char  *p = conf;
+
+    ngx_array_t     **types;
+    ngx_str_t        *value, *default_type;
+    ngx_uint_t        i, n, hash;
+    ngx_hash_key_t   *type;
+
+    types = (ngx_array_t **) (p + cmd->offset);
+
+    default_type = cmd->post;
+
+    if (*types == NULL) {
+        *types = ngx_array_create(cf->temp_pool, 1, sizeof(ngx_hash_key_t));
+        if (*types == NULL) {
+            return NGX_CONF_ERROR;
+        }
+
+        if (default_type) {
+            type = ngx_array_push(*types);
+            if (type == NULL) {
+                return NGX_CONF_ERROR;
+            }
+
+            type->key = *default_type;
+            type->key_hash = ngx_hash_key(default_type->data,
+                                          default_type->len);
+            type->value = (void *) 4;
+        }
+    }
+
+    value = cf->args->elts;
+
+    for (i = 1; i < cf->args->nelts; i++) {
+
+        hash = ngx_hash_strlow(value[i].data, value[i].data, value[i].len);
+        value[i].data[value[i].len] = '\0';
+
+        type = (*types)->elts;
+        for (n = 0; n < (*types)->nelts; n++) {
+
+            if (ngx_strcmp(value[i].data, type[n].key.data) == 0) {
+                ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
+                                   "duplicate MIME type \"%V\"", &value[i]);
+                continue;
+            }
+        }
+
+        type = ngx_array_push(*types);
+        if (type == NULL) {
+            return NGX_CONF_ERROR;
+        }
+
+        type->key = value[i];
+        type->key_hash = hash;
+        type->value = (void *) 4;
+    }
+
+    return NGX_CONF_OK;
+}
+
+
+char *
+ngx_http_merge_types(ngx_conf_t *cf, ngx_array_t *keys, ngx_hash_t *types_hash,
+    ngx_array_t *prev_keys, ngx_hash_t *prev_types_hash, 
+    ngx_str_t *default_types)
+{
+    ngx_hash_init_t  hash;
+
+    if (keys == NULL) {
+
+        if (prev_keys) {
+            *types_hash = *prev_types_hash;
+            return NGX_CONF_OK;
+        }
+
+        if (ngx_http_set_default_types(cf, &keys, default_types)
+            != NGX_CONF_OK)
+        {
+            return NGX_CONF_ERROR;
+        }
+    }
+
+    hash.hash = types_hash;
+    hash.key = NULL;
+    hash.max_size = 2048;
+    hash.bucket_size = 64;
+    hash.name = "test_types_hash";
+    hash.pool = cf->pool;
+    hash.temp_pool = NULL;
+
+    if (ngx_hash_init(&hash, keys->elts, keys->nelts) != NGX_OK) {
+        return NGX_CONF_ERROR;
+    }
+
+    return NGX_CONF_OK;
+
+}
+
+
+char *
+ngx_http_set_default_types(ngx_conf_t *cf, ngx_array_t **types,
+    ngx_str_t *default_type)
+{
+    ngx_hash_key_t  *type;
+
+    *types = ngx_array_create(cf->temp_pool, 1, sizeof(ngx_hash_key_t));
+    if (*types == NULL) {
+        return NGX_CONF_ERROR;
+    }
+
+    while (default_type->len) {
+
+        type = ngx_array_push(*types);
+        if (type == NULL) {
+            return NGX_CONF_ERROR;
+        }
+
+        type->key = *default_type;
+        type->key_hash = ngx_hash_key(default_type->data,
+                                      default_type->len);
+        type->value = (void *) 4;
+
+        default_type++;
+    }
+
+    return NGX_CONF_OK;
+}
--- a/src/http/ngx_http.h
+++ b/src/http/ngx_http.h
@@ -107,6 +107,14 @@ ngx_int_t ngx_http_discard_request_body(
 void ngx_http_block_reading(ngx_http_request_t *r);
 
 
+char *ngx_http_types_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
+char *ngx_http_merge_types(ngx_conf_t *cf, ngx_array_t *keys,
+    ngx_hash_t *types_hash, ngx_array_t *prev_keys, ngx_hash_t *prev_types_hash,
+    ngx_str_t *default_types);
+char *ngx_http_set_default_types(ngx_conf_t *cf, ngx_array_t **types,
+    ngx_str_t *default_type);
+
+
 extern ngx_module_t  ngx_http_module;
 
 
--- a/src/http/ngx_http_core_module.c
+++ b/src/http/ngx_http_core_module.c
@@ -1302,6 +1302,44 @@ ngx_http_core_send_continue(ngx_http_req
 }
 
 
+void *
+ngx_http_test_content_type(ngx_http_request_t *r, ngx_hash_t *types_hash)
+{
+    u_char       c, *p;
+    ngx_uint_t   i, hash;
+
+    if (r->headers_out.content_type.len == 0) {
+        return NULL;
+    }
+
+    if (r->headers_out.content_type_lowcase == NULL) {
+
+        p = ngx_pnalloc(r->pool, r->headers_out.content_type_len);
+
+        if (p == NULL) {
+            return NULL;
+        }
+
+        r->headers_out.content_type_lowcase = p;
+
+        hash = 0;
+
+        for (i = 0; i < r->headers_out.content_type_len; i++) {
+            c = ngx_tolower(r->headers_out.content_type.data[i]);
+            hash = ngx_hash(hash, c);
+            *p++ = c;
+        }
+
+        r->headers_out.content_type_hash = hash;
+    }
+
+    return ngx_hash_find(types_hash,
+                         r->headers_out.content_type_hash,
+                         r->headers_out.content_type_lowcase,
+                         r->headers_out.content_type_len);
+}
+
+
 ngx_int_t
 ngx_http_set_content_type(ngx_http_request_t *r)
 {
--- a/src/http/ngx_http_core_module.h
+++ b/src/http/ngx_http_core_module.h
@@ -373,6 +373,8 @@ ngx_int_t ngx_http_core_post_access_phas
 ngx_int_t ngx_http_core_content_phase(ngx_http_request_t *r,
     ngx_http_phase_handler_t *ph);
 
+
+void *ngx_http_test_content_type(ngx_http_request_t *r, ngx_hash_t *types_hash);
 ngx_int_t ngx_http_set_content_type(ngx_http_request_t *r);
 ngx_int_t ngx_http_set_exten(ngx_http_request_t *r);
 u_char *ngx_http_map_uri_to_path(ngx_http_request_t *r, ngx_str_t *name,
--- a/src/http/ngx_http_request.h
+++ b/src/http/ngx_http_request.h
@@ -244,6 +244,8 @@ typedef struct {
     size_t                            content_type_len;
     ngx_str_t                         content_type;
     ngx_str_t                         charset;
+    u_char                           *content_type_lowcase;
+    ngx_uint_t                        content_type_hash;
 
     ngx_array_t                       cache_control;