示例#1
0
/**
 * nginx handler to feed request body (if any) to IronBee
 *
 * @param[in] r   the nginx request object
 * @return    NGX_DECLINED for normal operation
 * @return    NGX_DONE if body is not yet available (processing will resume
 *            on new data)
 * @return    Error status if set by IronBee on sight of request data.
 */
ngx_int_t ngxib_handler(ngx_http_request_t *r)
{
    ngx_chain_t *link;
    ngxib_req_ctx *ctx;
    ngx_int_t rv = NGX_DECLINED;
    ngx_http_request_body_t *rb;
    /* Don't process internal requests */
    if (r->internal)
        return rv;

    ctx = ngx_http_get_module_ctx(r, ngx_ironbee_module);
    if (ctx->body_done)
        return rv;

    /* We already completed handling of no-body requests
     * when we looked at headers
     */
    if (!ngxib_has_request_body(r, ctx))
        return rv;

    ngx_regex_malloc_init(r->pool);

    /* We can now read the body.
     * This may come asynchronously in many chunks, so we need
     * to check for AGAIN and return DONE if waiting.
     * We pass it a handler to go round again while waiting.
     *
     * TODO: figure out how to pass data to ironbee asynchronously
     */
    rv = ngx_http_read_client_request_body(r, ngxib_post_handler);
    if (rv == NGX_AGAIN) {
        ctx->body_wait = 1;
        cleanup_return NGX_DONE;
    }

    /* We now have the request body.  Feed it to ironbee */
    rb = r->request_body;
    if (!rb) {
        ib_log_error_tx(ctx->tx, "Failed to read request body.");
        cleanup_return NGX_HTTP_INTERNAL_SERVER_ERROR;
    }
    if (!rb->bufs) {
        /* I think this shouldn't happen */
        /* But rethink if this turns up in logs when all is fine */
        ib_log_error_tx(ctx->tx, "Probable error reading request body.");
    }

    if (rb->temp_file && (rb->temp_file->file.fd != NGX_INVALID_FILE)) {
        /* Reader has put request body in temp file */
        off_t count = 0;
        u_char buf[BUFSIZE];
        size_t buf_len;
        ib_log_debug_tx(ctx->tx, "Reading request body in temp file.");
        while (buf_len = ngx_read_file(&rb->temp_file->file,
                         buf, BUFSIZE, count),
               buf_len > 0) {
            ib_log_debug_tx(ctx->tx, "Feeding %zd bytes request data to ironbee.",
                            buf_len);
            ib_state_notify_request_body_data(ctx->tx->ib, ctx->tx,
                                              (const char*)buf, buf_len);
            count += buf_len;
        }
        if ((int)buf_len == NGX_ERROR) {
            ib_log_error_tx(ctx->tx, "Failed to read request body in temp file.");
        }
    }

    for (link = rb->bufs; link != NULL; link = link->next) {
        size_t len = (link->buf->last - link->buf->pos);
        ib_log_debug_tx(ctx->tx, "Feeding %zd bytes request data to ironbee.",
                        len);
        if (len > 0) {
            ib_state_notify_request_body_data(ctx->tx->ib, ctx->tx,
                                              (const char*)link->buf->pos, len);
        }
    }
    ctx->body_done = 1;
    ib_state_notify_request_finished(ctx->tx->ib, ctx->tx);

    /* If IronBee signaled an error, we can return it */
    if (STATUS_IS_ERROR(ctx->status)) {
        rv = ctx->status;
        ctx->internal_errordoc = 1;
        ib_log_error_tx(ctx->tx, "IronBee set %d reading request body.", (int)rv);
    }

    cleanup_return rv;
}
示例#2
0
/**
 * nginx handler to feed request body (if any) to Ironbee
 *
 * @param[in] r   the nginx request object
 * @return    NGX_DECLINED for normal operation
 * @return    NGX_DONE if body is not yet available (processing will restart
 *            on new data)
 * @return    Error status if set by Ironbee on sight of request data.
 */
ngx_int_t ngxib_handler(ngx_http_request_t *r)
{
    ngx_log_t *prev_log;
    ib_txdata_t itxdata;
    ngx_chain_t *link;
    ngxib_req_ctx *ctx;
    ngx_int_t rv = NGX_DECLINED;
    ngx_http_request_body_t *rb;
    /* Don't process internal requests */
    if (r->internal)
        return rv;

    ctx = ngx_http_get_module_ctx(r, ngx_ironbee_module);
    if (ctx->body_done)
        return rv;

    if (!has_request_body(r, ctx))
        return rv;

    prev_log = ngxib_log(r->connection->log);
    ngx_regex_malloc_init(r->pool);

    /* We can now read the body.
     * This may come asynchronously in many chunks, so we need
     * to check for AGAIN and return DONE if waiting.
     * We pass it a handler to go round again while waiting.
     *
     * TODO: figure out how to pass data to ironbee asynchronously
     */
    rv = ngx_http_read_client_request_body(r, ngxib_post_handler);
    if (rv == NGX_AGAIN) {
        ctx->body_wait = 1;
        cleanup_return(prev_log) NGX_DONE;
    }

    /* We now have the request body.  Feed it to ironbee */
    rb = r->request_body;
    if (!rb) {
        ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
                      "Error reading request body");
        cleanup_return(prev_log) NGX_HTTP_INTERNAL_SERVER_ERROR;
    }
    if (!rb->bufs) {
        /* I think this shouldn't happen */
        /* But rethink if this turns up in logs when all is fine */
        ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
                      "Probable error reading request body");
    }

    if (rb->temp_file && (rb->temp_file->file.fd != NGX_INVALID_FILE)) {
        /* Reader has put request body in temp file */
        off_t count = 0;
        u_char buf[BUFSIZE];
        ngx_log_error(NGX_LOG_DEBUG, r->connection->log, 0,
                      "Reading request body in temp file");
        while (itxdata.dlen = ngx_read_file(&rb->temp_file->file,
                                            buf, BUFSIZE, count),
               (int)itxdata.dlen > 0) {
            itxdata.data = buf;
            ngx_log_error(NGX_LOG_DEBUG, r->connection->log, 0,
                          "Feeding %d bytes request data to ironbee", itxdata.dlen);
            ib_state_notify_request_body_data(ngxib_engine(), ctx->tx, &itxdata);
            count += itxdata.dlen;
        }
        if ((int)itxdata.dlen == NGX_ERROR) {
            ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
                          "Error reading request body in temp file");
        }
    }

    for (link = rb->bufs; link != NULL; link = link->next) {
        itxdata.data = link->buf->pos;
        itxdata.dlen = (link->buf->last - link->buf->pos);
        ngx_log_error(NGX_LOG_DEBUG, r->connection->log, 0,
                      "Feeding %d bytes request data to ironbee", itxdata.dlen);
        if (itxdata.dlen > 0) {
            ib_state_notify_request_body_data(ngxib_engine(), ctx->tx, &itxdata);
        }
    }
    ctx->body_done = 1;
    ib_state_notify_request_finished(ngxib_engine(), ctx->tx);

    /* If Ironbee signalled an error, we can return it */
    if (STATUS_IS_ERROR(ctx->status)) {
        rv = ctx->status;
        ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
                      "Ironbee set %d reading request body", rv);
    }

    cleanup_return(prev_log) rv;
}