On 12/26/2008 10:41 PM, [email protected] wrote:
> Author: nd
> Date: Fri Dec 26 13:41:48 2008
> New Revision: 729538
> 
> URL: http://svn.apache.org/viewvc?rev=729538&view=rev
> Log:
> add mod_proxy_scgi, as announced a long time ago
> 
> Added:
>     httpd/httpd/trunk/docs/manual/mod/mod_proxy_scgi.xml   (with props)
>     httpd/httpd/trunk/modules/proxy/mod_proxy_scgi.c   (with props)
> Modified:
>     httpd/httpd/trunk/CHANGES
>     httpd/httpd/trunk/modules/mappers/mod_rewrite.c
>     httpd/httpd/trunk/modules/proxy/config.m4
> 

> Added: httpd/httpd/trunk/modules/proxy/mod_proxy_scgi.c
> URL: 
> http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/proxy/mod_proxy_scgi.c?rev=729538&view=auto
> ==============================================================================
> --- httpd/httpd/trunk/modules/proxy/mod_proxy_scgi.c (added)
> +++ httpd/httpd/trunk/modules/proxy/mod_proxy_scgi.c Fri Dec 26 13:41:48 2008

> +/*
> + * Fetch response from backend and pass back to the front
> + */
> +static int pass_response(request_rec *r, proxy_conn_rec *conn)
> +{
> +    apr_bucket_brigade *bb;
> +    apr_bucket *b;
> +    const char *location;
> +    scgi_config *conf;
> +    socket_ex_data *sock_data;
> +    int status;
> +
> +    sock_data = apr_palloc(r->pool, sizeof(*sock_data));
> +    sock_data->sock = conn->sock;
> +    sock_data->counter = &conn->worker->s->read;
> +
> +    bb = apr_brigade_create(r->pool, r->connection->bucket_alloc);
> +    b = bucket_socket_ex_create(sock_data, r->connection->bucket_alloc);
> +    APR_BRIGADE_INSERT_TAIL(bb, b);
> +    b = apr_bucket_eos_create(r->connection->bucket_alloc);
> +    APR_BRIGADE_INSERT_TAIL(bb, b);
> +
> +    status = ap_scan_script_header_err_brigade(r, bb, NULL);
> +    if (status != OK) {
> +        ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
> +                      "proxy: " PROXY_FUNCTION ": error reading response "
> +                      "headers from %s:%u", conn->hostname, conn->port);
> +        r->status_line = NULL;
> +        apr_brigade_destroy(bb);
> +        return status;
> +    }
> +
> +    conf = ap_get_module_config(r->per_dir_config, &proxy_scgi_module);
> +    if (conf->sendfile && conf->sendfile != scgi_sendfile_off) {
> +        short err = 1;
> +
> +        location = apr_table_get(r->err_headers_out, conf->sendfile);
> +        if (!location) {
> +            err = 0;
> +            location = apr_table_get(r->headers_out, conf->sendfile);
> +        }
> +        if (location) {
> +            scgi_request_config *req_conf = apr_palloc(r->pool,
> +                                                       sizeof(*req_conf));
> +            ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
> +                          "proxy: " PROXY_FUNCTION ": Found %s: %s - "
> +                          "preparing subrequest.",
> +                          conf->sendfile, location);
> +
> +            if (err) {
> +                apr_table_unset(r->err_headers_out, conf->sendfile);
> +            }
> +            else {
> +                apr_table_unset(r->headers_out, conf->sendfile);
> +            }
> +            req_conf->location = location;
> +            req_conf->type = scgi_sendfile;
> +            ap_set_module_config(r->request_config, &proxy_scgi_module,
> +                                 req_conf);


Hm. Why this rather complex approach with the request_status hook?
Why not doing the subrequest here or even better just inserting the file buckets
into the brigade right here and be done?

> +            apr_brigade_destroy(bb);
> +            return OK;
> +        }
> +    }
> +
> +    if (conf->internal_redirect && r->status == HTTP_OK) {
> +        location = apr_table_get(r->headers_out, "Location");
> +        if (location && *location == '/') {
> +            scgi_request_config *req_conf = apr_palloc(r->pool,
> +                                                       sizeof(*req_conf));
> +            req_conf->location = location;
> +            req_conf->type = scgi_internal_redirect;
> +            ap_set_module_config(r->request_config, &proxy_scgi_module,
> +                                 req_conf);
> +            apr_brigade_destroy(bb);
> +            return OK;
> +        }
> +    }
> +
> +    /* XXX: What could we do with that return code? */
> +    (void)ap_pass_brigade(r->output_filters, bb);
> +
> +    return OK;
> +}
> +

> +
> +/*
> + * This handles scgi:(dest) URLs
> + */
> +static int scgi_handler(request_rec *r, proxy_worker *worker,
> +                        proxy_server_conf *conf, char *url,
> +                        const char *proxyname, apr_port_t proxyport)
> +{
> +    int status;
> +    proxy_conn_rec *backend = NULL;
> +    apr_pool_t *p = r->pool;
> +    apr_uri_t *uri = apr_palloc(r->pool, sizeof(*uri));
> +    char dummy;
> +
> +    if (strncasecmp(url, SCHEME "://", sizeof(SCHEME) + 2)) {
> +        ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r,
> +                      "proxy: " PROXY_FUNCTION ": declining URL %s", url);
> +        return DECLINED;
> +    }
> +    url += sizeof(SCHEME); /* keep the slashes */

Why cutting off the scheme?

> +    
> +    /* Create space for state information */
> +    status = ap_proxy_acquire_connection(PROXY_FUNCTION, &backend, worker,
> +                                         r->server);
> +    if (status != OK) {
> +        goto cleanup;
> +    }
> +    backend->is_ssl = 0;
> +
> +    /* Step One: Determine Who To Connect To */
> +    status = ap_proxy_determine_connection(p, r, conf, worker, backend,
> +                                           uri, &url, proxyname, proxyport,
> +                                           &dummy, 1);
> +    if (status != OK) {
> +        goto cleanup;
> +    }
> +
> +    /* Step Two: Make the Connection */
> +    if (ap_proxy_connect_backend(PROXY_FUNCTION, backend, worker, 
> r->server)) {
> +        ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server,
> +                     "proxy: " PROXY_FUNCTION ": failed to make connection "
> +                     "to backend: %s:%u", backend->hostname, backend->port);
> +        status = HTTP_SERVICE_UNAVAILABLE;
> +        goto cleanup;
> +    }
> +
> +    /* Step Three: Process the Request */
> +    if (   ((status = ap_setup_client_block(r, REQUEST_CHUNKED_ERROR)) != OK)
> +        || ((status = send_headers(r, backend)) != OK)
> +        || ((status = send_request_body(r, backend)) != OK)
> +        || ((status = pass_response(r, backend)) != OK)) {
> +        goto cleanup;
> +    }
> +
> +cleanup:
> +    if (backend) {
> +        backend->close = 1; /* always close the socket */
> +        ap_proxy_release_connection(PROXY_FUNCTION, backend, r->server);
> +    }
> +    return status;
> +}
> +
> +

Regards

Rüdiger

Reply via email to