/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "httpd.h"
#include "http_request.h"
#include "apr_strings.h"
#include "apr_portable.h"
#include "apr_pools.h"
#include "apr_file_io.h"
#include "util_script.h"
#include "fcgid_bridge.h"
#include "fcgid_pm.h"
#include "fcgid_proctbl.h"
#include "fcgid_proc.h"
#include "fcgid_conf.h"
#include "fcgid_spawn_ctl.h"
#include "fcgid_protocol.h"
#include "fcgid_bucket.h"
#define FCGID_APPLY_TRY_COUNT 2
#define FCGID_REQUEST_COUNT 32

static int g_variables_inited = 0;
static int g_busy_timeout;
static int g_connect_timeout;
static int g_comm_timeout;
static int g_max_requests_per_process;

static fcgid_procnode *apply_free_procnode(server_rec * main_server,
                                           fcgid_command * command)
{
    /* Scan idle list, find a node match inode, deviceid and groupid
       If there is no one there, return NULL */
    fcgid_procnode *previous_node, *current_node, *next_node;
    fcgid_procnode *busy_list_header, *proc_table;
    apr_ino_t inode = command->inode;
    apr_dev_t deviceid = command->deviceid;
    uid_t uid = command->uid;
    gid_t gid = command->gid;
    apr_size_t share_grp_id = command->share_grp_id;
    char *virtualhost = command->virtualhost;

    proc_table = proctable_get_table_array();
    previous_node = proctable_get_idle_list();
    busy_list_header = proctable_get_busy_list();

    safe_lock(main_server);
    current_node = &proc_table[previous_node->next_index];
    while (current_node != proc_table) {
        next_node = &proc_table[current_node->next_index];

        if (current_node->inode == inode
            && current_node->deviceid == deviceid
            && current_node->share_grp_id == share_grp_id
            && current_node->virtualhost == virtualhost
            && current_node->uid == uid && current_node->gid == gid) {
            /* Unlink from idle list */
            previous_node->next_index = current_node->next_index;

            /* Link to busy list */
            current_node->next_index = busy_list_header->next_index;
            busy_list_header->next_index = current_node - proc_table;

            safe_unlock(main_server);
            return current_node;
        } else
            previous_node = current_node;

        current_node = next_node;
    }
    safe_unlock(main_server);

    /* Found nothing */
    return NULL;
}

static void
return_procnode(server_rec * main_server,
                fcgid_procnode * procnode, int communicate_error)
{
    fcgid_procnode *previous_node, *current_node, *next_node;
    fcgid_procnode *proc_table = proctable_get_table_array();
    fcgid_procnode *error_list_header = proctable_get_error_list();
    fcgid_procnode *idle_list_header = proctable_get_idle_list();
    fcgid_procnode *busy_list_header = proctable_get_busy_list();

    safe_lock(main_server);

    /* Unlink the node from busy list first */
    previous_node = busy_list_header;
    current_node = &proc_table[previous_node->next_index];
    while (current_node != proc_table) {
        next_node = &proc_table[current_node->next_index];
        if (current_node == procnode) {
            /* Unlink from busy list */
            previous_node->next_index = current_node->next_index;
            break;
        } else
            previous_node = current_node;
        current_node = next_node;
    }

    /* Return to error list or idle list */
    if (communicate_error) {
        /* Link to error list */
        procnode->next_index = error_list_header->next_index;
        error_list_header->next_index = procnode - proc_table;
    } else {
        /* Link to idle list */
        procnode->next_index = idle_list_header->next_index;
        idle_list_header->next_index = procnode - proc_table;
    }

    safe_unlock(main_server);
}

static int
count_busy_processes(server_rec * main_server, fcgid_command * command)
{
    int result = 0;
    fcgid_procnode *previous_node, *current_node, *next_node;
    fcgid_procnode *proc_table = proctable_get_table_array();
    fcgid_procnode *busy_list_header = proctable_get_busy_list();

    safe_lock(main_server);

    previous_node = busy_list_header;
    current_node = &proc_table[previous_node->next_index];
    while (current_node != proc_table) {
        if (current_node->inode == command->inode
            && current_node->deviceid == command->deviceid
            && current_node->share_grp_id == command->share_grp_id
            && current_node->virtualhost == command->virtualhost
            && current_node->uid == command->uid
            && current_node->gid == command->gid) {
            result++;
        }
        next_node = &proc_table[current_node->next_index];
        current_node = next_node;
    }

    safe_unlock(main_server);

    return result;
}

