diff options
author | Paul Querna <pquerna@apache.org> | 2005-12-18 05:42:38 +0000 |
---|---|---|
committer | Paul Querna <pquerna@apache.org> | 2005-12-18 05:42:38 +0000 |
commit | d29585bc588298a72c76caa36d9e8fd2cd8e2909 (patch) | |
tree | 04450fef6c14222eab61b40052819d4c79faeacd | |
parent | 06e0a0078d02c054ec88a82dc687a94e8c7b8c2b (diff) | |
download | httpd-d29585bc588298a72c76caa36d9e8fd2cd8e2909.tar.gz |
Create a templte for a FastCGI proxy backend. It does not actually do much yet, but is the base for more development. I hope to work on this more tomorrow.
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/fcgi-proxy-dev@357444 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r-- | modules/proxy/config.m4 | 3 | ||||
-rw-r--r-- | modules/proxy/mod_proxy_fcgi.c | 219 |
2 files changed, 222 insertions, 0 deletions
diff --git a/modules/proxy/config.m4 b/modules/proxy/config.m4 index f131ee6611..7746b09569 100644 --- a/modules/proxy/config.m4 +++ b/modules/proxy/config.m4 @@ -16,6 +16,7 @@ APACHE_MODULE(proxy, Apache proxy module, $proxy_objs, , $proxy_mods_enable) proxy_connect_objs="mod_proxy_connect.lo" proxy_ftp_objs="mod_proxy_ftp.lo" proxy_http_objs="mod_proxy_http.lo" +proxy_fcgi_objs="mod_proxy_fcgi.lo" proxy_ajp_objs="mod_proxy_ajp.lo ajp_header.lo ajp_link.lo ajp_msg.lo" proxy_balancer_objs="mod_proxy_balancer.lo" @@ -26,6 +27,7 @@ case "$host" in proxy_connect_objs="$proxy_connect_objs mod_proxy.la" proxy_ftp_objs="$proxy_ftp_objs mod_proxy.la" proxy_http_objs="$proxy_http_objs mod_proxy.la" + proxy_fcgi_objs="$proxy_fcgi_objs mod_proxy.la" proxy_ajp_objs="$proxy_ajp_objs mod_proxy.la" proxy_balancer_objs="$proxy_balancer_objs mod_proxy.la" ;; @@ -34,6 +36,7 @@ esac APACHE_MODULE(proxy_connect, Apache proxy CONNECT module, $proxy_connect_objs, , $proxy_mods_enable) APACHE_MODULE(proxy_ftp, Apache proxy FTP module, $proxy_ftp_objs, , $proxy_mods_enable) APACHE_MODULE(proxy_http, Apache proxy HTTP module, $proxy_http_objs, , $proxy_mods_enable) +APACHE_MODULE(proxy_fcgi, Apache proxy FastCGI module, $proxy_fcgi_objs, , $proxy_mods_enable) APACHE_MODULE(proxy_ajp, Apache proxy AJP module, $proxy_ajp_objs, , $proxy_mods_enable) APACHE_MODULE(proxy_balancer, Apache proxy BALANCER module, $proxy_balancer_objs, , $proxy_mods_enable) diff --git a/modules/proxy/mod_proxy_fcgi.c b/modules/proxy/mod_proxy_fcgi.c new file mode 100644 index 0000000000..fbaf60f9c7 --- /dev/null +++ b/modules/proxy/mod_proxy_fcgi.c @@ -0,0 +1,219 @@ +/* Copyright 2005 The Apache Software Foundation or its licensors, as + * applicable. + * + * Licensed 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 "mod_proxy.h" + +module AP_MODULE_DECLARE_DATA proxy_fcgi_module; + +/* + * Canonicalise http-like URLs. + * scheme is the scheme for the URL + * url is the URL starting with the first '/' + * def_port is the default port for this scheme. + */ +static int proxy_fcgi_canon(request_rec *r, char *url) +{ + char *host, *path, *search, sport[7]; + const char *err; + apr_port_t port = 8000; + + if (strncasecmp(url, "fcgi:", 5) == 0) { + url += 5; + } + else { + return DECLINED; + } + + if (strncmp(url, "tcp://", 6) == 0) { + url += 6; + } + else if (strncmp(url, "local:", 6) == 0) { + url += 6; + } + else { + ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server, + "proxy: FCGI: mallformed destination: %s", url); + return HTTP_INTERNAL_SERVER_ERROR; + } + + + /* + * do syntactic check. + * We break the URL into host, port, path, search + */ + err = ap_proxy_canon_netloc(r->pool, &url, NULL, NULL, &host, &port); + if (err) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r, + "error parsing URL %s: %s", + url, err); + return HTTP_BAD_REQUEST; + } + + /* + * now parse path/search args, according to rfc1738 + * + * N.B. if this isn't a true proxy request, then the URL _path_ + * has already been decoded. True proxy requests have + * r->uri == r->unparsed_uri, and no others have that property. + */ + if (r->uri == r->unparsed_uri) { + search = strchr(url, '?'); + if (search != NULL) + *(search++) = '\0'; + } + else { + search = r->args; + } + + /* process path */ + path = ap_proxy_canonenc(r->pool, url, strlen(url), enc_path, 0, + r->proxyreq); + if (path == NULL) { + return HTTP_BAD_REQUEST; + } + + apr_snprintf(sport, sizeof(sport), ":%d", port); + + if (ap_strchr_c(host, ':')) { + /* if literal IPv6 address */ + host = apr_pstrcat(r->pool, "[", host, "]", NULL); + } + r->filename = apr_pstrcat(r->pool, "proxy:ajp://", host, sport, + "/", path, (search) ? "?" : "", + (search) ? search : "", NULL); + return OK; +} + +/* + * process the request and write the response. + */ +static int fcgi_do_request(apr_pool_t *p, request_rec *r, + proxy_conn_rec *conn, + conn_rec *origin, + proxy_dir_conf *conf, + apr_uri_t *uri, + char *url, char *server_portstr) +{ + /* TODO: Talk to a FastCGI Backend */ + return HTTP_SERVICE_UNAVAILABLE; +} + +/* + * This handles fcgi:(type):(dest) URLs + */ +static int proxy_fcgi_handler(request_rec *r, proxy_worker *worker, + proxy_server_conf *conf, + char *url, const char *proxyname, + apr_port_t proxyport) +{ + int status; + char server_portstr[32]; + conn_rec *origin = NULL; + proxy_conn_rec *backend = NULL; + const char *scheme; + proxy_dir_conf *dconf = ap_get_module_config(r->per_dir_config, + &proxy_module); + + apr_pool_t *p = r->pool; + + apr_uri_t *uri = apr_palloc(r->pool, sizeof(*uri)); + + + if (strncasecmp(url, "fcgi:", 5) == 0) { + url += 5; + } + else { + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, + "proxy: FCGI: declining URL %s", url); + return DECLINED; + } + + if (strncmp(url, "tcp://", 6) == 0) { + scheme = "FCGI_TCP"; + } + else if (strncmpp(url, "local:", 6) == 0) { + scheme = "FCGI_LOCAL"; + } + else { + ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server, + "proxy: FCGI: mallformed destination: %s", url); + return HTTP_INTERNAL_SERVER_ERROR; + } + + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, + "proxy: FCGI: serving URL %s via %s", url, scheme); + + /* create space for state information */ + if (!backend) { + status = ap_proxy_acquire_connection(scheme, &backend, worker, + r->server); + if (status != OK) { + if (backend) { + backend->close_on_recycle = 1; + ap_proxy_release_connection(scheme, backend, r->server); + } + return status; + } + } + + backend->is_ssl = 0; + backend->close_on_recycle = 0; + + /* Step One: Determine Who To Connect To */ + status = ap_proxy_determine_connection(p, r, conf, worker, backend, + uri, &url, proxyname, proxyport, + server_portstr, + sizeof(server_portstr)); + + if (status != OK) { + goto cleanup; + } + + /* Step Two: Make the Connection */ + if (ap_proxy_connect_backend(scheme, backend, worker, r->server)) { + ap_log_error(APLOG_MARK, APLOG_ERR, 0, r->server, + "proxy: FCGI: failed to make connection to backend: %s", + backend->hostname); + status = HTTP_SERVICE_UNAVAILABLE; + goto cleanup; + } + + /* Step Three: Process the Request */ + status = fcgi_do_request(p, r, backend, origin, dconf, uri, url, + server_portstr); + +cleanup: + /* Do not close the socket */ + ap_proxy_release_connection(scheme, backend, r->server); + return status; +} + +static void register_hooks(apr_pool_t *p) +{ + proxy_hook_scheme_handler(proxy_fcgi_handler, NULL, NULL, APR_HOOK_FIRST); + proxy_hook_canon_handler(proxy_fcgi_canon, NULL, NULL, APR_HOOK_FIRST); +} + +module AP_MODULE_DECLARE_DATA proxy_fcgi_module = { + STANDARD20_MODULE_STUFF, + NULL, /* create per-directory config structure */ + NULL, /* merge per-directory config structures */ + NULL, /* create per-server config structure */ + NULL, /* merge per-server config structures */ + NULL, /* command apr_table_t */ + register_hooks /* register hooks */ +}; + |