diff options
author | Valentin Bartenev <vbart@nginx.com> | 2017-05-16 22:02:01 +0300 |
---|---|---|
committer | Valentin Bartenev <vbart@nginx.com> | 2017-05-16 22:02:01 +0300 |
commit | dc95b2f3de76df03b64bab9bbc5e6a9dc7015550 (patch) | |
tree | 7c038aaa3ae2705e0544d94b73b2d7bbf58245ac /src | |
parent | 0ca2c2fce2c21a397fc10d19bca6628df7bc62ab (diff) | |
download | unit-dc95b2f3de76df03b64bab9bbc5e6a9dc7015550.tar.gz unit-dc95b2f3de76df03b64bab9bbc5e6a9dc7015550.tar.bz2 |
Controller: pretty-printing of JSON responses.
Diffstat (limited to 'src')
-rw-r--r-- | src/nxt_conf.h | 10 | ||||
-rw-r--r-- | src/nxt_conf_json.c | 165 | ||||
-rw-r--r-- | src/nxt_controller.c | 59 |
3 files changed, 184 insertions, 50 deletions
diff --git a/src/nxt_conf.h b/src/nxt_conf.h index 5dd16177..4d427bce 100644 --- a/src/nxt_conf.h +++ b/src/nxt_conf.h @@ -12,10 +12,16 @@ typedef struct nxt_conf_json_value_s nxt_conf_json_value_t; +typedef struct { + nxt_uint_t level; + nxt_bool_t more_space; /* 1 bit. */ +} nxt_conf_json_pretty_t; + + nxt_conf_json_value_t *nxt_conf_json_parse(u_char *pos, size_t length, nxt_mem_pool_t *pool); -nxt_buf_t *nxt_conf_json_print(nxt_conf_json_value_t *value, - nxt_mem_pool_t *pool); +uintptr_t nxt_conf_json_print_value(u_char *pos, nxt_conf_json_value_t *value, + nxt_conf_json_pretty_t *pretty); #endif /* _NXT_CONF_INCLUDED_ */ diff --git a/src/nxt_conf_json.c b/src/nxt_conf_json.c index b2b830e0..063fa988 100644 --- a/src/nxt_conf_json.c +++ b/src/nxt_conf_json.c @@ -69,20 +69,34 @@ static u_char *nxt_conf_json_parse_number(u_char *pos, u_char *end, nxt_conf_json_value_t *value, nxt_mem_pool_t *pool); -static uintptr_t nxt_conf_json_print_value(u_char *pos, - nxt_conf_json_value_t *value); static uintptr_t nxt_conf_json_print_integer(u_char *pos, nxt_conf_json_value_t *value); static uintptr_t nxt_conf_json_print_string(u_char *pos, nxt_conf_json_value_t *value); static uintptr_t nxt_conf_json_print_array(u_char *pos, - nxt_conf_json_value_t *value); + nxt_conf_json_value_t *value, nxt_conf_json_pretty_t *pretty); static uintptr_t nxt_conf_json_print_object(u_char *pos, - nxt_conf_json_value_t *value); + nxt_conf_json_value_t *value, nxt_conf_json_pretty_t *pretty); static uintptr_t nxt_conf_json_escape(u_char *dst, u_char *src, size_t size); +#define nxt_conf_json_newline(pos) \ + ((pos)[0] = '\r', (pos)[1] = '\n', (pos) + 2) + +nxt_inline u_char * +nxt_conf_json_indentation(u_char *pos, nxt_conf_json_pretty_t *pretty) +{ + nxt_uint_t i; + + for (i = 0; i < pretty->level; i++) { + pos[i] = '\t'; + } + + return pos + pretty->level; +} + + static const nxt_lvlhsh_proto_t nxt_conf_json_object_hash_proto nxt_aligned(64) = { @@ -789,27 +803,9 @@ nxt_conf_json_parse_number(u_char *pos, u_char *end, } -nxt_buf_t * -nxt_conf_json_print(nxt_conf_json_value_t *value, nxt_mem_pool_t *pool) -{ - size_t size; - nxt_buf_t *b; - - size = nxt_conf_json_print_value(NULL, value); - - b = nxt_buf_mem_alloc(pool, size, 0); - if (nxt_slow_path(b == NULL)) { - return NULL; - } - - b->mem.free = (u_char *) nxt_conf_json_print_value(b->mem.free, value); - - return b; -} - - -static uintptr_t -nxt_conf_json_print_value(u_char *pos, nxt_conf_json_value_t *value) +uintptr_t +nxt_conf_json_print_value(u_char *pos, nxt_conf_json_value_t *value, + nxt_conf_json_pretty_t *pretty) { switch (value->type) { @@ -845,10 +841,10 @@ nxt_conf_json_print_value(u_char *pos, nxt_conf_json_value_t *value) return nxt_conf_json_print_string(pos, value); case NXT_CONF_JSON_ARRAY: - return nxt_conf_json_print_array(pos, value); + return nxt_conf_json_print_array(pos, value, pretty); case NXT_CONF_JSON_OBJECT: - return nxt_conf_json_print_object(pos, value); + return nxt_conf_json_print_object(pos, value, pretty); } nxt_unreachable(); @@ -912,7 +908,8 @@ nxt_conf_json_print_string(u_char *pos, nxt_conf_json_value_t *value) static uintptr_t -nxt_conf_json_print_array(u_char *pos, nxt_conf_json_value_t *value) +nxt_conf_json_print_array(u_char *pos, nxt_conf_json_value_t *value, + nxt_conf_json_pretty_t *pretty) { size_t len; uint32_t n; @@ -921,15 +918,35 @@ nxt_conf_json_print_array(u_char *pos, nxt_conf_json_value_t *value) array = value->u.array; if (pos == NULL) { + /* [] */ len = 2; + if (pretty != NULL) { + pretty->level++; + } + value = array->elts; for (n = 0; n < array->nelts; n++) { - len += nxt_conf_json_print_value(NULL, &value[n]); + len += nxt_conf_json_print_value(NULL, &value[n], pretty); + + if (pretty != NULL) { + /* indentation and new line */ + len += pretty->level + 2; + } + } + + if (pretty != NULL) { + pretty->level--; + + if (n != 0) { + /* indentation and new line */ + len += pretty->level + 2; + } } - return n + len; + /* reserve space for "n" commas */ + return len + n; } *pos++ = '['; @@ -937,11 +954,35 @@ nxt_conf_json_print_array(u_char *pos, nxt_conf_json_value_t *value) if (array->nelts != 0) { value = array->elts; - pos = (u_char *) nxt_conf_json_print_value(pos, &value[0]); + if (pretty != NULL) { + pos = nxt_conf_json_newline(pos); + + pretty->level++; + pos = nxt_conf_json_indentation(pos, pretty); + } + + pos = (u_char *) nxt_conf_json_print_value(pos, &value[0], pretty); for (n = 1; n < array->nelts; n++) { *pos++ = ','; - pos = (u_char *) nxt_conf_json_print_value(pos, &value[n]); + + if (pretty != NULL) { + pos = nxt_conf_json_newline(pos); + pos = nxt_conf_json_indentation(pos, pretty); + + pretty->more_space = 0; + } + + pos = (u_char *) nxt_conf_json_print_value(pos, &value[n], pretty); + } + + if (pretty != NULL) { + pos = nxt_conf_json_newline(pos); + + pretty->level--; + pos = nxt_conf_json_indentation(pos, pretty); + + pretty->more_space = 1; } } @@ -952,7 +993,8 @@ nxt_conf_json_print_array(u_char *pos, nxt_conf_json_value_t *value) static uintptr_t -nxt_conf_json_print_object(u_char *pos, nxt_conf_json_value_t *value) +nxt_conf_json_print_object(u_char *pos, nxt_conf_json_value_t *value, + nxt_conf_json_pretty_t *pretty) { size_t len; nxt_lvlhsh_t *object; @@ -966,8 +1008,13 @@ nxt_conf_json_print_object(u_char *pos, nxt_conf_json_value_t *value) object = value->u.object; if (pos == NULL) { + /* {} */ len = 2; + if (pretty != NULL) { + pretty->level++; + } + for ( ;; ) { member = nxt_lvlhsh_each(object, &lhe); @@ -976,7 +1023,23 @@ nxt_conf_json_print_object(u_char *pos, nxt_conf_json_value_t *value) } len += nxt_conf_json_print_string(NULL, &member->name) + 1 - + nxt_conf_json_print_value(NULL, &member->value) + 1; + + nxt_conf_json_print_value(NULL, &member->value, pretty) + + 1; + + if (pretty != NULL) { + /* + * indentation, space after ":", new line, and possible + * additional empty line between non-empty objects + */ + len += pretty->level + 1 + 2 + 2; + } + } + + if (pretty != NULL) { + pretty->level--; + + /* indentation and new line */ + len += pretty->level + 2; } return len; @@ -988,12 +1051,26 @@ nxt_conf_json_print_object(u_char *pos, nxt_conf_json_value_t *value) if (member != NULL) { + if (pretty != NULL) { + pos = nxt_conf_json_newline(pos); + pretty->level++; + } + for ( ;; ) { + if (pretty != NULL) { + pos = nxt_conf_json_indentation(pos, pretty); + } + pos = (u_char *) nxt_conf_json_print_string(pos, &member->name); *pos++ = ':'; - pos = (u_char *) nxt_conf_json_print_value(pos, &member->value); + if (pretty != NULL) { + *pos++ = ' '; + } + + pos = (u_char *) nxt_conf_json_print_value(pos, &member->value, + pretty); member = nxt_lvlhsh_each(object, &lhe); @@ -1002,6 +1079,24 @@ nxt_conf_json_print_object(u_char *pos, nxt_conf_json_value_t *value) } *pos++ = ','; + + if (pretty != NULL) { + pos = nxt_conf_json_newline(pos); + + if (pretty->more_space) { + pretty->more_space = 0; + pos = nxt_conf_json_newline(pos); + } + } + } + + if (pretty != NULL) { + pos = nxt_conf_json_newline(pos); + + pretty->level--; + pos = nxt_conf_json_indentation(pos, pretty); + + pretty->more_space = 1; } } diff --git a/src/nxt_controller.c b/src/nxt_controller.c index 34be36fc..f02b1747 100644 --- a/src/nxt_controller.c +++ b/src/nxt_controller.c @@ -59,6 +59,8 @@ static nxt_int_t nxt_controller_request_body_parse(nxt_task_t *task, nxt_event_conn_t *c, nxt_controller_request_t *r); static nxt_int_t nxt_controller_response(nxt_task_t *task, nxt_event_conn_t *c, nxt_controller_response_t *resp); +static nxt_buf_t *nxt_controller_response_body(nxt_controller_response_t *resp, + nxt_mem_pool_t *pool); static nxt_http_fields_t nxt_controller_request_fields[] = { @@ -624,9 +626,7 @@ nxt_controller_response(nxt_task_t *task, nxt_event_conn_t *c, size_t size; nxt_buf_t *b; - size = sizeof("HTTP/1.0 " "\r\n\r\n") - 1 - + resp->status_line.length - + resp->json_string.length; + size = sizeof("HTTP/1.0 " "\r\n\r\n") - 1 + resp->status_line.length; b = nxt_buf_mem_alloc(c->mem_pool, size, 0); if (nxt_slow_path(b == NULL)) { @@ -639,25 +639,58 @@ nxt_controller_response(nxt_task_t *task, nxt_event_conn_t *c, b->mem.free = nxt_cpymem(b->mem.free, "\r\n\r\n", sizeof("\r\n\r\n") - 1); - if (resp->json_string.length > 0) { - b->mem.free = nxt_cpymem(b->mem.free, resp->json_string.start, - resp->json_string.length); + b->next = nxt_controller_response_body(resp, c->mem_pool); + + if (nxt_slow_path(b->next == NULL)) { + return NXT_ERROR; } c->write = b; c->write_state = &nxt_controller_conn_write_state; - if (resp->json_value != NULL) { - b = nxt_conf_json_print(resp->json_value, c->mem_pool); + nxt_event_conn_write(task->thread->engine, c); - if (b == NULL) { - return NXT_ERROR; + return NXT_OK; +} + + +static nxt_buf_t * +nxt_controller_response_body(nxt_controller_response_t *resp, + nxt_mem_pool_t *pool) +{ + size_t size; + nxt_buf_t *b; + nxt_conf_json_value_t *value; + nxt_conf_json_pretty_t pretty; + + if (resp->json_value) { + value = resp->json_value; + + } else { + value = nxt_conf_json_parse(resp->json_string.start, + resp->json_string.length, pool); + + if (nxt_slow_path(value == NULL)) { + return NULL; } + } + + nxt_memzero(&pretty, sizeof(nxt_conf_json_pretty_t)); + + size = nxt_conf_json_print_value(NULL, value, &pretty) + 2; - c->write->next = b; + b = nxt_buf_mem_alloc(pool, size, 0); + if (nxt_slow_path(b == NULL)) { + return NULL; } - nxt_event_conn_write(task->thread->engine, c); + nxt_memzero(&pretty, sizeof(nxt_conf_json_pretty_t)); - return NXT_OK; + b->mem.free = (u_char *) nxt_conf_json_print_value(b->mem.free, value, + &pretty); + + *b->mem.free++ = '\r'; + *b->mem.free++ = '\n'; + + return b; } |