コード例 #1
0
static ngx_int_t
ngx_http_subs_out_chain_append(ngx_http_request_t *r,
    ngx_http_subs_ctx_t *ctx, ngx_buf_t *b)
{
    size_t       len, capcity;

    if (b == NULL || ngx_buf_size(b) == 0) {
        return NGX_OK;
    }

    if (ctx->out_buf == NULL) {
       if (ngx_http_subs_get_chain_buf(r, ctx) != NGX_OK) {
           return NGX_ERROR;
       }
    }

    while (1) {

        len = (size_t) ngx_buf_size(b);
        if (len == 0) {
            break;
        }

        capcity = ctx->out_buf->end - ctx->out_buf->last;

        if (len <= capcity) {
            ctx->out_buf->last = ngx_copy(ctx->out_buf->last, b->pos, len);
            b->pos += len;
            break;

        } else {
            ctx->out_buf->last = ngx_copy(ctx->out_buf->last,
                                          b->pos, capcity);
        }

        b->pos += capcity;

        /* get more buffers */
        if (ngx_http_subs_get_chain_buf(r, ctx) != NGX_OK) {
            return NGX_ERROR;
        }
    }

    return NGX_OK;
}
static ngx_int_t 
ngx_http_subs_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
{
    ngx_int_t		           rc; 
    ngx_log_t                 *log;
    ngx_chain_t               *cl, *ll;
    ngx_http_subs_ctx_t       *ctx;
    ngx_http_subs_loc_conf_t  *slcf;

    ll = NULL;
    log = r->connection->log;

    slcf = ngx_http_get_module_loc_conf(r, ngx_http_subs_filter_module);
    if (slcf == NULL) {
        return ngx_http_next_body_filter(r, in);
    }

    ctx = ngx_http_get_module_ctx(r, ngx_http_subs_filter_module);
    if (ctx == NULL) {
        return ngx_http_next_body_filter(r, in);
    }

    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, log, 0, 
                   "http subs filter \"%V\"", &r->uri);

    if (in == NULL && ctx->busy == NULL) {
        return ngx_http_next_body_filter(r, in);
    }

    if (ngx_http_subs_body_filter_init_context(r, in) != NGX_OK){
        goto failed;
    }

    for (cl = ctx->in; cl; cl = cl->next) {

        if (cl->buf->last_buf || cl->buf->last_in_chain){
            ctx->last = 1;
        }

        /* TODO: check the flush tag */
        rc = ngx_http_subs_body_filter_process_buffer(r, cl->buf);

        if (rc == NGX_DECLINED) {
            continue;
        }
        else if (rc == NGX_ERROR) {
            goto failed;
        }

        if (cl->next != NULL) {
            continue;
        }

        if (ctx->last) {

            /* copy line_in to ctx->out. */
            if (ngx_buf_size(ctx->line_in) > 0) {

                ngx_log_debug0(NGX_LOG_DEBUG_HTTP, log, 0,
                        "[subs_filter] Lost last linefeed, output anyway.");

                if (ngx_http_subs_out_chain_append(r, ctx, ctx->line_in)
                    != NGX_OK) {
                    goto failed;
                }
            }

            if (ctx->out_buf == NULL) {
                if (ngx_http_subs_get_chain_buf(r, ctx) != NGX_OK) {
                    goto failed;
                }
            }

            ctx->out_buf->sync = 1;
            ctx->out_buf->last_buf = (r == r->main) ? 1 : 0;
            ctx->out_buf->last_in_chain = cl->buf->last_in_chain;

            break;
        }
    }

    /* It doesn't output anything, return */
    if ((ctx->last_out == &ctx->out) && (ctx->busy == NULL)) {
        return NGX_OK;
    }

    ngx_http_subs_body_filter_clean_context(r, ctx);

    return ngx_http_subs_output(r, ctx, in);

failed:

    ngx_http_subs_body_filter_clean_context(r, ctx);

    ngx_log_error(NGX_LOG_ERR, log, 0, 
                  "[subs_filter] ngx_http_subs_body_filter error.");

    return NGX_ERROR;
}