#ifndef DDEBUG #define DDEBUG 0 #endif #include "ddebug.h" #include "ngx_http_rds_json_handler.h" #include "ngx_http_rds_json_util.h" ngx_int_t ngx_http_rds_json_ret_handler(ngx_http_request_t *r) { ngx_chain_t *cl; ngx_buf_t *b; size_t len; ngx_str_t errstr; ngx_int_t rc; uintptr_t escape = 0; ngx_str_t *values = NULL; uintptr_t *escapes = NULL; ngx_uint_t i; ngx_http_rds_json_property_t *prop = NULL; ngx_http_rds_json_loc_conf_t *conf; dd("entered ret handler"); conf = ngx_http_get_module_loc_conf(r, ngx_http_rds_json_filter_module); /* evaluate the final value of conf->errstr */ if (ngx_http_complex_value(r, conf->errstr, &errstr) != NGX_OK) { return NGX_ERROR; } /* calculate the buffer size */ len = sizeof("{") - 1 + conf->errcode_key.len + sizeof(":") - 1 + conf->errcode.len + sizeof("}") - 1 ; if (errstr.len) { escape = ngx_http_rds_json_escape_json_str(NULL, errstr.data, errstr.len); len += sizeof(",") - 1 + conf->errstr_key.len + sizeof(":") - 1 + sizeof("\"") - 1 + errstr.len + escape + sizeof("\"") - 1 ; } if (conf->success.len) { len += conf->success.len + sizeof(":,") - 1; if (ngx_atoi(conf->errcode.data, conf->errcode.len) == 0) { len += sizeof("true") - 1; } else { len += sizeof("false") - 1; } } 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); len += sizeof(":\"\",") - 1 + prop[i].key.len + values[i].len + escapes[i]; } } /* create the buffer */ cl = ngx_alloc_chain_link(r->pool); if (cl == NULL) { return NGX_ERROR; } b = ngx_create_temp_buf(r->pool, len); if (b == NULL) { return NGX_ERROR; } if (r == r->main) { b->last_buf = 1; } cl->buf = b; cl->next = NULL; /* copy data over to the buffer */ *b->last++ = '{'; b->last = ngx_copy(b->last, conf->errcode_key.data, conf->errcode_key.len); *b->last++ = ':'; b->last = ngx_copy(b->last, conf->errcode.data, conf->errcode.len); if (errstr.len) { *b->last++ = ','; b->last = ngx_copy(b->last, conf->errstr_key.data, conf->errstr_key.len); *b->last++ = ':'; *b->last++ = '"'; if (escape == 0) { b->last = ngx_copy(b->last, errstr.data, errstr.len); } else { b->last = (u_char *) ngx_http_rds_json_escape_json_str(b->last, errstr.data, errstr.len); } *b->last++ = '"'; } if (conf->success.len) { *b->last++ = ','; b->last = ngx_copy(b->last, conf->success.data, conf->success.len); if (ngx_atoi(conf->errcode.data, conf->errcode.len) == 0) { b->last = ngx_copy_literal(b->last, ":true"); } else { b->last = ngx_copy_literal(b->last, ":false"); } } if (conf->user_props) { for (i = 0; i < conf->user_props->nelts; i++) { *b->last++ = ','; b->last = ngx_copy(b->last, prop[i].key.data, prop[i].key.len); *b->last++ = ':'; *b->last++ = '"'; if (escapes[i] == 0) { b->last = ngx_copy(b->last, values[i].data, values[i].len); } else { b->last = (u_char *) ngx_http_rds_json_escape_json_str(b->last, values[i].data, values[i].len); } *b->last++ = '"'; } } *b->last++ = '}'; if (b->last != b->end) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "rds_json: rds_json_ret: buffer error"); return NGX_ERROR; } /* send headers */ r->headers_out.status = NGX_HTTP_OK; r->headers_out.content_type = conf->content_type; r->headers_out.content_type_len = conf->content_type.len; rc = ngx_http_send_header(r); if (rc == NGX_ERROR || rc >= NGX_HTTP_SPECIAL_RESPONSE) { return rc; } dd("output filter..."); return ngx_http_output_filter(r, cl); }