comparison src/http/ngx_http_variables.c @ 160:73e8476f9142 NGINX_0_3_27

nginx 0.3.27 *) Change: the "variables_hash_max_size" and "variables_hash_bucket_size" directives. *) Feature: the $body_bytes_sent variable can be used not only in the "log_format" directive. *) Feature: the $ssl_protocol and $ssl_cipher variables. *) Feature: the cache line size detection for widespread CPUs at start time. *) Feature: now the "accept_mutex" directive is supported using fcntl(2) on platforms different from i386, amd64, sparc64, and ppc. *) Feature: the "lock_file" directive and the --with-lock-path=PATH autoconfiguration directive. *) Bugfix: if the HTTPS protocol was used in the "proxy_pass" directive then the requests with the body was not transferred.
author Igor Sysoev <http://sysoev.ru>
date Wed, 08 Feb 2006 00:00:00 +0300
parents 8e6d4d96ec4c
children 87699398f955
comparison
equal deleted inserted replaced
159:25c27e983933 160:73e8476f9142
39 static ngx_int_t ngx_http_variable_request_filename(ngx_http_request_t *r, 39 static ngx_int_t ngx_http_variable_request_filename(ngx_http_request_t *r,
40 ngx_http_variable_value_t *v, uintptr_t data); 40 ngx_http_variable_value_t *v, uintptr_t data);
41 static ngx_int_t ngx_http_variable_request_method(ngx_http_request_t *r, 41 static ngx_int_t ngx_http_variable_request_method(ngx_http_request_t *r,
42 ngx_http_variable_value_t *v, uintptr_t data); 42 ngx_http_variable_value_t *v, uintptr_t data);
43 static ngx_int_t ngx_http_variable_remote_user(ngx_http_request_t *r, 43 static ngx_int_t ngx_http_variable_remote_user(ngx_http_request_t *r,
44 ngx_http_variable_value_t *v, uintptr_t data);
45 static ngx_int_t ngx_http_variable_body_bytes_sent(ngx_http_request_t *r,
44 ngx_http_variable_value_t *v, uintptr_t data); 46 ngx_http_variable_value_t *v, uintptr_t data);
45 47
46 48
47 /* 49 /*
48 * TODO: 50 * TODO:
128 130
129 { ngx_string("request_method"), ngx_http_variable_request_method, 0, 0, 0 }, 131 { ngx_string("request_method"), ngx_http_variable_request_method, 0, 0, 0 },
130 132
131 { ngx_string("remote_user"), ngx_http_variable_remote_user, 0, 0, 0 }, 133 { ngx_string("remote_user"), ngx_http_variable_remote_user, 0, 0, 0 },
132 134
135 { ngx_string("body_bytes_sent"), ngx_http_variable_body_bytes_sent,
136 0, 0, 0 },
137
133 { ngx_null_string, NULL, 0, 0, 0 } 138 { ngx_null_string, NULL, 0, 0, 0 }
134 }; 139 };
135 140
136 141
137 ngx_http_variable_value_t ngx_http_variable_null_value = 142 ngx_http_variable_value_t ngx_http_variable_null_value =
141 146
142 147
143 ngx_http_variable_t * 148 ngx_http_variable_t *
144 ngx_http_add_variable(ngx_conf_t *cf, ngx_str_t *name, ngx_uint_t flags) 149 ngx_http_add_variable(ngx_conf_t *cf, ngx_str_t *name, ngx_uint_t flags)
145 { 150 {
151 ngx_int_t rc;
146 ngx_uint_t i; 152 ngx_uint_t i;
153 ngx_hash_key_t *key;
147 ngx_http_variable_t *v; 154 ngx_http_variable_t *v;
148 ngx_http_core_main_conf_t *cmcf; 155 ngx_http_core_main_conf_t *cmcf;
149 156
150 cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module); 157 cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
151 158
152 v = cmcf->all_variables.elts; 159 key = cmcf->variables_keys->keys.elts;
153 for (i = 0; i < cmcf->all_variables.nelts; i++) { 160 for (i = 0; i < cmcf->variables_keys->keys.nelts; i++) {
154 if (name->len != v[i].name.len 161 if (name->len != key[i].key.len
155 || ngx_strncasecmp(name->data, v[i].name.data, name->len) != 0) 162 || ngx_strncasecmp(name->data, key[i].key.data, name->len) != 0)
156 { 163 {
157 continue; 164 continue;
158 } 165 }
159 166
160 if (!(v[i].flags & NGX_HTTP_VAR_CHANGABLE)) { 167 v = key[i].value;
168
169 if (!(v->flags & NGX_HTTP_VAR_CHANGABLE)) {
161 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, 170 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
162 "the duplicate \"%V\" variable", name); 171 "the duplicate \"%V\" variable", name);
163 return NULL; 172 return NULL;
164 } 173 }
165 174
166 return &v[i]; 175 return v;
167 } 176 }
168 177
169 v = ngx_array_push(&cmcf->all_variables); 178 v = ngx_palloc(cf->pool, sizeof(ngx_http_variable_t));
170 if (v == NULL) { 179 if (v == NULL) {
171 return NULL; 180 return NULL;
172 } 181 }
173 182
174 v->name.len = name->len; 183 v->name.len = name->len;
183 192
184 v->handler = NULL; 193 v->handler = NULL;
185 v->data = 0; 194 v->data = 0;
186 v->flags = flags; 195 v->flags = flags;
187 v->index = 0; 196 v->index = 0;
197
198 rc = ngx_hash_add_key(cmcf->variables_keys, &v->name, v, 0);
199
200 if (rc == NGX_ERROR) {
201 return NULL;
202 }
203
204 if (rc == NGX_BUSY) {
205 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
206 "conflicting variable name \"%V\"", name);
207 return NULL;
208 }
188 209
189 return v; 210 return v;
190 } 211 }
191 212
192 213
296 return ngx_http_get_indexed_variable(r, index); 317 return ngx_http_get_indexed_variable(r, index);
297 } 318 }
298 319
299 320
300 ngx_http_variable_value_t * 321 ngx_http_variable_value_t *
301 ngx_http_get_variable(ngx_http_request_t *r, ngx_str_t *name) 322 ngx_http_get_variable(ngx_http_request_t *r, ngx_str_t *name, ngx_uint_t key)
302 { 323 {
303 ngx_uint_t i, key;
304 ngx_http_variable_t *v; 324 ngx_http_variable_t *v;
305 ngx_http_variable_value_t *vv; 325 ngx_http_variable_value_t *vv;
306 ngx_http_core_main_conf_t *cmcf; 326 ngx_http_core_main_conf_t *cmcf;
307 327
308 cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module); 328 cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
309 329
310 key = 0; 330 v = ngx_hash_find(&cmcf->variables_hash, key, name->data, name->len);
311 for (i = 0; i < name->len; i++) { 331
312 key += name->data[i]; 332 if (v) {
313 } 333 if (v->flags & NGX_HTTP_VAR_INDEXED) {
314 334 return ngx_http_get_indexed_variable(r, v->index);
315 key %= cmcf->variables_hash.hash_size;
316 v = (ngx_http_variable_t *) cmcf->variables_hash.buckets;
317
318 if (v[key].name.len == name->len
319 && ngx_strncmp(v[key].name.data, name->data, name->len) == 0)
320 {
321 if (v[key].flags & NGX_HTTP_VAR_INDEXED) {
322 return ngx_http_get_indexed_variable(r, v[key].index);
323 335
324 } else { 336 } else {
325 337
326 vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t)); 338 vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t));
327 339
328 if (vv && v[key].handler(r, vv, v[key].data) == NGX_OK) { 340 if (vv && v->handler(r, vv, v->data) == NGX_OK) {
329 return vv; 341 return vv;
330 } 342 }
331 343
332 return NULL; 344 return NULL;
333 } 345 }
756 768
757 return NGX_OK; 769 return NGX_OK;
758 } 770 }
759 771
760 772
773 static ngx_int_t
774 ngx_http_variable_body_bytes_sent(ngx_http_request_t *r,
775 ngx_http_variable_value_t *v, uintptr_t data)
776 {
777 off_t sent;
778 u_char *p;
779
780 sent = r->connection->sent - r->header_size;
781
782 if (sent < 0) {
783 sent = 0;
784 }
785
786 p = ngx_palloc(r->pool, NGX_OFF_T_LEN);
787 if (p == NULL) {
788 return NGX_ERROR;
789 }
790
791 v->len = ngx_sprintf(p, "%O", sent) - p;
792 v->valid = 1;
793 v->no_cachable = 0;
794 v->not_found = 0;
795 v->data = p;
796
797 return NGX_OK;
798 }
799
800
761 ngx_int_t 801 ngx_int_t
762 ngx_http_variables_add_core_vars(ngx_conf_t *cf) 802 ngx_http_variables_add_core_vars(ngx_conf_t *cf)
763 { 803 {
764 ngx_http_variable_t *v, *cv; 804 ngx_int_t rc;
805 ngx_http_variable_t *v;
765 ngx_http_core_main_conf_t *cmcf; 806 ngx_http_core_main_conf_t *cmcf;
766 807
767 cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module); 808 cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
768 809
769 if (ngx_array_init(&cmcf->all_variables, cf->pool, 32, 810 cmcf->variables_keys = ngx_pcalloc(cf->temp_pool,
770 sizeof(ngx_http_variable_t)) 811 sizeof(ngx_hash_keys_arrays_t));
771 == NGX_ERROR) 812 if (cmcf->variables_keys == NULL) {
813 return NGX_ERROR;
814 }
815
816 cmcf->variables_keys->pool = cf->pool;
817 cmcf->variables_keys->temp_pool = cf->pool;
818
819 if (ngx_hash_keys_array_init(cmcf->variables_keys, NGX_HASH_SMALL)
820 != NGX_OK)
772 { 821 {
773 return NGX_ERROR; 822 return NGX_ERROR;
774 } 823 }
775 824
776 for (cv = ngx_http_core_variables; cv->name.len; cv++) { 825 for (v = ngx_http_core_variables; v->name.len; v++) {
777 v = ngx_array_push(&cmcf->all_variables); 826 rc = ngx_hash_add_key(cmcf->variables_keys, &v->name, v,
778 if (v == NULL) { 827 NGX_HASH_READONLY_KEY);
779 return NGX_ERROR; 828
780 } 829 if (rc == NGX_OK) {
781 830 continue;
782 *v = *cv; 831 }
832
833 if (rc == NGX_BUSY) {
834 ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
835 "conflicting variable name \"%V\"", &v->name);
836 }
837
838 return NGX_ERROR;
783 } 839 }
784 840
785 return NGX_OK; 841 return NGX_OK;
786 } 842 }
787 843
788 844
789 ngx_int_t 845 ngx_int_t
790 ngx_http_variables_init_vars(ngx_conf_t *cf) 846 ngx_http_variables_init_vars(ngx_conf_t *cf)
791 { 847 {
792 ngx_uint_t i, n; 848 ngx_uint_t i, n;
849 ngx_hash_key_t *key;
850 ngx_hash_init_t hash;
793 ngx_http_variable_t *v, *av; 851 ngx_http_variable_t *v, *av;
794 ngx_http_core_main_conf_t *cmcf; 852 ngx_http_core_main_conf_t *cmcf;
795 853
796 /* set the handlers for the indexed http variables */ 854 /* set the handlers for the indexed http variables */
797 855
798 cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module); 856 cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);
799 857
800 v = cmcf->variables.elts; 858 v = cmcf->variables.elts;
801 av = cmcf->all_variables.elts; 859 key = cmcf->variables_keys->keys.elts;
802 860
803 for (i = 0; i < cmcf->variables.nelts; i++) { 861 for (i = 0; i < cmcf->variables.nelts; i++) {
804 862
805 for (n = 0; n < cmcf->all_variables.nelts; n++) { 863 for (n = 0; n < cmcf->variables_keys->keys.nelts; n++) {
806 864
807 if (v[i].name.len == av[n].name.len 865 if (v[i].name.len == key[n].key.len
808 && ngx_strncmp(v[i].name.data, av[n].name.data, v[i].name.len) 866 && ngx_strncmp(v[i].name.data, key[n].key.data, v[i].name.len)
809 == 0) 867 == 0)
810 { 868 {
811 v[i].handler = av[n].handler; 869 av = key[n].value;
812 v[i].data = av[n].data; 870
813 871 v[i].handler = av->handler;
814 av[n].flags |= NGX_HTTP_VAR_INDEXED; 872 v[i].data = av->data;
815 v[i].flags = av[n].flags; 873
816 874 av->flags |= NGX_HTTP_VAR_INDEXED;
817 av[n].index = i; 875 v[i].flags = av->flags;
876
877 av->index = i;
818 878
819 goto next; 879 goto next;
820 } 880 }
821 } 881 }
822 882
841 901
842 next: 902 next:
843 continue; 903 continue;
844 } 904 }
845 905
846 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, cf->log, 0, 906
847 "http variables: %ui", cmcf->variables.nelts); 907 for (n = 0; n < cmcf->variables_keys->keys.nelts; n++) {
848 908 av = key[n].value;
849 909
850 for (n = 0; n < cmcf->all_variables.nelts; n++) { 910 if (av->flags & NGX_HTTP_VAR_NOHASH) {
851 if (av[n].flags & NGX_HTTP_VAR_NOHASH) { 911 key[n].key.data = NULL;
852 av[n].name.data = NULL; 912 }
853 } 913 }
854 } 914
855 915
856 916 hash.hash = &cmcf->variables_hash;
857 /* init the all http variables hash */ 917 hash.key = ngx_hash_key;
858 918 hash.max_size = cmcf->variables_hash_max_size;
859 cmcf->variables_hash.max_size = 500; 919 hash.bucket_size = cmcf->variables_hash_bucket_size;
860 cmcf->variables_hash.bucket_limit = 1; 920 hash.name = "variables_hash";
861 cmcf->variables_hash.bucket_size = sizeof(ngx_http_variable_t); 921 hash.pool = cf->pool;
862 cmcf->variables_hash.name = "http variables"; 922 hash.temp_pool = NULL;
863 923
864 if (ngx_hash0_init(&cmcf->variables_hash, cf->pool, 924 if (ngx_hash_init(&hash, cmcf->variables_keys->keys.elts,
865 cmcf->all_variables.elts, cmcf->all_variables.nelts) 925 cmcf->variables_keys->keys.nelts)
866 != NGX_OK) 926 != NGX_OK)
867 { 927 {
868 return NGX_ERROR; 928 return NGX_ERROR;
869 } 929 }
870 930
871 ngx_log_debug3(NGX_LOG_DEBUG_HTTP, cf->log, 0, 931 cmcf->variables_keys = NULL;
872 "http variables hash size: %ui for %ui values, " 932
873 "max buckets per entry: %ui", 933 return NGX_OK;
874 cmcf->variables_hash.hash_size, cmcf->all_variables.nelts, 934 }
875 cmcf->variables_hash.min_buckets);
876
877 return NGX_OK;
878 }