Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

now we postpone the header sending action after we parse the RDS head…

…er. so errors in RDS headers can result in proper 500 response headers. thanks Piotr Sikora for suggesting this.
  • Loading branch information...
commit ec5f1a90683186b37ed4ec3fca28b22bf85e7eb4 1 parent 952c73d
@agentzh agentzh authored
View
23 src/ngx_http_rds_json_filter_module.c
@@ -118,11 +118,15 @@ ngx_http_rds_json_header_filter(ngx_http_request_t *r)
* {"errcode":403,"error":"Permission denied"}
* for HTTP error pages? */
if (r->headers_out.status != NGX_HTTP_OK) {
- dd("status is not OK: %d, skipping", r->headers_out.status);
+ ngx_http_set_ctx(r, NULL, ngx_http_rds_json_filter_module);
+
+ dd("status is not OK: %d, skipping", (int) r->headers_out.status);
return ngx_http_rds_json_next_header_filter(r);
}
+ /* r->headers_out.status = 0; */
+
conf = ngx_http_get_module_loc_conf(r, ngx_http_rds_json_filter_module);
if ( ! conf->enabled) {
@@ -146,6 +150,8 @@ ngx_http_rds_json_header_filter(ngx_http_request_t *r)
ctx->state = state_expect_header;
+ ctx->header_sent = 0;
+
/* set by ngx_pcalloc
* ctx->busy_bufs = NULL
* ctx->free_bufs = NULL
@@ -163,9 +169,8 @@ ngx_http_rds_json_header_filter(ngx_http_request_t *r)
r->filter_need_in_memory = 1;
- /* TODO: only send the header when we actually
- * see the RDS header */
- return ngx_http_rds_json_next_header_filter(r);
+ /* we do postpone the header sending to the body filter */
+ return NGX_OK;
}
@@ -211,6 +216,16 @@ ngx_http_rds_json_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
"rds_json: invalid internal state: %d",
ctx->state);
+ if (! ctx->header_sent) {
+ ctx->header_sent = 1;
+
+ r->headers_out.status = NGX_HTTP_INTERNAL_SERVER_ERROR;
+ ngx_http_send_header(r);
+ ngx_http_send_special(r, NGX_HTTP_LAST);
+
+ return NGX_ERROR;
+ }
+
return NGX_ERROR;
}
View
2  src/ngx_http_rds_json_filter_module.h
@@ -69,6 +69,8 @@ typedef struct {
uint32_t field_data_rest;
+ ngx_flag_t header_sent;
+
} ngx_http_rds_json_ctx_t;
View
40 src/ngx_http_rds_json_processor.c
@@ -34,7 +34,7 @@ ngx_http_rds_json_process_header(ngx_http_request_t *r,
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
"rds_json: process header: buf from "
"upstream not in memory");
- return NGX_ERROR;
+ goto invalid;
}
in = in->next;
@@ -49,7 +49,7 @@ ngx_http_rds_json_process_header(ngx_http_request_t *r,
rc = ngx_http_rds_parse_header(r, b, &header);
if (rc != NGX_OK) {
- return NGX_ERROR;
+ goto invalid;
}
if (header.col_count == 0) {
@@ -59,11 +59,22 @@ ngx_http_rds_json_process_header(ngx_http_request_t *r,
if (b->pos != b->last) {
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
"rds_json: header: there's unexpected remaining data in the buf");
- return NGX_ERROR;
+ goto invalid;
}
ctx->state = state_done;
+ /* now we send the postponed response header */
+ if (! ctx->header_sent) {
+ ctx->header_sent = 1;
+
+ rc = ngx_http_rds_json_next_header_filter(r);
+
+ if (rc == NGX_ERROR || rc >= NGX_HTTP_SPECIAL_RESPONSE) {
+ return rc;
+ }
+ }
+
rc = ngx_http_rds_json_output_header(r, ctx, &header);
if (rc == NGX_ERROR || rc >= NGX_HTTP_SPECIAL_RESPONSE) {
@@ -79,15 +90,36 @@ ngx_http_rds_json_process_header(ngx_http_request_t *r,
header.col_count * sizeof(ngx_http_rds_column_t));
if (ctx->cols == NULL) {
- return NGX_ERROR;
+ goto invalid;
}
ctx->state = state_expect_col;
ctx->cur_col = 0;
ctx->col_count = header.col_count;
+ /* now we send the postponed response header */
+ rc = ngx_http_rds_json_next_header_filter(r);
+ if (rc == NGX_ERROR || rc >= NGX_HTTP_SPECIAL_RESPONSE) {
+ return rc;
+ }
+
return ngx_http_rds_json_process_col(r,
b->pos == b->last ? in->next : in, ctx);
+
+invalid:
+
+ dd("return 500");
+ if (! ctx->header_sent) {
+ ctx->header_sent = 1;
+
+ r->headers_out.status = NGX_HTTP_INTERNAL_SERVER_ERROR;
+ ngx_http_send_header(r);
+ ngx_http_send_special(r, NGX_HTTP_LAST);
+
+ return NGX_ERROR;
+ }
+
+ return NGX_ERROR;
}
View
1  test/t/sanity.t
@@ -4,6 +4,7 @@ use lib 'lib';
use Test::Nginx::Socket;
repeat_each(10);
+#repeat_each(1);
plan tests => repeat_each() * 2 * blocks() + 2 * repeat_each() * 3;
Please sign in to comment.
Something went wrong with that request. Please try again.