src/http/modules/ngx_http_json_module.c - nginx-1.31.9 nginx/ @ 2a3a19c6f

Global variables defined

Data types defined

Functions defined

Macros defined

Source code


  1. /*
  2. * Copyright (C) Nginx, Inc.
  3. */


  4. #include <ngx_config.h>
  5. #include <ngx_core.h>
  6. #include <ngx_http.h>
  7. #include <ngx_json_parse.h>


  8. ‌#define NGX_HTTP_JSON_DEFAULT_MAX_DEPTH       32

  9. ‌typedef struct {
  10.     ngx_uint_t                     is_index;
  11.     ngx_str_t                      key;
  12.     ngx_uint_t                     index;
  13. ‌} ngx_http_json_seg_t;


  14. ‌typedef struct ngx_http_json_node_s  ngx_http_json_node_t;


  15. ‌struct ngx_http_json_node_s {
  16.     ngx_http_json_seg_t            seg;
  17.     ngx_array_t                   *children;  /* ngx_http_json_node_t */
  18.     ngx_uint_t                    *dests;
  19.     ngx_uint_t                     ndests;
  20. };


  21. ‌typedef struct {
  22.     ngx_int_t                      index;
  23.     ngx_http_json_node_t          *root;
  24. ‌} ngx_http_json_source_t;


  25. ‌typedef struct {
  26.     ngx_uint_t                     source_index;
  27. ‌} ngx_http_json_variable_t;


  28. ‌typedef struct {
  29.     ngx_uint_t                     index;
  30.     u_char                        *start;
  31.     ngx_http_json_node_t          *node;
  32.     ngx_uint_t                     is_array;
  33. ‌} ngx_http_json_frame_t;


  34. ‌typedef struct {
  35.     ngx_int_t                      max_depth;
  36.     ngx_array_t                   *sources;
  37.     ngx_array_t                   *variables;
  38. ‌} ngx_http_json_main_conf_t;


  39. ‌typedef struct {
  40.     ngx_http_request_t            *r;
  41.     ngx_http_variable_value_t     *values;
  42.     ngx_array_t                    stack;
  43.     ngx_str_t                      key_buffer;
  44.     ngx_uint_t                     in_member;
  45.     ngx_http_json_node_t          *current_node;
  46.     ngx_http_json_node_t          *root;
  47. ‌} ngx_http_json_state_t;


  48. static char *ngx_http_json_set(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
  49. static ngx_int_t ngx_http_json_variable(ngx_http_request_t *r,
  50.     ngx_http_variable_value_t *v, uintptr_t data);
  51. static void ngx_http_json_reset(ngx_http_variable_value_t *values,
  52.     ngx_http_json_main_conf_t *jmcf, ngx_uint_t source_index);
  53. static char *ngx_http_json_insert_path(ngx_conf_t *cf,
  54.     ngx_http_json_node_t *root, ngx_uint_t dest, ngx_str_t *path);
  55. static ngx_http_json_node_t *ngx_http_json_child(ngx_conf_t *cf,
  56.     ngx_http_json_node_t *parent, ngx_http_json_seg_t *seg);
  57. static ngx_int_t ngx_http_json_handler(ngx_json_ctx_t *ctx,
  58.     ngx_json_event_e event, ngx_str_t *token);
  59. static void ngx_http_json_inc_index(ngx_http_json_state_t *state);
  60. static ngx_http_json_node_t *ngx_http_json_lookup_key(
  61.     ngx_http_json_node_t *parent, ngx_str_t *key);
  62. static ngx_http_json_node_t *ngx_http_json_lookup_index(
  63.     ngx_http_json_node_t *parent, ngx_uint_t index);
  64. static ngx_int_t ngx_http_json_store(ngx_http_json_state_t *state,
  65.     ngx_http_json_node_t *node, ngx_str_t *value, ngx_uint_t unescape);
  66. static ngx_int_t ngx_http_json_push(ngx_http_json_state_t *state,
  67.     ngx_json_event_e event, u_char *start, ngx_http_json_node_t *node);
  68. static void *ngx_http_json_create_main_conf(ngx_conf_t *cf);
  69. static char *ngx_http_json_init_main_conf(ngx_conf_t *cf, void *conf);


  70. ‌static ngx_conf_num_bounds_t  ngx_http_json_max_depth_bounds = {
  71.     ngx_conf_check_num_bounds, 1, 256
  72. };


  73. ‌static ngx_command_t  ngx_http_json_commands[] = {

  74.     { ngx_string("json_set"),
  75.       NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE3,
  76.       ngx_http_json_set,
  77.       NGX_HTTP_MAIN_CONF_OFFSET,
  78.       0,
  79.       NULL },

  80.     { ngx_string("json_max_depth"),
  81.       NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1,
  82.       ngx_conf_set_num_slot,
  83.       NGX_HTTP_MAIN_CONF_OFFSET,
  84.       offsetof(ngx_http_json_main_conf_t, max_depth),
  85.       &ngx_http_json_max_depth_bounds },

  86.       ngx_null_command
  87. };


  88. ‌static ngx_http_module_t  ngx_http_json_module_ctx = {
  89.     NULL,                            /* preconfiguration */
  90.     NULL,                            /* postconfiguration */

  91.     ngx_http_json_create_main_conf,  /* create main configuration */
  92.     ngx_http_json_init_main_conf,    /* init main configuration */

  93.     NULL,                            /* create server configuration */
  94.     NULL,                            /* merge server configuration */

  95.     NULL,                            /* create location configuration */
  96.     NULL                             /* merge location configuration */
  97. };


  98. ‌ngx_module_t  ngx_http_json_module = {
  99.     NGX_MODULE_V1,
  100.     &ngx_http_json_module_ctx,       /* module context */
  101.     ngx_http_json_commands,          /* module directives */
  102.     NGX_HTTP_MODULE,                 /* module type */
  103.     NULL,                            /* init master */
  104.     NULL,                            /* init module */
  105.     NULL,                            /* init process */
  106.     NULL,                            /* init thread */
  107.     NULL,                            /* exit thread */
  108.     NULL,                            /* exit process */
  109.     NULL,                            /* exit master */
  110.     NGX_MODULE_V1_PADDING
  111. };


  112. static char *
  113. ‌ngx_http_json_set(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
  114. {
  115.     ngx_http_json_main_conf_t  *jmcf = conf;

  116.     ngx_str_t                 *value, name, source;
  117.     ngx_int_t                  sindex;
  118.     ngx_uint_t                 i, oi, si;
  119.     ngx_http_variable_t       *var;
  120.     ngx_http_json_source_t    *src, *srcs;
  121.     ngx_http_json_variable_t  *jv;

  122.     value = cf->args->elts;

  123.     name = value[1];

  124.     if (name.data[0] != '$') {
  125.         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  126.                            "invalid variable name \"%V\"", &name);
  127.         return NGX_CONF_ERROR;
  128.     }

  129.     name.len--;
  130.     name.data++;

  131.     var = ngx_http_add_variable(cf, &name, NGX_HTTP_VAR_CHANGEABLE);
  132.     if (var == NULL) {
  133.         return NGX_CONF_ERROR;
  134.     }

  135.     if (var->get_handler == ngx_http_json_variable) {
  136.         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  137.                            "json_set variable \"%V\" is already defined",
  138.                            &name);
  139.         return NGX_CONF_ERROR;
  140.     }

  141.     source = value[2];

  142.     if (source.data[0] != '$') {
  143.         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  144.                            "invalid variable name \"%V\"", &source);
  145.         return NGX_CONF_ERROR;
  146.     }

  147.     source.len--;
  148.     source.data++;

  149.     sindex = ngx_http_get_variable_index(cf, &source);
  150.     if (sindex == NGX_ERROR) {
  151.         return NGX_CONF_ERROR;
  152.     }

  153.     if (jmcf->sources == NULL) {
  154.         jmcf->sources = ngx_array_create(cf->pool, 4,
  155.                                          sizeof(ngx_http_json_source_t));
  156.         if (jmcf->sources == NULL) {
  157.             return NGX_CONF_ERROR;
  158.         }
  159.     }

  160.     srcs = jmcf->sources->elts;
  161.     si = jmcf->sources->nelts;

  162.     for (i = 0; i < jmcf->sources->nelts; i++) {
  163.         if (srcs[i].index == sindex) {
  164.             si = i;
  165.             break;
  166.         }
  167.     }

  168.     if (si == jmcf->sources->nelts) {
  169.         src = ngx_array_push(jmcf->sources);
  170.         if (src == NULL) {
  171.             return NGX_CONF_ERROR;
  172.         }

  173.         src->index = sindex;

  174.         src->root = ngx_pcalloc(cf->pool, sizeof(ngx_http_json_node_t));
  175.         if (src->root == NULL) {
  176.             return NGX_CONF_ERROR;
  177.         }

  178.     } else {
  179.         src = &srcs[si];
  180.     }

  181.     if (jmcf->variables == NULL) {
  182.         jmcf->variables = ngx_array_create(cf->pool, 4,
  183.                                            sizeof(ngx_http_json_variable_t));
  184.         if (jmcf->variables == NULL) {
  185.             return NGX_CONF_ERROR;
  186.         }
  187.     }

  188.     oi = jmcf->variables->nelts;

  189.     jv = ngx_array_push(jmcf->variables);
  190.     if (jv == NULL) {
  191.         return NGX_CONF_ERROR;
  192.     }

  193.     jv->source_index = si;

  194.     if (ngx_http_json_insert_path(cf, src->root, oi, &value[3])
  195.         != NGX_CONF_OK)
  196.     {
  197.         return NGX_CONF_ERROR;
  198.     }

  199.     var->get_handler = ngx_http_json_variable;
  200.     var->data = (uintptr_t) oi;

  201.     return NGX_CONF_OK;
  202. }


  203. static ngx_int_t
  204. ‌ngx_http_json_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v,
  205.     uintptr_t data)
  206. {
  207.     ngx_int_t                   rc;
  208.     ngx_uint_t                  oi, si;
  209.     ngx_json_ctx_t              jctx;
  210.     ngx_http_json_state_t       state;
  211.     ngx_http_json_source_t     *src, *srcs;
  212.     ngx_http_json_variable_t   *jv;
  213.     ngx_http_variable_value_t  *cached, *values, *vv;
  214.     ngx_http_json_main_conf_t  *jmcf;

  215.     oi = (ngx_uint_t) data;

  216.     jmcf = ngx_http_get_module_main_conf(r, ngx_http_json_module);

  217.     if (jmcf->variables == NULL || oi >= jmcf->variables->nelts) {
  218.         v->not_found = 1;
  219.         return NGX_OK;
  220.     }

  221.     values = ngx_http_get_module_ctx(r, ngx_http_json_module);

  222.     if (values == NULL) {
  223.         values = ngx_pcalloc(r->pool, jmcf->variables->nelts
  224.                              * sizeof(ngx_http_variable_value_t));
  225.         if (values == NULL) {
  226.             return NGX_ERROR;
  227.         }

  228.         ngx_http_set_ctx(r, values, ngx_http_json_module);
  229.     }

  230.     cached = &values[oi];

  231.     if (cached->valid || cached->not_found) {
  232.         *v = *cached;
  233.         return NGX_OK;
  234.     }

  235.     jv = jmcf->variables->elts;
  236.     si = jv[oi].source_index;

  237.     srcs = jmcf->sources->elts;
  238.     src = &srcs[si];

  239.     vv = ngx_http_get_flushed_variable(r, (ngx_uint_t) src->index);

  240.     if (vv == NULL) {
  241.         return NGX_ERROR;
  242.     }

  243.     ngx_http_json_reset(values, jmcf, si);

  244.     if (vv->not_found || vv->len == 0) {
  245.         *v = *cached;
  246.         return NGX_OK;
  247.     }

  248.     ngx_memzero(&state, sizeof(ngx_http_json_state_t));

  249.     state.r = r;
  250.     state.values = values;
  251.     state.root = src->root;

  252.     if (ngx_array_init(&state.stack, r->pool, 8, sizeof(ngx_http_json_frame_t))
  253.         != NGX_OK)
  254.     {
  255.         return NGX_ERROR;
  256.     }

  257.     ngx_json_ctx_init(&jctx, r->pool);

  258.     jctx.handler = ngx_http_json_handler;
  259.     jctx.data = &state;
  260.     jctx.max_depth = jmcf->max_depth;

  261.     rc = ngx_json_parse_ctx(&jctx, vv->data, vv->len);

  262.     if (rc == NGX_OK) {
  263.         *v = *cached;
  264.         return NGX_OK;
  265.     }

  266.     ngx_http_json_reset(values, jmcf, si);

  267.     if (rc == NGX_DECLINED) {
  268.         ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
  269.                        "json_set: invalid JSON source");
  270.     }

  271.     if (rc == NGX_ERROR) {
  272.         return NGX_ERROR;
  273.     }

  274.     *v = *cached;

  275.     return NGX_OK;
  276. }


  277. static void
  278. ‌ngx_http_json_reset(ngx_http_variable_value_t *values,
  279.     ngx_http_json_main_conf_t *jmcf, ngx_uint_t source_index)
  280. {
  281.     ngx_uint_t                 i;
  282.     ngx_http_json_variable_t  *jv;

  283.     jv = jmcf->variables->elts;

  284.     for (i = 0; i < jmcf->variables->nelts; i++) {
  285.         if (jv[i].source_index != source_index) {
  286.             continue;
  287.         }

  288.         values[i].valid = 0;
  289.         values[i].not_found = 1;
  290.     }
  291. }


  292. static char *
  293. ‌ngx_http_json_insert_path(ngx_conf_t *cf, ngx_http_json_node_t *root,
  294.     ngx_uint_t dest, ngx_str_t *path)
  295. {
  296.     u_char                *p, *last, *start, *dst;
  297.     ngx_int_t              index;
  298.     ngx_str_t              raw;
  299.     ngx_uint_t            *term;
  300.     ngx_http_json_seg_t    seg;
  301.     ngx_http_json_node_t  *node;
  302. ‌    enum {
  303.         sw_start = 0,
  304.         sw_key,
  305.         sw_dot,
  306.         sw_bracket,
  307.         sw_index,
  308.         sw_quoted,
  309.         sw_quoted_escape,
  310.         sw_quoted_close,
  311.         sw_after_bracket
  312.     } state;

  313.     if (path->len == 0) {
  314.         ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "empty json_set path");
  315.         return NGX_CONF_ERROR;
  316.     }

  317.     node = root;
  318.     start = NULL;

  319.     last = path->data + path->len;
  320.     state = sw_start;

  321.     for (p = path->data; p < last; p++) {

  322.         switch (state) {

  323.         case sw_start:

  324.             if (*p == '[') {
  325.                 state = sw_bracket;
  326.                 break;
  327.             }

  328.             if (*p == '.' || *p == '$') {
  329.                 goto invalid;
  330.             }

  331.             start = p;
  332.             state = sw_key;
  333.             break;

  334.         case sw_key:

  335.             if (*p == '.' || *p == '[') {

  336.                 seg.is_index = 0;
  337.                 seg.key.data = start;
  338.                 seg.key.len = p - start;
  339.                 seg.index = 0;

  340.                 node = ngx_http_json_child(cf, node, &seg);
  341.                 if (node == NULL) {
  342.                     return NGX_CONF_ERROR;
  343.                 }

  344.                 state = (*p == '.') ? sw_dot : sw_bracket;
  345.             }

  346.             break;

  347.         case sw_dot:

  348.             if (*p == '.' || *p == '[' || *p == '$') {
  349.                 goto invalid;
  350.             }

  351.             start = p;
  352.             state = sw_key;
  353.             break;

  354.         case sw_bracket:

  355.             if (*p == '"') {
  356.                 start = p + 1;
  357.                 state = sw_quoted;
  358.                 break;
  359.             }

  360.             if (*p >= '0' && *p <= '9') {
  361.                 start = p;
  362.                 state = sw_index;
  363.                 break;
  364.             }

  365.             goto invalid;

  366.         case sw_index:

  367.             if (*p >= '0' && *p <= '9') {
  368.                 break;
  369.             }

  370.             if (*p != ']') {
  371.                 goto invalid;
  372.             }

  373.             index = ngx_atoi(start, p - start);
  374.             if (index == NGX_ERROR) {
  375.                 goto invalid;
  376.             }

  377.             seg.is_index = 1;
  378.             seg.index = index;
  379.             ngx_str_null(&seg.key);

  380.             node = ngx_http_json_child(cf, node, &seg);
  381.             if (node == NULL) {
  382.                 return NGX_CONF_ERROR;
  383.             }

  384.             state = sw_after_bracket;
  385.             break;

  386.         case sw_quoted:

  387.             if (*p == '\\') {
  388.                 state = sw_quoted_escape;
  389.                 break;
  390.             }

  391.             if (*p == '"') {

  392.                 dst = ngx_pnalloc(cf->pool, (size_t) (p - start));
  393.                 if (dst == NULL) {
  394.                     return NGX_CONF_ERROR;
  395.                 }

  396.                 raw.data = start;
  397.                 raw.len = p - start;

  398.                 seg.is_index = 0;
  399.                 seg.key.data = dst;
  400.                 seg.key.len = p - start;
  401.                 seg.index = 0;

  402.                 if (ngx_json_unescape_string(&seg.key, &raw) != NGX_OK) {
  403.                     goto invalid;
  404.                 }

  405.                 node = ngx_http_json_child(cf, node, &seg);
  406.                 if (node == NULL) {
  407.                     return NGX_CONF_ERROR;
  408.                 }

  409.                 state = sw_quoted_close;
  410.             }

  411.             break;

  412.         case sw_quoted_escape:

  413.             state = sw_quoted;
  414.             break;

  415.         case sw_quoted_close:

  416.             if (*p != ']') {
  417.                 goto invalid;
  418.             }

  419.             state = sw_after_bracket;
  420.             break;

  421.         case sw_after_bracket:

  422.             if (*p == '.') {
  423.                 state = sw_dot;
  424.                 break;
  425.             }

  426.             if (*p == '[') {
  427.                 state = sw_bracket;
  428.                 break;
  429.             }

  430.             goto invalid;
  431.         }
  432.     }

  433.     switch (state) {

  434.     case sw_key:

  435.         seg.is_index = 0;
  436.         seg.key.data = start;
  437.         seg.key.len = last - start;
  438.         seg.index = 0;

  439.         node = ngx_http_json_child(cf, node, &seg);
  440.         if (node == NULL) {
  441.             return NGX_CONF_ERROR;
  442.         }

  443.         break;

  444.     case sw_after_bracket:
  445.         break;

  446.     default:
  447.         goto invalid;
  448.     }

  449.     term = ngx_palloc(cf->pool, (node->ndests + 1) * sizeof(ngx_uint_t));
  450.     if (term == NULL) {
  451.         return NGX_CONF_ERROR;
  452.     }

  453.     if (node->ndests) {
  454.         ngx_memcpy(term, node->dests, node->ndests * sizeof(ngx_uint_t));
  455.     }

  456.     term[node->ndests] = dest;
  457.     node->dests = term;
  458.     node->ndests++;

  459.     return NGX_CONF_OK;

  460. invalid:

  461.     ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
  462.                        "invalid json_set path \"%V\"", path);
  463.     return NGX_CONF_ERROR;
  464. }


  465. static ngx_http_json_node_t *
  466. ‌ngx_http_json_child(ngx_conf_t *cf, ngx_http_json_node_t *parent,
  467.     ngx_http_json_seg_t *seg)
  468. {
  469.     ngx_uint_t             i;
  470.     ngx_http_json_seg_t   *cseg;
  471.     ngx_http_json_node_t  *child, *elts;

  472.     if (parent->children != NULL) {
  473.         elts = parent->children->elts;

  474.         for (i = 0; i < parent->children->nelts; i++) {
  475.             child = &elts[i];
  476.             cseg = &child->seg;

  477.             if (seg->is_index) {
  478.                 if (cseg->is_index && cseg->index == seg->index) {
  479.                     return child;
  480.                 }

  481.             } else {
  482.                 if (!cseg->is_index
  483.                     && cseg->key.len == seg->key.len
  484.                     && ngx_memcmp(cseg->key.data, seg->key.data, seg->key.len)
  485.                        == 0)
  486.                 {
  487.                     return child;
  488.                 }
  489.             }
  490.         }

  491.     } else {
  492.         parent->children = ngx_array_create(cf->pool, 1,
  493.                                             sizeof(ngx_http_json_node_t));
  494.         if (parent->children == NULL) {
  495.             return NULL;
  496.         }
  497.     }

  498.     child = ngx_array_push(parent->children);
  499.     if (child == NULL) {
  500.         return NULL;
  501.     }

  502.     ngx_memzero(child, sizeof(ngx_http_json_node_t));

  503.     child->seg = *seg;

  504.     return child;
  505. }


  506. static ngx_int_t
  507. ‌ngx_http_json_handler(ngx_json_ctx_t *ctx, ngx_json_event_e event,
  508.     ngx_str_t *token)
  509. {
  510.     size_t                  size;
  511.     u_char                 *p;
  512.     ngx_str_t               key, slice, value;
  513.     ngx_uint_t              is_member;
  514.     ngx_http_json_node_t   *node;
  515.     ngx_http_json_state_t  *state;
  516.     ngx_http_json_frame_t  *top;

  517.     state = ctx->data;

  518.     top = NULL;
  519.     if (state->stack.nelts) {
  520.         top = (ngx_http_json_frame_t *) state->stack.elts
  521.               + state->stack.nelts - 1;
  522.     }

  523.     switch (event) {

  524.     case NGX_JSON_OBJECT_OPEN:
  525.     case NGX_JSON_ARRAY_OPEN:

  526.         if (state->stack.nelts == 0) {

  527.             state->in_member = 0;
  528.             state->current_node = NULL;

  529.             return ngx_http_json_push(state, event, token->data, state->root);
  530.         }

  531.         is_member = state->in_member;
  532.         state->in_member = 0;

  533.         if (is_member) {

  534.             node = state->current_node;
  535.             state->current_node = NULL;

  536.         } else {

  537.             node = ngx_http_json_lookup_index(top->node, top->index);

  538.             ngx_http_json_inc_index(state);

  539.             if (node == NULL) {
  540.                 return NGX_JSON_SKIP;
  541.             }
  542.         }

  543.         return ngx_http_json_push(state, event, token->data, node);

  544.     case NGX_JSON_OBJECT_CLOSE:
  545.     case NGX_JSON_ARRAY_CLOSE:

  546.         if (top != NULL) {

  547.             if (top->node->ndests > 0) {
  548.                 slice.data = top->start;
  549.                 slice.len = token->data - top->start + 1;

  550.                 if (ngx_http_json_store(state, top->node, &slice, 0)
  551.                     != NGX_OK)
  552.                 {
  553.                     return NGX_ERROR;
  554.                 }
  555.             }

  556.             state->stack.nelts--;
  557.         }

  558.         break;

  559.     case NGX_JSON_KEY:
  560.     case NGX_JSON_KEY_ESCAPED:

  561.         key = *token;

  562.         if (event == NGX_JSON_KEY_ESCAPED) {
  563.             if (token->len > state->key_buffer.len) {
  564.                 size = token->len;

  565.                 if (state->key_buffer.len <= NGX_MAX_SIZE_T_VALUE / 2) {
  566.                     size = ngx_max(size, state->key_buffer.len * 2);
  567.                 }

  568.                 p = ngx_pnalloc(ctx->pool, size);
  569.                 if (p == NULL) {
  570.                     return NGX_ERROR;
  571.                 }

  572.                 state->key_buffer.data = p;
  573.                 state->key_buffer.len = size;
  574.             }

  575.             key = state->key_buffer;

  576.             if (ngx_json_unescape_string(&key, token) != NGX_OK) {
  577.                 return NGX_ERROR;
  578.             }
  579.         }

  580.         node = ngx_http_json_lookup_key(top->node, &key);
  581.         if (node == NULL) {
  582.             state->in_member = 0;
  583.             state->current_node = NULL;
  584.             return NGX_JSON_SKIP;
  585.         }

  586.         state->in_member = 1;
  587.         state->current_node = node;

  588.         break;

  589.     case NGX_JSON_VALUE_STRING:
  590.     case NGX_JSON_VALUE_STRING_ESCAPED:
  591.     case NGX_JSON_VALUE_NUMBER:
  592.     case NGX_JSON_VALUE_BOOL:
  593.     case NGX_JSON_VALUE_NULL:

  594.         if (top == NULL) {
  595.             state->in_member = 0;
  596.             state->current_node = NULL;
  597.             break;
  598.         }

  599.         is_member = state->in_member;
  600.         state->in_member = 0;

  601.         if (is_member) {

  602.             node = state->current_node;
  603.             state->current_node = NULL;

  604.         } else {

  605.             node = ngx_http_json_lookup_index(top->node, top->index);

  606.             ngx_http_json_inc_index(state);
  607.         }

  608.         if (node != NULL && node->ndests > 0) {

  609.             value = *token;

  610.             if (ngx_http_json_store(state, node, &value,
  611.                                     event == NGX_JSON_VALUE_STRING_ESCAPED)
  612.                 != NGX_OK)
  613.             {
  614.                 return NGX_ERROR;
  615.             }
  616.         }

  617.         break;
  618.     }

  619.     return NGX_OK;
  620. }


  621. static void
  622. ‌ngx_http_json_inc_index(ngx_http_json_state_t *state)
  623. {
  624.     ngx_http_json_frame_t  *top;

  625.     if (state->stack.nelts == 0) {
  626.         return;
  627.     }

  628.     top = state->stack.elts;
  629.     top += state->stack.nelts - 1;

  630.     if (top->is_array) {
  631.         top->index++;
  632.     }
  633. }


  634. static ngx_http_json_node_t *
  635. ‌ngx_http_json_lookup_key(ngx_http_json_node_t *parent, ngx_str_t *key)
  636. {
  637.     ngx_uint_t             i;
  638.     ngx_http_json_seg_t   *seg;
  639.     ngx_http_json_node_t  *child, *elts;

  640.     if (parent->children == NULL) {
  641.         return NULL;
  642.     }

  643.     elts = parent->children->elts;

  644.     for (i = 0; i < parent->children->nelts; i++) {
  645.         child = &elts[i];
  646.         seg = &child->seg;

  647.         if (!seg->is_index
  648.             && seg->key.len == key->len
  649.             && ngx_memcmp(seg->key.data, key->data, key->len) == 0)
  650.         {
  651.             return child;
  652.         }
  653.     }

  654.     return NULL;
  655. }


  656. static ngx_http_json_node_t *
  657. ‌ngx_http_json_lookup_index(ngx_http_json_node_t *parent, ngx_uint_t index)
  658. {
  659.     ngx_uint_t             i;
  660.     ngx_http_json_seg_t   *seg;
  661.     ngx_http_json_node_t  *child, *elts;

  662.     if (parent->children == NULL) {
  663.         return NULL;
  664.     }

  665.     elts = parent->children->elts;

  666.     for (i = 0; i < parent->children->nelts; i++) {
  667.         child = &elts[i];
  668.         seg = &child->seg;

  669.         if (seg->is_index && seg->index == index) {
  670.             return child;
  671.         }
  672.     }

  673.     return NULL;
  674. }


  675. static ngx_int_t
  676. ‌ngx_http_json_store(ngx_http_json_state_t *state, ngx_http_json_node_t *node,
  677.     ngx_str_t *value, ngx_uint_t unescape)
  678. {
  679.     ngx_str_t                   val;
  680.     ngx_uint_t                  i;
  681.     ngx_http_variable_value_t  *slot;

  682.     if (value->len == 0) {
  683.         val.len = 0;
  684.         val.data = (u_char *) "";

  685.     } else if (unescape) {
  686.         val.data = ngx_pnalloc(state->r->pool, value->len);
  687.         if (val.data == NULL) {
  688.             return NGX_ERROR;
  689.         }

  690.         val.len = value->len;

  691.         if (ngx_json_unescape_string(&val, value) != NGX_OK) {
  692.             return NGX_ERROR;
  693.         }

  694.     } else {
  695.         val.data = ngx_pstrdup(state->r->pool, value);
  696.         if (val.data == NULL) {
  697.             return NGX_ERROR;
  698.         }

  699.         val.len = value->len;
  700.     }

  701.     for (i = 0; i < node->ndests; i++) {
  702.         slot = &state->values[node->dests[i]];
  703.         slot->valid = 1;
  704.         slot->not_found = 0;
  705.         slot->no_cacheable = 0;
  706.         slot->escape = 0;
  707.         slot->len = val.len;
  708.         slot->data = val.data;
  709.     }

  710.     return NGX_OK;
  711. }


  712. static ngx_int_t
  713. ‌ngx_http_json_push(ngx_http_json_state_t *state, ngx_json_event_e event,
  714.     u_char *start, ngx_http_json_node_t *node)
  715. {
  716.     ngx_http_json_frame_t  *frame;

  717.     frame = ngx_array_push(&state->stack);
  718.     if (frame == NULL) {
  719.         return NGX_ERROR;
  720.     }

  721.     frame->index = 0;
  722.     frame->start = start;
  723.     frame->is_array = (event == NGX_JSON_ARRAY_OPEN);
  724.     frame->node = node;

  725.     return NGX_OK;
  726. }


  727. static void *
  728. ‌ngx_http_json_create_main_conf(ngx_conf_t *cf)
  729. {
  730.     ngx_http_json_main_conf_t  *jmcf;

  731.     jmcf = ngx_pcalloc(cf->pool, sizeof(ngx_http_json_main_conf_t));
  732.     if (jmcf == NULL) {
  733.         return NULL;
  734.     }

  735.     jmcf->max_depth = NGX_CONF_UNSET;

  736.     return jmcf;
  737. }


  738. static char *
  739. ‌ngx_http_json_init_main_conf(ngx_conf_t *cf, void *conf)
  740. {
  741.     ngx_http_json_main_conf_t  *jmcf = conf;

  742.     ngx_conf_init_value(jmcf->max_depth, NGX_HTTP_JSON_DEFAULT_MAX_DEPTH);

  743.     return NGX_CONF_OK;
  744. }