apr_status_t bucket_ctx_cleanup(void *thectx)
{
    /* Cleanup jobs:
       1. Free bucket buffer
       2. Return procnode
       NOTE: ipc will be clean when request pool cleanup, so I don't need to close it here
     */
    fcgid_bucket_ctx *ctx = (fcgid_bucket_ctx *) thectx;
    server_rec *main_server = ctx->ipc.request->server;

    /* Free bucket buffer */
    if (ctx->buffer) {
        apr_bucket_destroy(ctx->buffer);
        ctx->buffer = NULL;
    }

    proc_close_ipc(main_server, &ctx->ipc);

    if (ctx->procnode) {
        /* Return procnode
           I will return this slot to idle(or error) list except:
           I take too much time on this request( greater than get_busy_timeout() ),
           so the process manager may have put this slot from busy list to error
           list, and the contain of this slot may have been modified
           In this case I will do nothing and return, let the process manager 
           do the job   
         */
        int dt =
            apr_time_sec(apr_time_now()) - apr_time_sec(ctx->active_time);
        if (dt > g_busy_timeout) {
            /* Do nothing but print log */
            ap_log_error(APLOG_MARK, APLOG_INFO, 0,
                         main_server,
                         "mod_fcgid: process busy timeout, take %d seconds for this request",
                         dt);
        } else if (ctx->has_error) {
            ctx->procnode->diewhy = FCGID_DIE_COMM_ERROR;
            return_procnode(main_server, ctx->procnode,
                            1 /* communication error */ );
        } else if (g_max_requests_per_process != -1
                   && ++ctx->procnode->requests_handled >=
                   g_max_requests_per_process) {
            ctx->procnode->diewhy = FCGID_DIE_LIFETIME_EXPIRED;
            return_procnode(main_server, ctx->procnode,
                            1 /* handled all requests */ );
        } else
            return_procnode(main_server, ctx->procnode,
                            0 /* communication ok */ );

        ctx->procnode = NULL;
    }

    return APR_SUCCESS;
}

static int getsfunc_fcgid_BRIGADE(char *buf, int len, void *arg)
{
    apr_bucket_brigade *bb = (apr_bucket_brigade *) arg;
    const char *dst_end = buf + len - 1;    /* leave room for terminating null */
    char *dst = buf;
    apr_bucket *e = APR_BRIGADE_FIRST(bb);
    apr_status_t rv;
    int done = 0;
    int getLF = 0;
    int getColon = 0;

    while ((dst < dst_end) && !done && !APR_BUCKET_IS_EOS(e)) {
        const char *bucket_data;
        apr_size_t bucket_data_len;
        const char *src;
        const char *src_end;
        apr_bucket *next;

        rv = apr_bucket_read(e, &bucket_data, &bucket_data_len,
                             APR_BLOCK_READ);
        if (rv != APR_SUCCESS) {
            return 0;
        }

        /* Move on to next bucket if it's fastcgi header bucket */
        if (e->type == &ap_bucket_type_fcgid_header
            || e->type == &apr_bucket_type_immortal) {
            next = APR_BUCKET_NEXT(e);
            apr_bucket_delete(e);
            e = next;
            if (getLF) {
                done = 1;
            }
            continue;
        }

        if (bucket_data_len == 0)
            return 0;

        /* Base on RFC2616 section 4.2 */
        src = bucket_data;
        src_end = bucket_data + bucket_data_len;
        while ((src < src_end) && (dst < dst_end) && !done) {
            if (*src == ':')
                getColon = 1;

            if (getLF && ((*src != ' ' && *src != '\t') || !getColon)) {
                done = 1;
                getColon = 0;
                break;
            } else if (getLF && (*src == ' ' || *src == '\t')) {
                *dst++ = '\r';
                *dst++ = '\n';
                getLF = 0;
            }

            if (*src == '\n') {
                getLF = 1;
            } else if (*src != '\r') {
                *dst++ = *src;
            }
            src++;
        }

        if (src < src_end) {
            apr_bucket_split(e, src - bucket_data);
        }
        next = APR_BUCKET_NEXT(e);
        apr_bucket_delete(e);
        e = next;
    }
    *dst = 0;
    return 1;
}

