Permalink
Browse files

implemented the rds_json_user_property directive.

  • Loading branch information...
1 parent fc9cce8 commit bc6b2f047f28d42cc75d0f8e7dc1aeaedb8f2d53 @agentzh agentzh committed Sep 15, 2011
Showing with 312 additions and 5 deletions.
  1. +14 −0 README
  2. +97 −3 src/ngx_http_rds_json_filter_module.c
  3. +7 −0 src/ngx_http_rds_json_filter_module.h
  4. +105 −2 src/ngx_http_rds_json_output.c
  5. +89 −0 t/property.t
View
14 README
@@ -105,6 +105,20 @@ Directives
Specify the top-level object property name used in the JSON output
for indicating success or false of the query.
+ rds_json_user_property
+ syntax: rds_json_user_property <key> <value>
+ default: no
+
+ Specify additonal user properties for the top-level object
+ of the JSON output.
+
+ Multiple instances of this directives are allowed in a single scope.
+
+ Nginx variables are supported in the <value> argument.
+
+ Both of the <key> and <value> arguments will be automatically
+ quoted according to JSON strings' notation.
+
rds_json_ret
syntax: rds_json_ret <error-code> <descrption>
default: no
@@ -40,6 +40,8 @@ static char * ngx_http_rds_json_root(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
static char * ngx_http_rds_json_success_property(ngx_conf_t *cf,
ngx_command_t *cmd, void *conf);
+static char * ngx_http_rds_json_user_property(ngx_conf_t *cf,
+ ngx_command_t *cmd, void *conf);
static ngx_command_t ngx_http_rds_json_commands[] = {
@@ -71,6 +73,15 @@ static ngx_command_t ngx_http_rds_json_commands[] = {
0,
NULL },
+ { ngx_string("rds_json_user_property"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF
+ |NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF
+ |NGX_CONF_TAKE2,
+ ngx_http_rds_json_user_property,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ 0,
+ NULL },
+
{ ngx_string("rds_json_format"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF
|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF
@@ -333,6 +344,7 @@ ngx_http_rds_json_create_conf(ngx_conf_t *cf)
* conf->content_type = { 0, NULL };
* conf->root = { 0, NULL };
* conf->success = { 0, NULL };
+ * conf->user_props = NULL;
* conf->errcode = { 0, NULL };
* conf->errstr = NULL;
*/
@@ -366,7 +378,11 @@ ngx_http_rds_json_merge_conf(ngx_conf_t *cf, void *parent, void *child)
ngx_conf_merge_str_value(conf->success, prev->success,
"");
- if (conf->success.len && conf->root.len == 0) {
+ if (conf->user_props == NULL) {
+ conf->user_props = prev->user_props;
+ }
+
+ if (conf->root.len == 0 && (conf->success.len || conf->user_props)) {
ngx_str_set(&conf->root, "\"data\"");
}
@@ -493,7 +509,7 @@ ngx_http_rds_json_root(ngx_conf_t *cf, ngx_command_t *cmd,
*p++ = '"';
if (p - jlcf->root.data != (ssize_t) jlcf->root.len) {
- return " sees buffer error";
+ return "sees buffer error";
}
return NGX_CONF_OK;
@@ -544,7 +560,85 @@ ngx_http_rds_json_success_property(ngx_conf_t *cf, ngx_command_t *cmd,
*p++ = '"';
if (p - jlcf->success.data != (ssize_t) jlcf->success.len) {
- return " sees buffer error";
+ return "sees buffer error";
+ }
+
+ return NGX_CONF_OK;
+}
+
+
+static char *
+ngx_http_rds_json_user_property(ngx_conf_t *cf, ngx_command_t *cmd,
+ void *conf)
+{
+ ngx_http_rds_json_conf_t *jlcf = conf;
+ ngx_str_t *value;
+ ngx_http_rds_json_property_t *prop;
+ uintptr_t escape;
+ u_char *p;
+
+ ngx_http_compile_complex_value_t ccv;
+
+ value = cf->args->elts;
+
+ if (value[1].len == 0) {
+ return "takes an empty key";
+ }
+
+ if (value[2].len == 0) {
+ return "takes an empty value";
+ }
+
+ if (jlcf->user_props == NULL) {
+ jlcf->user_props = ngx_array_create(cf->pool, 4,
+ sizeof(ngx_http_rds_json_property_t));
+
+ if (jlcf->user_props == NULL) {
+ return NGX_CONF_ERROR;
+ }
+ }
+
+ prop = ngx_array_push(jlcf->user_props);
+
+ /* process the user property key */
+
+ escape = ngx_http_rds_json_escape_json_str(NULL, value[1].data,
+ value[1].len);
+
+ prop->key.len = value[1].len + escape + sizeof("\"\"") - 1;
+
+ p = ngx_palloc(cf->pool, prop->key.len);
+ if (p == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
+ prop->key.data = p;
+
+ *p++ = '"';
+
+ if (escape == 0) {
+ p = ngx_copy(p, value[1].data, value[1].len);
+
+ } else {
+ p = (u_char *) ngx_http_rds_json_escape_json_str(p, value[1].data,
+ value[1].len);
+ }
+
+ *p++ = '"';
+
+ if (p - prop->key.data != (ssize_t) prop->key.len) {
+ return "sees buffer error";
+ }
+
+ /* process the user property value */
+
+ ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
+ ccv.cf = cf;
+ ccv.value = &value[2];
+ ccv.complex_value = &prop->value;
+
+ if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
+ return NGX_CONF_ERROR;
}
return NGX_CONF_OK;
@@ -34,12 +34,19 @@ typedef enum {
typedef struct {
+ ngx_str_t key;
+ ngx_http_complex_value_t value;
+} ngx_http_rds_json_property_t;
+
+
+typedef struct {
ngx_flag_t enabled;
ngx_uint_t format;
ngx_str_t content_type;
ngx_str_t root; /* rds_json_root key */
ngx_str_t success; /* rds_json_success_property
* key */
+ ngx_array_t *user_props; /* rds_json_user_property */
size_t buf_size;
@@ -118,7 +118,11 @@ ngx_http_rds_json_output_header(ngx_http_request_t *r,
size_t size;
uintptr_t escape;
unsigned last_buf = 0;
+ ngx_uint_t i;
+ ngx_str_t *values = NULL;
+ uintptr_t *escapes = NULL;
+ ngx_http_rds_json_property_t *prop = NULL;
ngx_http_rds_json_conf_t *conf;
conf = ngx_http_get_module_loc_conf(r, ngx_http_rds_json_filter_module);
@@ -140,6 +144,34 @@ ngx_http_rds_json_output_header(ngx_http_request_t *r,
}
}
+ if (conf->user_props) {
+ values = ngx_pnalloc(r->pool,
+ conf->user_props->nelts * (sizeof(ngx_str_t) +
+ sizeof(uintptr_t)));
+
+ if (values == NULL) {
+ return NGX_ERROR;
+ }
+
+ escapes = (uintptr_t *) ((u_char *) values +
+ conf->user_props->nelts * sizeof(ngx_str_t));
+
+ prop = conf->user_props->elts;
+ for (i = 0; i < conf->user_props->nelts; i++) {
+ if (ngx_http_complex_value(r, &prop[i].value, &values[i])
+ != NGX_OK)
+ {
+ return NGX_ERROR;
+ }
+
+ escapes[i] = ngx_http_rds_json_escape_json_str(NULL, values[i].data,
+ values[i].len);
+
+ size += sizeof(":\"\",") - 1 + prop[i].key.len + values[i].len
+ + escapes[i];
+ }
+ }
+
if (header->errstr.len) {
escape = ngx_http_rds_json_escape_json_str(NULL, header->errstr.data,
header->errstr.len);
@@ -188,6 +220,25 @@ ngx_http_rds_json_output_header(ngx_http_request_t *r,
}
}
+ if (conf->user_props) {
+ for (i = 0; i < conf->user_props->nelts; i++) {
+ last = ngx_copy(last, prop[i].key.data, prop[i].key.len);
+ *last++ = ':';
+ *last++ = '"';
+
+ if (escapes[i] == 0) {
+ last = ngx_copy(last, values[i].data, values[i].len);
+
+ } else {
+ last = (u_char *) ngx_http_rds_json_escape_json_str(last,
+ values[i].data, values[i].len);
+ }
+
+ *last++ = '"';
+ *last++ = ',';
+ }
+ }
+
last = ngx_copy_literal(last, "\"errcode\":");
last = ngx_snprintf(last, NGX_UINT16_LEN, "%uD",
@@ -244,15 +295,48 @@ ngx_int_t
ngx_http_rds_json_output_props(ngx_http_request_t *r,
ngx_http_rds_json_ctx_t *ctx, ngx_http_rds_json_conf_t *conf)
{
- size_t size;
- u_char *pos, *last;
+ size_t size;
+ u_char *pos, *last;
+ ngx_uint_t i;
+ ngx_str_t *values = NULL;
+ uintptr_t *escapes = NULL;
+
+ ngx_http_rds_json_property_t *prop = NULL;
size = sizeof("{:") - 1 + conf->root.len;
if (conf->success.len) {
size += sizeof(",:true") - 1 + conf->success.len;
}
+ if (conf->user_props) {
+ values = ngx_pnalloc(r->pool,
+ conf->user_props->nelts * (sizeof(ngx_str_t) +
+ sizeof(uintptr_t)));
+
+ if (values == NULL) {
+ return NGX_ERROR;
+ }
+
+ escapes = (uintptr_t *) ((u_char *) values +
+ conf->user_props->nelts * sizeof(ngx_str_t));
+
+ prop = conf->user_props->elts;
+ for (i = 0; i < conf->user_props->nelts; i++) {
+ if (ngx_http_complex_value(r, &prop[i].value, &values[i])
+ != NGX_OK)
+ {
+ return NGX_ERROR;
+ }
+
+ escapes[i] = ngx_http_rds_json_escape_json_str(NULL, values[i].data,
+ values[i].len);
+
+ size += sizeof(":\"\",") - 1 + prop[i].key.len + values[i].len
+ + escapes[i];
+ }
+ }
+
pos = ngx_http_rds_json_request_mem(r, ctx, size);
if (pos == NULL) {
return NGX_ERROR;
@@ -267,6 +351,25 @@ ngx_http_rds_json_output_props(ngx_http_request_t *r,
last = ngx_copy_literal(last, ":true,");
}
+ if (conf->user_props) {
+ for (i = 0; i < conf->user_props->nelts; i++) {
+ last = ngx_copy(last, prop[i].key.data, prop[i].key.len);
+ *last++ = ':';
+ *last++ = '"';
+
+ if (escapes[i] == 0) {
+ last = ngx_copy(last, values[i].data, values[i].len);
+
+ } else {
+ last = (u_char *) ngx_http_rds_json_escape_json_str(last,
+ values[i].data, values[i].len);
+ }
+
+ *last++ = '"';
+ *last++ = ',';
+ }
+ }
+
last = ngx_copy(last, conf->root.data, conf->root.len);
*last++ = ':';
Oops, something went wrong.

0 comments on commit bc6b2f0

Please sign in to comment.