From: Jim Jagielski Date: Fri, 13 May 2011 13:46:43 +0000 (+0000) Subject: Add in new mod_proxy "extension" module: mod_proxy_express. X-Git-Tag: 2.3.13~146 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a63ae1c31d65041854227093ab9c8af84af99e25;p=thirdparty%2Fapache%2Fhttpd.git Add in new mod_proxy "extension" module: mod_proxy_express. This is a module developed by myself to support the RedHat OpenShift Express project, to allow for dynamic and fast reverse-proxy switching. The idea is to easily map Host: header entries to backend servers, with the mapping done in a DBM file (think of mod_vhost_alias, kinda, for mod_proxy). Yeah, mod_rewrite and RewriteMap could kinda do it but (1) that is slow and (2) no support for ProxyPassReverse capability. Donated to the ASF. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1102733 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/CHANGES b/CHANGES index 8371bd749fc..2cd9baa971d 100644 --- a/CHANGES +++ b/CHANGES @@ -2,6 +2,9 @@ Changes with Apache 2.3.13 + *) mod_proxy_express: New mass reverse-proxy switch extension for + mod_proxy. [Jim Jagielski] + *) configure: Fix script error when configuring module set "reallyall". [Rainer Jung] diff --git a/docs/manual/mod/mod_proxy_express.html b/docs/manual/mod/mod_proxy_express.html new file mode 100644 index 00000000000..28ca0cd65a1 --- /dev/null +++ b/docs/manual/mod/mod_proxy_express.html @@ -0,0 +1,5 @@ +# GENERATED FROM XML -- DO NOT EDIT + +URI: mod_proxy_express.html.en +Content-Language: en +Content-type: text/html; charset=ISO-8859-1 diff --git a/docs/manual/mod/mod_proxy_express.html.en b/docs/manual/mod/mod_proxy_express.html.en new file mode 100644 index 00000000000..218f4cb39fe --- /dev/null +++ b/docs/manual/mod/mod_proxy_express.html.en @@ -0,0 +1,164 @@ + + + +mod_proxy_express - Apache HTTP Server + + + + + + +
<-
+
+Apache > HTTP Server > Documentation > Version 2.3 > Modules
+
+

Apache Module mod_proxy_express

+
+

Available Languages:  en 

+
+ + + +
Description:Dynamic mass reverse proxy extension for +mod_proxy
Status:Extension
Module Identifier:proxy_express_module
Source File:mod_proxy_express.c
+

Summary

+ +

This module creates dynamically configured mass reverse + proxies, by mapping the Host: header of the HTTP request to + a server name and backend URL stored in a DBM file. + This allows for easy use of a huge number of reverse proxies + with no configuration changes. It is much less feature-full + than mod_proxy_balancer, which also provides + dynamic growth, but is intended to handle much, much + larger numbers of backends. It is ideally suited as a + front-end HTTP switch.

+ +

This module requires the service of mod_proxy.

+ +

Warning

+

Do not enable proxying until you have secured your server. Open proxy + servers are dangerous both to your network and to the Internet at + large.

+
+ +

Limitations

+
    +
  • This module is not intended to replace the dynamic capability of + mod_proxy_balancer. Instead, it is intended to be mostly + a lightweight and fast alternative to using mod_rewrite + with RewriteMap and the [P] flag + for mapped reverse proxying. +
  • +
  • It does not support regex or pattern matching at all. +
  • +
  • It emulates: +

    + ProxyPass / backend.server:port
    + ProxyPassReverse / backend.server:port
    +

    + That is, the entire URL is appended to the mapped backend + URL. This is in keeping with the intent of being a simple + but fast reverse proxy switch. +
  • +
+
+ +
+ + +
top
+

ProxyExpressDBMFile Directive

+ + + + + + + + +
Description:Pathname to DBM file.
Syntax:ProxyExpressDBMFile <pathname>
Default:None
Context:server config, virtual host
Status:Extension
Module:mod_proxy_express
Compatibility:Available in Apache 2.3.13 and later
+

