ParsedResponseLine ParsedResponseLine::create_alias( Transaction transaction, const char* raw, size_t raw_length, const char* protocol, size_t protocol_length, const char* status, size_t status_length, const char* message, size_t message_length ) { ib_parsed_resp_line_t *ib_prl; Internal::throw_if_error( ib_parsed_resp_line_create( transaction.ib(), &ib_prl, raw, raw_length, protocol, protocol_length, status, status_length, message, message_length ) ); return ParsedResponseLine(ib_prl); }
/** * A header filter to intercept response line and headers and feed to Ironbee. * * @param[in] r The nginx request object. * @return status propagated from next filter, or Error */ static ngx_int_t ironbee_headers_out(ngx_http_request_t *r) { ngx_log_t *prev_log; ngxib_req_ctx *ctx; ib_parsed_resp_line_t *rline; ib_parsed_header_wrapper_t *ibhdrs; ib_status_t rc; ngx_list_part_t *part; ngx_table_elt_t *hdr; unsigned int i; char proto[12]; char *status; const char *reason; int status_len, reason_len; /* FIXME: needs more logic here to catch error pages */ if (r->internal) return ngx_http_next_header_filter(r); ctx = ngx_http_get_module_ctx(r, ngx_ironbee_module); assert((ctx != NULL) && (ctx->tx != NULL)); prev_log = ngxib_log(r->connection->log); ngx_regex_malloc_init(r->pool); /* Notify Ironbee of request line and headers */ sprintf(proto, "HTTP/%d.%d", r->http_major, r->http_minor); if (r->headers_out.status_line.len) { status = (char*)r->headers_out.status_line.data; status_len = strcspn(status, " \t"); for (reason = status+status_len; isspace(*reason); ++reason); reason_len = r->headers_out.status_line.len - (reason-status); } else if (r->headers_out.status >= 100 && r->headers_out.status < 600) { status = ngx_palloc(r->pool, 4); /* cast to int, because ngx_int_t requires different format args * on different platforms. We're already limited to 3-digit numbers. */ sprintf(status, "%d", (int)r->headers_out.status); status_len = 3; reason = ""; reason_len = 0; } else { ib_log_error_tx(ctx->tx, "Ironbee: bogus response status %d", (int)r->headers_out.status); cleanup_return(prev_log) NGX_ERROR; } rc = ib_parsed_resp_line_create(ctx->tx, &rline, NULL, 0, proto, strlen(proto), status, status_len, reason, reason_len); if (rc != IB_OK) cleanup_return(prev_log) NGX_ERROR; ib_state_notify_response_started(ironbee, ctx->tx, rline); rc = ib_parsed_name_value_pair_list_wrapper_create(&ibhdrs, ctx->tx); if (rc != IB_OK) cleanup_return(prev_log) NGX_ERROR; for (part = &r->headers_out.headers.part; part != NULL; part = part->next) { hdr = part->elts; for (i = 0; i < part->nelts; ++i) { ib_parsed_name_value_pair_list_add(ibhdrs, (const char*)hdr->key.data, hdr->key.len, (const char*)hdr->value.data, hdr->value.len); ++hdr; } } /* Ironbee currently crashes if called here with no headers, * even perfectly correctly on a 204/304 response. */ if (ibhdrs->size > 0) { rc = ib_state_notify_response_header_data(ironbee, ctx->tx, ibhdrs); if (rc != IB_OK) cleanup_return(prev_log) NGX_ERROR; } rc = ib_state_notify_response_header_finished(ironbee, ctx->tx); if (rc != IB_OK) cleanup_return(prev_log) NGX_ERROR; ctx->hdrs_out = 1; cleanup_return(prev_log) ngx_http_next_header_filter(r); }