static int
handle_request(request_rec * r, int role, const char *argv0,
               fcgid_wrapper_conf * wrapper_conf,
               apr_bucket_brigade * output_brigade)
{
    apr_pool_t *request_pool = r->main ? r->main->pool : r->pool;
    server_rec *main_server = r->server;
    fcgid_command fcgi_request;
    fcgid_bucket_ctx *bucket_ctx;
    int i, j, cond_status;
    apr_status_t rv;
    apr_bucket_brigade *brigade_stdout;
    char sbuf[MAX_STRING_LEN];
    const char *location;

    if (!g_variables_inited) {
        g_connect_timeout = get_ipc_connect_timeout(r->server);
        g_comm_timeout = get_ipc_comm_timeout(r->server);
        g_busy_timeout = get_busy_timeout(r->server);
        g_max_requests_per_process =
            get_max_requests_per_process(r->server);
        if (g_comm_timeout == 0)
            g_comm_timeout = 1;
        g_variables_inited = 1;
    }

    bucket_ctx = apr_pcalloc(request_pool, sizeof(*bucket_ctx));
    if (!bucket_ctx) {
        ap_log_error(APLOG_MARK, APLOG_WARNING, apr_get_os_error(),
                     r->server,
                     "mod_fcgid: apr_calloc bucket_ctx failed in handle_request function");
        return HTTP_INTERNAL_SERVER_ERROR;
    }
    bucket_ctx->ipc.connect_timeout = g_connect_timeout;
    bucket_ctx->ipc.communation_timeout = g_comm_timeout;
    bucket_ctx->ipc.request = r;
    apr_pool_cleanup_register(request_pool, bucket_ctx,
                              bucket_ctx_cleanup, apr_pool_cleanup_null);

    /* Try to get a connected ipc handle */
    for (i = 0; i < FCGID_REQUEST_COUNT; i++) {
        /* Apply a free process slot, send a spawn request if I can't get one */
        for (j = 0; j < FCGID_APPLY_TRY_COUNT; j++) {
            apr_ino_t inode =
                wrapper_conf ? wrapper_conf->inode : r->finfo.inode;
            apr_dev_t deviceid =
                wrapper_conf ? wrapper_conf->deviceid : r->finfo.device;
            apr_size_t shareid =
                wrapper_conf ? wrapper_conf->share_group_id : 0;

            /* Init spawn request */
            procmgr_init_spawn_cmd(&fcgi_request, r, argv0, deviceid,
                                   inode, shareid);

            /* Apply a process slot */
            bucket_ctx->procnode =
                apply_free_procnode(r->server, &fcgi_request);
            if (bucket_ctx->procnode)
                break;

            /* Avoid sleeping the very first time through if there are no
               busy processes; the problem is just that we haven't spawned
               anything yet, so waiting is pointless */
            if (i > 0 || j > 0
                || count_busy_processes(r->server, &fcgi_request)) {
                apr_sleep(apr_time_from_sec(1));

                bucket_ctx->procnode =
                    apply_free_procnode(r->server, &fcgi_request);
                if (bucket_ctx->procnode)
                    break;
            }

            /* Send a spawn request if I can't get a process slot */
            procmgr_post_spawn_cmd(&fcgi_request, r);
        }

        /* Connect to the fastcgi server */
        if (bucket_ctx->procnode) {
            if (proc_connect_ipc
                (r->server, bucket_ctx->procnode,
                 &bucket_ctx->ipc) != APR_SUCCESS) {
                proc_close_ipc(r->server, &bucket_ctx->ipc);
                bucket_ctx->procnode->diewhy = FCGID_DIE_CONNECT_ERROR;
                return_procnode(r->server, bucket_ctx->procnode,
                                1 /* has error */ );
                bucket_ctx->procnode = NULL;
            } else
                break;
        }
    }

    /* Now I get a connected ipc handle */
    if (!bucket_ctx->procnode) {
        ap_log_error(APLOG_MARK, APLOG_WARNING, 0, r->server,
                     "mod_fcgid: can't apply process slot for %s", argv0);
        return HTTP_SERVICE_UNAVAILABLE;
    }
    bucket_ctx->active_time = bucket_ctx->procnode->last_active_time =
        apr_time_now();

    /* Write output_brigade to fastcgi server */
    if ((rv =
         proc_write_ipc(main_server, &bucket_ctx->ipc,
                        output_brigade)) != APR_SUCCESS) {
        ap_log_error(APLOG_MARK, APLOG_WARNING, rv, r->server,
                     "mod_fcgid: write data to fastcgi server error");
        bucket_ctx->has_error = 1;
        return HTTP_INTERNAL_SERVER_ERROR;
    }

    /* Create brigade */
    brigade_stdout =
        apr_brigade_create(request_pool, r->connection->bucket_alloc);
    if (!brigade_stdout) {
        ap_log_error(APLOG_MARK, APLOG_WARNING, rv, r->server,
                     "mod_fcgid: apr_brigade_create failed in handle_request function");
        return HTTP_INTERNAL_SERVER_ERROR;
    }
    APR_BRIGADE_INSERT_TAIL(brigade_stdout,
                            ap_bucket_fcgid_header_create(r->connection->
                                                          bucket_alloc,
                                                          bucket_ctx));
    /*APR_BRIGADE_INSERT_TAIL(brigade_stdout, apr_bucket_flush_create(r->connection->bucket_alloc)); */

    /* Check the script header first. If got error, return immediately */
    if ((cond_status = ap_scan_script_header_err_core
         (r, sbuf, getsfunc_fcgid_BRIGADE, brigade_stdout)) >= 400)
        return cond_status;

    /* Check redirect */
    location = apr_table_get(r->headers_out, "Location");

    if (location && location[0] == '/' && r->status == 200) {
        /* This redirect needs to be a GET no matter what the original 
         * method was. 
         */
        r->method = apr_pstrdup(r->pool, "GET");
        r->method_number = M_GET;

        /* We already read the message body (if any), so don't allow 
         * the redirected request to think it has one. We can ignore 
         * Transfer-Encoding, since we used REQUEST_CHUNKED_ERROR. 
         */
        apr_table_unset(r->headers_in, "Content-Length");

        ap_internal_redirect_handler(location, r);
        return HTTP_OK;
    } else if (location && r->status == 200) {
        /* XX Note that if a script wants to produce its own Redirect 
         * body, it now has to explicitly *say* "Status: 302" 
         */
        return HTTP_MOVED_TEMPORARILY;
    }

    /* Now pass to output filter */
    if (role == FCGI_RESPONDER && (rv =
                                   ap_pass_brigade(r->output_filters,
                                                   brigade_stdout)) !=
        APR_SUCCESS) {
        ap_log_error(APLOG_MARK, APLOG_WARNING, rv, r->server,
                     "mod_fcgid: ap_pass_brigade failed in handle_request function");
        return HTTP_INTERNAL_SERVER_ERROR;
    }

    /* Retrun condition status */
    return cond_status;
}