The ProxyExpressDBMFile directive + points to the location of the Express map DBM file. This + file serves to map the incoming server name, obtained from + the Host: header, to a backend URL.

+ +

Note

+

The file is constructed from a plain text file format using + the httxt2dbm + utility.

+ +

ProxyExpress map file

+ ##
+ ##express-map.txt:
+ ##
+
+ www1.example.com http://192.168.211.2:8080
+ www2.example.com http://192.168.211.12:8088
+ www3.example.com http://192.168.212.10
+

+ +

Create DBM file

+ httxt2dbm -i express-map.txt -o emap
+

+ +

Configuration

+ ProxyExpressDBMFile emap
+

+
+ +
+
top
+

ProxyExpressDBMType Directive

+ + + + + + + + +
Description:DBM type of file.
Syntax:ProxyExpressDBMFile <type>
Default:"default"
Context:server config, virtual host
Status:Extension
Module:mod_proxy_express
Compatibility:Available in Apache 2.3.13 and later
+

The ProxyExpressDBMType directive + controls the DBM type expected by the module. The default + is the default DBM type created with + httxt2dbm

+ +
+
top
+

ProxyExpressEnable Directive

+ + + + + + + + +
Description:Enable the module functionality.
Syntax:ProxyExpressEnable [on|off]
Default:off
Context:server config, virtual host
Status:Extension
Module:mod_proxy_express
Compatibility:Available in Apache 2.3.13 and later
+

The ProxyExpressEnable directive + controls whether the module will be active.

+ +
+
+
+

Available Languages:  en 

+
+ \ No newline at end of file diff --git a/docs/manual/mod/mod_proxy_express.xml b/docs/manual/mod/mod_proxy_express.xml new file mode 100644 index 00000000000..1ca43e184f9 --- /dev/null +++ b/docs/manual/mod/mod_proxy_express.xml @@ -0,0 +1,151 @@ + + + + + + + + + +mod_proxy_express +Dynamic mass reverse proxy extension for +mod_proxy +Extension +mod_proxy_express.c +proxy_express_module + + +

This module creates dynamically configured mass reverse + proxies, by mapping the Host: header of the HTTP request to + a server name and backend URL stored in a DBM file. + This allows for easy use of a huge number of reverse proxies + with no configuration changes. It is much less feature-full + than mod_proxy_balancer, which also provides + dynamic growth, but is intended to handle much, much + larger numbers of backends. It is ideally suited as a + front-end HTTP switch.

+ +

This module requires the service of mod_proxy.

+ + Warning +

Do not enable proxying until you have secured your server. Open proxy + servers are dangerous both to your network and to the Internet at + large.

+
+ +Limitations +
    +
  • This module is not intended to replace the dynamic capability of + mod_proxy_balancer. Instead, it is intended to be mostly + a lightweight and fast alternative to using mod_rewrite + with RewriteMap and the [P] flag + for mapped reverse proxying. +
  • +
  • It does not support regex or pattern matching at all. +
  • +
  • It emulates: + + ProxyPass / backend.server:port
    + ProxyPassReverse / backend.server:port
    +
    + That is, the entire URL is appended to the mapped backend + URL. This is in keeping with the intent of being a simple + but fast reverse proxy switch. +
  • +
+
+ +
+mod_proxy + + +ProxyExpressEnable +Enable the module functionality. +ProxyExpressEnable [on|off] +off +server configvirtual host + +Available in Apache 2.3.13 and later + + +

The ProxyExpressEnable directive + controls whether the module will be active.

+
+
+ + +ProxyExpressDBMFile +Pathname to DBM file. +ProxyExpressDBMFile <pathname> +None +server configvirtual host + +Available in Apache 2.3.13 and later + + +

The ProxyExpressDBMFile directive + points to the location of the Express map DBM file. This + file serves to map the incoming server name, obtained from + the Host: header, to a backend URL.

+ + Note +

