changeset 7503:b82162b8496a

Added ngx_http_set_complex_value_size_slot(). If a complex value is expected to be of type size_t, and the compiled value is constant, the constant size_t value is remembered at compile time. The value is accessed through ngx_http_complex_value_size() which either returns the remembered constant or evaluates the expression and parses it as size_t.
author Ruslan Ermilov <ru@nginx.com>
date Wed, 24 Apr 2019 16:38:51 +0300
parents b7a7c02aea3a
children c19ca381b2e6
files src/http/ngx_http_script.c src/http/ngx_http_script.h src/stream/ngx_stream_script.c src/stream/ngx_stream_script.h
diffstat 4 files changed, 138 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/src/http/ngx_http_script.c
+++ b/src/http/ngx_http_script.c
@@ -104,6 +104,37 @@ ngx_http_complex_value(ngx_http_request_
 }
 
 
+size_t
+ngx_http_complex_value_size(ngx_http_request_t *r,
+    ngx_http_complex_value_t *val, size_t default_value)
+{
+    size_t     size;
+    ngx_str_t  value;
+
+    if (val == NULL) {
+        return default_value;
+    }
+
+    if (val->lengths == NULL) {
+        return val->u.size;
+    }
+
+    if (ngx_http_complex_value(r, val, &value) != NGX_OK) {
+        return default_value;
+    }
+
+    size = ngx_parse_size(&value);
+
+    if (size == (size_t) NGX_ERROR) {
+        ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
+                      "invalid size \"%V\"", &value);
+        return default_value;
+    }
+
+    return size;
+}
+
+
 ngx_int_t
 ngx_http_compile_complex_value(ngx_http_compile_complex_value_t *ccv)
 {
@@ -244,6 +275,36 @@ ngx_http_set_complex_value_slot(ngx_conf
 }
 
 
+char *
+ngx_http_set_complex_value_size_slot(ngx_conf_t *cf, ngx_command_t *cmd,
+    void *conf)
+{
+    char  *p = conf;
+
+    char                      *rv;
+    ngx_http_complex_value_t  *cv;
+
+    rv = ngx_http_set_complex_value_slot(cf, cmd, conf);
+
+    if (rv != NGX_CONF_OK) {
+        return rv;
+    }
+
+    cv = *(ngx_http_complex_value_t **) (p + cmd->offset);
+
+    if (cv->lengths) {
+        return NGX_CONF_OK;
+    }
+
+    cv->u.size = ngx_parse_size(&cv->value);
+    if (cv->u.size == (size_t) NGX_ERROR) {
+        return "invalid value";
+    }
+
+    return NGX_CONF_OK;
+}
+
+
 ngx_int_t
 ngx_http_test_predicates(ngx_http_request_t *r, ngx_array_t *predicates)
 {
--- a/src/http/ngx_http_script.h
+++ b/src/http/ngx_http_script.h
@@ -68,6 +68,10 @@ typedef struct {
     ngx_uint_t                 *flushes;
     void                       *lengths;
     void                       *values;
+
+    union {
+        size_t                  size;
+    } u;
 } ngx_http_complex_value_t;
 
 
@@ -207,9 +211,13 @@ void ngx_http_script_flush_complex_value
     ngx_http_complex_value_t *val);
 ngx_int_t ngx_http_complex_value(ngx_http_request_t *r,
     ngx_http_complex_value_t *val, ngx_str_t *value);
+size_t ngx_http_complex_value_size(ngx_http_request_t *r,
+    ngx_http_complex_value_t *val, size_t default_value);
 ngx_int_t ngx_http_compile_complex_value(ngx_http_compile_complex_value_t *ccv);
 char *ngx_http_set_complex_value_slot(ngx_conf_t *cf, ngx_command_t *cmd,
     void *conf);
+char *ngx_http_set_complex_value_size_slot(ngx_conf_t *cf, ngx_command_t *cmd,
+    void *conf);
 
 
 ngx_int_t ngx_http_test_predicates(ngx_http_request_t *r,
--- a/src/stream/ngx_stream_script.c
+++ b/src/stream/ngx_stream_script.c
@@ -105,6 +105,37 @@ ngx_stream_complex_value(ngx_stream_sess
 }
 
 
+size_t
+ngx_stream_complex_value_size(ngx_stream_session_t *s,
+    ngx_stream_complex_value_t *val, size_t default_value)
+{
+    size_t     size;
+    ngx_str_t  value;
+
+    if (val == NULL) {
+        return default_value;
+    }
+
+    if (val->lengths == NULL) {
+        return val->u.size;
+    }
+
+    if (ngx_stream_complex_value(s, val, &value) != NGX_OK) {
+        return default_value;
+    }
+
+    size = ngx_parse_size(&value);
+
+    if (size == (size_t) NGX_ERROR) {
+        ngx_log_error(NGX_LOG_ERR, s->connection->log, 0,
+                      "invalid size \"%V\"", &value);
+        return default_value;
+    }
+
+    return size;
+}
+
+
 ngx_int_t
 ngx_stream_compile_complex_value(ngx_stream_compile_complex_value_t *ccv)
 {
@@ -246,6 +277,36 @@ ngx_stream_set_complex_value_slot(ngx_co
 }
 
 
+char *
+ngx_stream_set_complex_value_size_slot(ngx_conf_t *cf, ngx_command_t *cmd,
+    void *conf)
+{
+    char  *p = conf;
+
+    char                        *rv;
+    ngx_stream_complex_value_t  *cv;
+
+    rv = ngx_stream_set_complex_value_slot(cf, cmd, conf);
+
+    if (rv != NGX_CONF_OK) {
+        return rv;
+    }
+
+    cv = *(ngx_stream_complex_value_t **) (p + cmd->offset);
+
+    if (cv->lengths) {
+        return NGX_CONF_OK;
+    }
+
+    cv->u.size = ngx_parse_size(&cv->value);
+    if (cv->u.size == (size_t) NGX_ERROR) {
+        return "invalid value";
+    }
+
+    return NGX_CONF_OK;
+}
+
+
 ngx_uint_t
 ngx_stream_script_variables_count(ngx_str_t *value)
 {
--- a/src/stream/ngx_stream_script.h
+++ b/src/stream/ngx_stream_script.h
@@ -56,6 +56,10 @@ typedef struct {
     ngx_uint_t                   *flushes;
     void                         *lengths;
     void                         *values;
+
+    union {
+        size_t                    size;
+    } u;
 } ngx_stream_complex_value_t;
 
 
@@ -102,10 +106,14 @@ void ngx_stream_script_flush_complex_val
     ngx_stream_complex_value_t *val);
 ngx_int_t ngx_stream_complex_value(ngx_stream_session_t *s,
     ngx_stream_complex_value_t *val, ngx_str_t *value);
+size_t ngx_stream_complex_value_size(ngx_stream_session_t *s,
+    ngx_stream_complex_value_t *val, size_t default_value);
 ngx_int_t ngx_stream_compile_complex_value(
     ngx_stream_compile_complex_value_t *ccv);
 char *ngx_stream_set_complex_value_slot(ngx_conf_t *cf, ngx_command_t *cmd,
     void *conf);
+char *ngx_stream_set_complex_value_size_slot(ngx_conf_t *cf, ngx_command_t *cmd,
+    void *conf);
 
 
 ngx_uint_t ngx_stream_script_variables_count(ngx_str_t *value);