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);
}
Exemple #2
0
/**
 * 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);
}