The file is constructed from a plain text file format using + the httxt2dbm + utility.

+ + ProxyExpress map file + ##
+ ##express-map.txt:
+ ##
+
+ www1.example.com http://192.168.211.2:8080
+ www2.example.com http://192.168.211.12:8088
+ www3.example.com http://192.168.212.10
+
+ + Create DBM file + httxt2dbm -i express-map.txt -o emap
+
+ + Configuration + ProxyExpressDBMFile emap
+
+
+
+
+ + +ProxyExpressDBMType +DBM type of file. +ProxyExpressDBMFile <type> +"default" +server configvirtual host + +Available in Apache 2.3.13 and later + + +

The ProxyExpressDBMType directive + controls the DBM type expected by the module. The default + is the default DBM type created with + httxt2dbm

+
+
+ +
diff --git a/docs/manual/mod/mod_proxy_express.xml.meta b/docs/manual/mod/mod_proxy_express.xml.meta new file mode 100644 index 00000000000..a0a06bf7e9c --- /dev/null +++ b/docs/manual/mod/mod_proxy_express.xml.meta @@ -0,0 +1,12 @@ + + + + + mod_proxy_express + /mod/ + .. + + + en + + diff --git a/modules/proxy/mod_proxy_express.c b/modules/proxy/mod_proxy_express.c new file mode 100644 index 00000000000..40b3372e911 --- /dev/null +++ b/modules/proxy/mod_proxy_express.c @@ -0,0 +1,228 @@ +/* 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 "mod_proxy.h" +#include "apr_dbm.h" + +module AP_MODULE_DECLARE_DATA proxy_express_module; + +static int proxy_available = 0; + +typedef struct { + char *dbmfile; + char *dbmtype; + int enabled; +} express_server_conf; + +static const char *set_dbmfile(cmd_parms *cmd, + void *dconf, + const char *arg) +{ + express_server_conf *sconf; + sconf = ap_get_module_config(cmd->server->module_config, &proxy_express_module); + + if ((sconf->dbmfile = ap_server_root_relative(cmd->pool, arg)) == NULL) { + return apr_pstrcat(cmd->pool, "ProxyExpressDBMFile: bad path to file: ", + arg, NULL); + } + return NULL; +} + +static const char *set_dbmtype(cmd_parms *cmd, + void *dconf, + const char *arg) +{ + express_server_conf *sconf; + sconf = ap_get_module_config(cmd->server->module_config, &proxy_express_module); + + sconf->dbmtype = apr_pstrdup(cmd->pool, arg); + return NULL; +} + +static const char *set_enabled(cmd_parms *cmd, + void *dconf, + int flag) +{ + express_server_conf *sconf; + sconf = ap_get_module_config(cmd->server->module_config, &proxy_express_module); + + sconf->enabled = flag; + + return NULL; +} + +static void *server_create(apr_pool_t *p, server_rec *s) +{ + express_server_conf *a; + + a = (express_server_conf *)apr_pcalloc(p, sizeof(express_server_conf)); + + a->dbmfile = NULL; + a->dbmtype = "default"; + a->enabled = 0; + + return (void *)a; +} + +static void *server_merge(apr_pool_t *p, void *basev, void *overridesv) +{ + express_server_conf *a, *base, *overrides; + + a = (express_server_conf *)apr_pcalloc(p, + sizeof(express_server_conf)); + base = (express_server_conf *)basev; + overrides = (express_server_conf *)overridesv; + + a->dbmfile = (overrides->dbmfile) ? overrides->dbmfile : base->dbmfile; + a->dbmtype = (overrides->dbmtype) ? overrides->dbmtype : base->dbmtype; + a->enabled = (overrides->enabled) ? overrides->enabled : base->enabled; + + return (void *)a; +} + +static int post_config(apr_pool_t *p, + apr_pool_t *plog, + apr_pool_t *ptemp, + server_rec *s) +{ + proxy_available = (ap_find_linked_module("mod_proxy.c") != NULL); + return OK; +} + + +static int xlate_name(request_rec *r) +{ + int i; + const char *name; + char *backend; + apr_dbm_t *db; + apr_status_t rv; + apr_datum_t key, val; + struct proxy_alias *ralias; + proxy_dir_conf *dconf; + express_server_conf *sconf; + + sconf = ap_get_module_config(r->server->module_config, &proxy_express_module); + dconf = ap_get_module_config(r->per_dir_config, &proxy_module); + + if (!sconf->enabled) { + return DECLINED; + } + + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, + "proxy_express: Enabled"); + if (!sconf->dbmfile || (r->filename && strncmp(r->filename, "proxy:", 6) == 0)) { + /* it should be go on as an internal proxy request */ + return DECLINED; + } + + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, + "proxy_express: Opening DBM file: %s (%s)", + sconf->dbmfile, sconf->dbmtype); + rv = apr_dbm_open_ex(&db, sconf->dbmtype, sconf->dbmfile, APR_DBM_READONLY, + APR_OS_DEFAULT, r->pool); + if (rv != APR_SUCCESS) { + return DECLINED; + } + + name = ap_get_server_name(r); + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, + "proxy_express: looking for %s", name); + key.dptr = (char *)name; + key.dsize = strlen(key.dptr); + + rv = apr_dbm_fetch(db, key, &val); + apr_dbm_close(db); + if (rv != APR_SUCCESS) { + return DECLINED; + } + + backend = apr_pstrmemdup(r->pool, val.dptr, val.dsize); + if (!backend) { + return DECLINED; + } + + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, + "proxy_express: found %s -> %s", name, backend); + r->filename = apr_pstrcat(r->pool, "proxy:", backend, r->uri, NULL); + r->handler = "proxy-server"; + r->proxyreq = PROXYREQ_REVERSE; + + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, + "proxy_express: rewritten as: %s", r->filename); + + ralias = (struct proxy_alias *)dconf->raliases->elts; + /* + * See if we have already added a ProxyPassReverse entry + * for this host... If so, don't do it again. + */ + /* + * NOTE: dconf is process specific so this wil only + * work as long as we maintain that this process + * or thread is handling the backend + */ + for (i = 0; i < dconf->raliases->nelts; i++, ralias++) { + if (strcasecmp(backend, ralias->real) == 0) { + ralias = NULL; + break; + } + } + + /* Didn't find one... add it */ + if (!ralias) { + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, + "proxy_express: adding PPR entry"); + ralias = apr_array_push(dconf->raliases); + ralias->fake = "/"; + ralias->real = backend; + ralias->flags = 0; + } + return OK; +} + +static const command_rec command_table[] = { + AP_INIT_FLAG("ProxyExpressEnable", set_enabled, NULL, OR_FILEINFO, + "Enable the ProxyExpress functionality"), + AP_INIT_TAKE1("ProxyExpressDBMFile", set_dbmfile, NULL, OR_FILEINFO, + "Location of ProxyExpressDBMFile file"), + AP_INIT_TAKE1("ProxyExpressDBMType", set_dbmtype, NULL, OR_FILEINFO, + "Type of ProxyExpressDBMFile file"), + { NULL } +}; + +static void register_hooks(apr_pool_t *p) +{ + ap_hook_post_config(post_config, NULL, NULL, APR_HOOK_LAST); + ap_hook_translate_name(xlate_name, NULL, NULL, APR_HOOK_FIRST); +} + +/* the main config structure */ + +#if MODULE_MAGIC_COOKIE == 0x41503234UL +AP_DECLARE_MODULE(proxy_express) = +#else +module AP_MODULE_DECLARE_DATA proxy_express = +#endif +{ + STANDARD20_MODULE_STUFF, + NULL, /* create per-dir config structures */ + NULL, /* merge per-dir config structures */ + server_create, /* create per-server config structures */ + server_merge, /* merge per-server config structures */ + command_table, /* table of config file commands */ + register_hooks /* register hooks */ +}; +