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