int bridge_request(request_rec * r, int role, const char *argv0,
                   fcgid_wrapper_conf * wrapper_conf)
{
    apr_pool_t *request_pool = r->main ? r->main->pool : r->pool;
    server_rec *main_server = r->server;
    apr_status_t rv = APR_SUCCESS;
    int seen_eos;
    size_t request_size = 0;
    apr_file_t *fd = NULL;
    int need_truncate = 1;
    apr_off_t cur_pos = 0;
    FCGI_Header *stdin_request_header;
    apr_bucket_brigade *output_brigade;
    apr_bucket *bucket_input, *bucket_header, *bucket_eos;
    size_t max_request_len = get_max_request_len(main_server);
    size_t max_mem_request_len = get_max_mem_request_len(main_server);
    char **envp = ap_create_environment(request_pool,
                                        r->subprocess_env);

    /* Create brigade for the request to fastcgi server */
    output_brigade =
        apr_brigade_create(request_pool, r->connection->bucket_alloc);
    if (!output_brigade) {
        ap_log_error(APLOG_MARK, APLOG_WARNING, apr_get_os_error(),
                     main_server,
                     "mod_fcgid: can't alloc memory for output brigade");
        return HTTP_INTERNAL_SERVER_ERROR;
    }

    /* Build the begin request and environ request, append them to output_brigade */
    if (!build_begin_block
        (role, r->server, r->connection->bucket_alloc, output_brigade)
        || !build_env_block(r->server, envp, r->connection->bucket_alloc,
                            output_brigade)) {
        ap_log_error(APLOG_MARK, APLOG_WARNING, 0,
                     main_server,
                     "mod_fcgid: can't build begin or env request");
        return HTTP_INTERNAL_SERVER_ERROR;
    }

    /* Stdin header and body */
    /* XXX HACK: I have to read all the request into memory before sending it 
       to fastcgi application server, this prevents slow clients from 
       keeping the server in processing too long. 
       Buf sometimes it's not acceptable(think about uploading a larage attachment)
       file_bucket is a better choice in this case...
       To do, or not to do, that is the question ^_^
     */
    seen_eos = 0;
    do {
        apr_bucket_brigade *input_brigade =
            apr_brigade_create(request_pool,
                               r->connection->bucket_alloc);

        if (!input_brigade
            || (rv = ap_get_brigade(r->input_filters, input_brigade,
                                    AP_MODE_READBYTES,
                                    APR_BLOCK_READ,
                                    HUGE_STRING_LEN)) != APR_SUCCESS) {
            ap_log_error(APLOG_MARK, APLOG_WARNING, rv,
                         main_server,
                         "mod_fcgid: can't get data from http client");
            apr_brigade_destroy(output_brigade);
            if (input_brigade)
                apr_brigade_destroy(input_brigade);
            return HTTP_INTERNAL_SERVER_ERROR;
        }

        request_size = 0;
        for (bucket_input = APR_BRIGADE_FIRST(input_brigade);
             bucket_input != APR_BRIGADE_SENTINEL(input_brigade);
             bucket_input = APR_BUCKET_NEXT(bucket_input)) {
            const char *data;
            apr_size_t len;
            apr_bucket *bucket_stdin;

            if (APR_BUCKET_IS_EOS(bucket_input)) {
                seen_eos = 1;
                break;
            }

            if (APR_BUCKET_IS_METADATA(bucket_input))
                continue;

            if ((rv = apr_bucket_read(bucket_input, &data, &len,
                                      APR_BLOCK_READ)) != APR_SUCCESS) {
                ap_log_error(APLOG_MARK, APLOG_WARNING, rv,
                             main_server,
                             "mod_fcgid: can't read request from HTTP client");
                apr_brigade_destroy(input_brigade);
                apr_brigade_destroy(output_brigade);
                return HTTP_INTERNAL_SERVER_ERROR;
            }

            /* Append a header, and the the bucket */
            stdin_request_header = apr_bucket_alloc(sizeof(FCGI_Header),
                                                    r->connection->
                                                    bucket_alloc);
            bucket_header =
                apr_bucket_heap_create((const char *) stdin_request_header,
                                       sizeof(*stdin_request_header),
                                       apr_bucket_free,
                                       r->connection->bucket_alloc);

            request_size += len;
            if (request_size > max_request_len) {
                ap_log_error(APLOG_MARK, APLOG_WARNING, apr_get_os_error(),
                             main_server,
                             "mod_fcgid: http request length %d > %d",
                             request_size, max_request_len);
                return HTTP_INTERNAL_SERVER_ERROR;
            }

            if (request_size > max_mem_request_len) {
                apr_size_t wrote_len;
                static const char *fd_key = "fcgid_fd";

                if (fd == NULL)
                    apr_pool_userdata_get((void **) &fd, fd_key,
                                          r->connection->pool);

                if (fd == NULL) {
                    const char *tempdir = NULL;
                    char *template;

                    rv = apr_temp_dir_get(&tempdir, r->pool);
                    if (rv != APR_SUCCESS) {
                        ap_log_error(APLOG_MARK, APLOG_WARNING,
                                     apr_get_os_error(), main_server,
                                     "mod_fcigd: can't get tmp dir");
                        return HTTP_INTERNAL_SERVER_ERROR;
                    }

                    apr_filepath_merge(&template, tempdir,
                                       "fcgid.tmp.XXXXXX",
                                       APR_FILEPATH_NATIVE, r->pool);
                    rv = apr_file_mktemp(&fd, template, 0,
                                         r->connection->pool);
                    if (rv != APR_SUCCESS) {
                        ap_log_error(APLOG_MARK, APLOG_WARNING,
                                     apr_get_os_error(), main_server,
                                     "mod_fcgid: can't open tmp file fot stdin request");
                        return HTTP_INTERNAL_SERVER_ERROR;
                    }
                    apr_pool_userdata_set((const void *) fd, fd_key,
                                          apr_pool_cleanup_null,
                                          r->connection->pool);
                } else if (need_truncate) {
                    need_truncate = 0;
                    apr_file_trunc(fd, 0);
                    cur_pos = 0;
                }
                // Write request to tmp file
                if ((rv =
                     apr_file_write_full(fd, (const void *) data, len,
                                         &wrote_len)) != APR_SUCCESS
                    || len != wrote_len) {
                    ap_log_error(APLOG_MARK, APLOG_WARNING,
                                 apr_get_os_error(), main_server,
                                 "mod_fcgid: can't write tmp file for stdin request");
                    return HTTP_INTERNAL_SERVER_ERROR;
                }
                // Create file bucket
                bucket_stdin =
                    apr_bucket_file_create(fd, cur_pos, len, r->pool,
                                           r->connection->bucket_alloc);
                cur_pos += len;
            } else {
                if (APR_BUCKET_IS_HEAP(bucket_input))
                    apr_bucket_copy(bucket_input, &bucket_stdin);
                else {
                    /* mod_ssl have a bug? */
                    char *pcopydata =
                        apr_bucket_alloc(len, r->connection->bucket_alloc);
                    memcpy(pcopydata, data, len);
                    bucket_stdin =
                        apr_bucket_heap_create(pcopydata, len,
                                               apr_bucket_free,
                                               r->connection->
                                               bucket_alloc);
                }
            }

            if (!stdin_request_header || !bucket_header || !bucket_stdin
                || !init_header(FCGI_STDIN, 1, len, 0,
                                stdin_request_header)) {
                ap_log_error(APLOG_MARK, APLOG_WARNING, apr_get_os_error(),
                             main_server,
                             "mod_fcgid: can't alloc memory for stdin request");
                apr_brigade_destroy(input_brigade);
                apr_brigade_destroy(output_brigade);
                return HTTP_INTERNAL_SERVER_ERROR;
            }
            APR_BRIGADE_INSERT_TAIL(output_brigade, bucket_header);
            APR_BRIGADE_INSERT_TAIL(output_brigade, bucket_stdin);
        }

        apr_brigade_destroy(input_brigade);
    }
    while (!seen_eos);

    /* Append an empty body stdin header */
    stdin_request_header = apr_bucket_alloc(sizeof(FCGI_Header),
                                            r->connection->bucket_alloc);
    bucket_header =
        apr_bucket_heap_create((const char *) stdin_request_header,
                               sizeof(*stdin_request_header),
                               apr_bucket_free,
                               r->connection->bucket_alloc);
    if (!stdin_request_header || !bucket_header
        || !init_header(FCGI_STDIN, 1, 0, 0, stdin_request_header)) {
        ap_log_error(APLOG_MARK, APLOG_WARNING, apr_get_os_error(),
                     main_server,
                     "mod_fcgid: can't alloc memory for stdin request");
        return HTTP_INTERNAL_SERVER_ERROR;
    }
    APR_BRIGADE_INSERT_TAIL(output_brigade, bucket_header);

    /* The eos bucket now */
    bucket_eos = apr_bucket_eos_create(r->connection->bucket_alloc);
    if (!bucket_eos) {
        ap_log_error(APLOG_MARK, APLOG_WARNING, apr_get_os_error(),
                     main_server,
                     "mod_fcgid: can't alloc memory for eos bucket");
        return HTTP_INTERNAL_SERVER_ERROR;
    }
    APR_BRIGADE_INSERT_TAIL(output_brigade, bucket_eos);

    /* Bridge the request */
    return handle_request(r, role, argv0, wrapper_conf, output_brigade);
}
