83c89da783ba8bdaef50ec1912443f7fad3556acjim/* Licensed to the Apache Software Foundation (ASF) under one or more
83c89da783ba8bdaef50ec1912443f7fad3556acjim * contributor license agreements. See the NOTICE file distributed with
83c89da783ba8bdaef50ec1912443f7fad3556acjim * this work for additional information regarding copyright ownership.
83c89da783ba8bdaef50ec1912443f7fad3556acjim * The ASF licenses this file to You under the Apache License, Version 2.0
83c89da783ba8bdaef50ec1912443f7fad3556acjim * (the "License"); you may not use this file except in compliance with
83c89da783ba8bdaef50ec1912443f7fad3556acjim * the License. You may obtain a copy of the License at
83c89da783ba8bdaef50ec1912443f7fad3556acjim *
83c89da783ba8bdaef50ec1912443f7fad3556acjim * http://www.apache.org/licenses/LICENSE-2.0
83c89da783ba8bdaef50ec1912443f7fad3556acjim *
83c89da783ba8bdaef50ec1912443f7fad3556acjim * Unless required by applicable law or agreed to in writing, software
83c89da783ba8bdaef50ec1912443f7fad3556acjim * distributed under the License is distributed on an "AS IS" BASIS,
83c89da783ba8bdaef50ec1912443f7fad3556acjim * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
83c89da783ba8bdaef50ec1912443f7fad3556acjim * See the License for the specific language governing permissions and
83c89da783ba8bdaef50ec1912443f7fad3556acjim * limitations under the License.
83c89da783ba8bdaef50ec1912443f7fad3556acjim */
83c89da783ba8bdaef50ec1912443f7fad3556acjim
83c89da783ba8bdaef50ec1912443f7fad3556acjim#include "mod_proxy.h"
83c89da783ba8bdaef50ec1912443f7fad3556acjim#include "apr_dbm.h"
83c89da783ba8bdaef50ec1912443f7fad3556acjim
83c89da783ba8bdaef50ec1912443f7fad3556acjimmodule AP_MODULE_DECLARE_DATA proxy_express_module;
83c89da783ba8bdaef50ec1912443f7fad3556acjim
83c89da783ba8bdaef50ec1912443f7fad3556acjimstatic int proxy_available = 0;
83c89da783ba8bdaef50ec1912443f7fad3556acjim
83c89da783ba8bdaef50ec1912443f7fad3556acjimtypedef struct {
83c89da783ba8bdaef50ec1912443f7fad3556acjim char *dbmfile;
83c89da783ba8bdaef50ec1912443f7fad3556acjim char *dbmtype;
83c89da783ba8bdaef50ec1912443f7fad3556acjim int enabled;
83c89da783ba8bdaef50ec1912443f7fad3556acjim} express_server_conf;
83c89da783ba8bdaef50ec1912443f7fad3556acjim
83c89da783ba8bdaef50ec1912443f7fad3556acjimstatic const char *set_dbmfile(cmd_parms *cmd,
83c89da783ba8bdaef50ec1912443f7fad3556acjim void *dconf,
83c89da783ba8bdaef50ec1912443f7fad3556acjim const char *arg)
83c89da783ba8bdaef50ec1912443f7fad3556acjim{
83c89da783ba8bdaef50ec1912443f7fad3556acjim express_server_conf *sconf;
83c89da783ba8bdaef50ec1912443f7fad3556acjim sconf = ap_get_module_config(cmd->server->module_config, &proxy_express_module);
83c89da783ba8bdaef50ec1912443f7fad3556acjim
83c89da783ba8bdaef50ec1912443f7fad3556acjim if ((sconf->dbmfile = ap_server_root_relative(cmd->pool, arg)) == NULL) {
83c89da783ba8bdaef50ec1912443f7fad3556acjim return apr_pstrcat(cmd->pool, "ProxyExpressDBMFile: bad path to file: ",
83c89da783ba8bdaef50ec1912443f7fad3556acjim arg, NULL);
83c89da783ba8bdaef50ec1912443f7fad3556acjim }
83c89da783ba8bdaef50ec1912443f7fad3556acjim return NULL;
83c89da783ba8bdaef50ec1912443f7fad3556acjim}
83c89da783ba8bdaef50ec1912443f7fad3556acjim
83c89da783ba8bdaef50ec1912443f7fad3556acjimstatic const char *set_dbmtype(cmd_parms *cmd,
83c89da783ba8bdaef50ec1912443f7fad3556acjim void *dconf,
83c89da783ba8bdaef50ec1912443f7fad3556acjim const char *arg)
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim{
83c89da783ba8bdaef50ec1912443f7fad3556acjim express_server_conf *sconf;
83c89da783ba8bdaef50ec1912443f7fad3556acjim sconf = ap_get_module_config(cmd->server->module_config, &proxy_express_module);
83c89da783ba8bdaef50ec1912443f7fad3556acjim
83c89da783ba8bdaef50ec1912443f7fad3556acjim sconf->dbmtype = apr_pstrdup(cmd->pool, arg);
83c89da783ba8bdaef50ec1912443f7fad3556acjim return NULL;
83c89da783ba8bdaef50ec1912443f7fad3556acjim}
83c89da783ba8bdaef50ec1912443f7fad3556acjim
83c89da783ba8bdaef50ec1912443f7fad3556acjimstatic const char *set_enabled(cmd_parms *cmd,
83c89da783ba8bdaef50ec1912443f7fad3556acjim void *dconf,
83c89da783ba8bdaef50ec1912443f7fad3556acjim int flag)
83c89da783ba8bdaef50ec1912443f7fad3556acjim{
83c89da783ba8bdaef50ec1912443f7fad3556acjim express_server_conf *sconf;
83c89da783ba8bdaef50ec1912443f7fad3556acjim sconf = ap_get_module_config(cmd->server->module_config, &proxy_express_module);
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim
83c89da783ba8bdaef50ec1912443f7fad3556acjim sconf->enabled = flag;
83c89da783ba8bdaef50ec1912443f7fad3556acjim
83c89da783ba8bdaef50ec1912443f7fad3556acjim return NULL;
83c89da783ba8bdaef50ec1912443f7fad3556acjim}
83c89da783ba8bdaef50ec1912443f7fad3556acjim
83c89da783ba8bdaef50ec1912443f7fad3556acjimstatic void *server_create(apr_pool_t *p, server_rec *s)
83c89da783ba8bdaef50ec1912443f7fad3556acjim{
83c89da783ba8bdaef50ec1912443f7fad3556acjim express_server_conf *a;
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim
83c89da783ba8bdaef50ec1912443f7fad3556acjim a = (express_server_conf *)apr_pcalloc(p, sizeof(express_server_conf));
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim
83c89da783ba8bdaef50ec1912443f7fad3556acjim a->dbmfile = NULL;
83c89da783ba8bdaef50ec1912443f7fad3556acjim a->dbmtype = "default";
83c89da783ba8bdaef50ec1912443f7fad3556acjim a->enabled = 0;
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim
83c89da783ba8bdaef50ec1912443f7fad3556acjim return (void *)a;
83c89da783ba8bdaef50ec1912443f7fad3556acjim}
83c89da783ba8bdaef50ec1912443f7fad3556acjim
83c89da783ba8bdaef50ec1912443f7fad3556acjimstatic void *server_merge(apr_pool_t *p, void *basev, void *overridesv)
83c89da783ba8bdaef50ec1912443f7fad3556acjim{
83c89da783ba8bdaef50ec1912443f7fad3556acjim express_server_conf *a, *base, *overrides;
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim
83c89da783ba8bdaef50ec1912443f7fad3556acjim a = (express_server_conf *)apr_pcalloc(p,
83c89da783ba8bdaef50ec1912443f7fad3556acjim sizeof(express_server_conf));
83c89da783ba8bdaef50ec1912443f7fad3556acjim base = (express_server_conf *)basev;
83c89da783ba8bdaef50ec1912443f7fad3556acjim overrides = (express_server_conf *)overridesv;
83c89da783ba8bdaef50ec1912443f7fad3556acjim
83c89da783ba8bdaef50ec1912443f7fad3556acjim a->dbmfile = (overrides->dbmfile) ? overrides->dbmfile : base->dbmfile;
83c89da783ba8bdaef50ec1912443f7fad3556acjim a->dbmtype = (overrides->dbmtype) ? overrides->dbmtype : base->dbmtype;
83c89da783ba8bdaef50ec1912443f7fad3556acjim a->enabled = (overrides->enabled) ? overrides->enabled : base->enabled;
83c89da783ba8bdaef50ec1912443f7fad3556acjim
83c89da783ba8bdaef50ec1912443f7fad3556acjim return (void *)a;
83c89da783ba8bdaef50ec1912443f7fad3556acjim}
83c89da783ba8bdaef50ec1912443f7fad3556acjim
83c89da783ba8bdaef50ec1912443f7fad3556acjimstatic int post_config(apr_pool_t *p,
83c89da783ba8bdaef50ec1912443f7fad3556acjim apr_pool_t *plog,
83c89da783ba8bdaef50ec1912443f7fad3556acjim apr_pool_t *ptemp,
83c89da783ba8bdaef50ec1912443f7fad3556acjim server_rec *s)
83c89da783ba8bdaef50ec1912443f7fad3556acjim{
83c89da783ba8bdaef50ec1912443f7fad3556acjim proxy_available = (ap_find_linked_module("mod_proxy.c") != NULL);
83c89da783ba8bdaef50ec1912443f7fad3556acjim return OK;
83c89da783ba8bdaef50ec1912443f7fad3556acjim}
83c89da783ba8bdaef50ec1912443f7fad3556acjim
83c89da783ba8bdaef50ec1912443f7fad3556acjim
83c89da783ba8bdaef50ec1912443f7fad3556acjimstatic int xlate_name(request_rec *r)
83c89da783ba8bdaef50ec1912443f7fad3556acjim{
83c89da783ba8bdaef50ec1912443f7fad3556acjim int i;
83c89da783ba8bdaef50ec1912443f7fad3556acjim const char *name;
83c89da783ba8bdaef50ec1912443f7fad3556acjim char *backend;
83c89da783ba8bdaef50ec1912443f7fad3556acjim apr_dbm_t *db;
83c89da783ba8bdaef50ec1912443f7fad3556acjim apr_status_t rv;
83c89da783ba8bdaef50ec1912443f7fad3556acjim apr_datum_t key, val;
83c89da783ba8bdaef50ec1912443f7fad3556acjim struct proxy_alias *ralias;
83c89da783ba8bdaef50ec1912443f7fad3556acjim proxy_dir_conf *dconf;
83c89da783ba8bdaef50ec1912443f7fad3556acjim express_server_conf *sconf;
83c89da783ba8bdaef50ec1912443f7fad3556acjim
83c89da783ba8bdaef50ec1912443f7fad3556acjim sconf = ap_get_module_config(r->server->module_config, &proxy_express_module);
83c89da783ba8bdaef50ec1912443f7fad3556acjim dconf = ap_get_module_config(r->per_dir_config, &proxy_module);
83c89da783ba8bdaef50ec1912443f7fad3556acjim
83c89da783ba8bdaef50ec1912443f7fad3556acjim if (!sconf->enabled) {
83c89da783ba8bdaef50ec1912443f7fad3556acjim return DECLINED;
83c89da783ba8bdaef50ec1912443f7fad3556acjim }
83c89da783ba8bdaef50ec1912443f7fad3556acjim
185aa71728867671e105178b4c66fbc22b65ae26sf ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01001) "proxy_express: Enabled");
83c89da783ba8bdaef50ec1912443f7fad3556acjim if (!sconf->dbmfile || (r->filename && strncmp(r->filename, "proxy:", 6) == 0)) {
83c89da783ba8bdaef50ec1912443f7fad3556acjim /* it should be go on as an internal proxy request */
83c89da783ba8bdaef50ec1912443f7fad3556acjim return DECLINED;
83c89da783ba8bdaef50ec1912443f7fad3556acjim }
83c89da783ba8bdaef50ec1912443f7fad3556acjim
185aa71728867671e105178b4c66fbc22b65ae26sf ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01002)
e6061cf1962bb4bcce89c2bdce375398d614be6asf "proxy_express: Opening DBM file: %s (%s)",
e6061cf1962bb4bcce89c2bdce375398d614be6asf sconf->dbmfile, sconf->dbmtype);
83c89da783ba8bdaef50ec1912443f7fad3556acjim rv = apr_dbm_open_ex(&db, sconf->dbmtype, sconf->dbmfile, APR_DBM_READONLY,
83c89da783ba8bdaef50ec1912443f7fad3556acjim APR_OS_DEFAULT, r->pool);
83c89da783ba8bdaef50ec1912443f7fad3556acjim if (rv != APR_SUCCESS) {
83c89da783ba8bdaef50ec1912443f7fad3556acjim return DECLINED;
83c89da783ba8bdaef50ec1912443f7fad3556acjim }
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim
83c89da783ba8bdaef50ec1912443f7fad3556acjim name = ap_get_server_name(r);
185aa71728867671e105178b4c66fbc22b65ae26sf ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01003)
e6061cf1962bb4bcce89c2bdce375398d614be6asf "proxy_express: looking for %s", name);
83c89da783ba8bdaef50ec1912443f7fad3556acjim key.dptr = (char *)name;
83c89da783ba8bdaef50ec1912443f7fad3556acjim key.dsize = strlen(key.dptr);
83c89da783ba8bdaef50ec1912443f7fad3556acjim
83c89da783ba8bdaef50ec1912443f7fad3556acjim rv = apr_dbm_fetch(db, key, &val);
83c89da783ba8bdaef50ec1912443f7fad3556acjim apr_dbm_close(db);
83c89da783ba8bdaef50ec1912443f7fad3556acjim if (rv != APR_SUCCESS) {
83c89da783ba8bdaef50ec1912443f7fad3556acjim return DECLINED;
83c89da783ba8bdaef50ec1912443f7fad3556acjim }
83c89da783ba8bdaef50ec1912443f7fad3556acjim
83c89da783ba8bdaef50ec1912443f7fad3556acjim backend = apr_pstrmemdup(r->pool, val.dptr, val.dsize);
83c89da783ba8bdaef50ec1912443f7fad3556acjim if (!backend) {
83c89da783ba8bdaef50ec1912443f7fad3556acjim return DECLINED;
83c89da783ba8bdaef50ec1912443f7fad3556acjim }
83c89da783ba8bdaef50ec1912443f7fad3556acjim
185aa71728867671e105178b4c66fbc22b65ae26sf ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01004)
e6061cf1962bb4bcce89c2bdce375398d614be6asf "proxy_express: found %s -> %s", name, backend);
83c89da783ba8bdaef50ec1912443f7fad3556acjim r->filename = apr_pstrcat(r->pool, "proxy:", backend, r->uri, NULL);
83c89da783ba8bdaef50ec1912443f7fad3556acjim r->handler = "proxy-server";
83c89da783ba8bdaef50ec1912443f7fad3556acjim r->proxyreq = PROXYREQ_REVERSE;
83c89da783ba8bdaef50ec1912443f7fad3556acjim
185aa71728867671e105178b4c66fbc22b65ae26sf ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01005)
e6061cf1962bb4bcce89c2bdce375398d614be6asf "proxy_express: rewritten as: %s", r->filename);
83c89da783ba8bdaef50ec1912443f7fad3556acjim
83c89da783ba8bdaef50ec1912443f7fad3556acjim ralias = (struct proxy_alias *)dconf->raliases->elts;
83c89da783ba8bdaef50ec1912443f7fad3556acjim /*
83c89da783ba8bdaef50ec1912443f7fad3556acjim * See if we have already added a ProxyPassReverse entry
83c89da783ba8bdaef50ec1912443f7fad3556acjim * for this host... If so, don't do it again.
83c89da783ba8bdaef50ec1912443f7fad3556acjim */
83c89da783ba8bdaef50ec1912443f7fad3556acjim /*
83c89da783ba8bdaef50ec1912443f7fad3556acjim * NOTE: dconf is process specific so this wil only
83c89da783ba8bdaef50ec1912443f7fad3556acjim * work as long as we maintain that this process
83c89da783ba8bdaef50ec1912443f7fad3556acjim * or thread is handling the backend
83c89da783ba8bdaef50ec1912443f7fad3556acjim */
83c89da783ba8bdaef50ec1912443f7fad3556acjim for (i = 0; i < dconf->raliases->nelts; i++, ralias++) {
83c89da783ba8bdaef50ec1912443f7fad3556acjim if (strcasecmp(backend, ralias->real) == 0) {
83c89da783ba8bdaef50ec1912443f7fad3556acjim ralias = NULL;
83c89da783ba8bdaef50ec1912443f7fad3556acjim break;
83c89da783ba8bdaef50ec1912443f7fad3556acjim }
83c89da783ba8bdaef50ec1912443f7fad3556acjim }
83c89da783ba8bdaef50ec1912443f7fad3556acjim
83c89da783ba8bdaef50ec1912443f7fad3556acjim /* Didn't find one... add it */
83c89da783ba8bdaef50ec1912443f7fad3556acjim if (!ralias) {
185aa71728867671e105178b4c66fbc22b65ae26sf ap_log_rerror(APLOG_MARK, APLOG_DEBUG, 0, r, APLOGNO(01006)
e6061cf1962bb4bcce89c2bdce375398d614be6asf "proxy_express: adding PPR entry");
83c89da783ba8bdaef50ec1912443f7fad3556acjim ralias = apr_array_push(dconf->raliases);
83c89da783ba8bdaef50ec1912443f7fad3556acjim ralias->fake = "/";
c659b85c58d3bd150dafc8cb6819acba2af6c2f1jim ralias->real = apr_pstrdup(dconf->raliases->pool, backend);
83c89da783ba8bdaef50ec1912443f7fad3556acjim ralias->flags = 0;
83c89da783ba8bdaef50ec1912443f7fad3556acjim }
83c89da783ba8bdaef50ec1912443f7fad3556acjim return OK;
83c89da783ba8bdaef50ec1912443f7fad3556acjim}
83c89da783ba8bdaef50ec1912443f7fad3556acjim
83c89da783ba8bdaef50ec1912443f7fad3556acjimstatic const command_rec command_table[] = {
83c89da783ba8bdaef50ec1912443f7fad3556acjim AP_INIT_FLAG("ProxyExpressEnable", set_enabled, NULL, OR_FILEINFO,
83c89da783ba8bdaef50ec1912443f7fad3556acjim "Enable the ProxyExpress functionality"),
83c89da783ba8bdaef50ec1912443f7fad3556acjim AP_INIT_TAKE1("ProxyExpressDBMFile", set_dbmfile, NULL, OR_FILEINFO,
83c89da783ba8bdaef50ec1912443f7fad3556acjim "Location of ProxyExpressDBMFile file"),
83c89da783ba8bdaef50ec1912443f7fad3556acjim AP_INIT_TAKE1("ProxyExpressDBMType", set_dbmtype, NULL, OR_FILEINFO,
83c89da783ba8bdaef50ec1912443f7fad3556acjim "Type of ProxyExpressDBMFile file"),
83c89da783ba8bdaef50ec1912443f7fad3556acjim { NULL }
83c89da783ba8bdaef50ec1912443f7fad3556acjim};
83c89da783ba8bdaef50ec1912443f7fad3556acjim
83c89da783ba8bdaef50ec1912443f7fad3556acjimstatic void register_hooks(apr_pool_t *p)
83c89da783ba8bdaef50ec1912443f7fad3556acjim{
83c89da783ba8bdaef50ec1912443f7fad3556acjim ap_hook_post_config(post_config, NULL, NULL, APR_HOOK_LAST);
83c89da783ba8bdaef50ec1912443f7fad3556acjim ap_hook_translate_name(xlate_name, NULL, NULL, APR_HOOK_FIRST);
83c89da783ba8bdaef50ec1912443f7fad3556acjim}
83c89da783ba8bdaef50ec1912443f7fad3556acjim
83c89da783ba8bdaef50ec1912443f7fad3556acjim/* the main config structure */
83c89da783ba8bdaef50ec1912443f7fad3556acjim
83c89da783ba8bdaef50ec1912443f7fad3556acjimAP_DECLARE_MODULE(proxy_express) =
83c89da783ba8bdaef50ec1912443f7fad3556acjim{
83c89da783ba8bdaef50ec1912443f7fad3556acjim STANDARD20_MODULE_STUFF,
83c89da783ba8bdaef50ec1912443f7fad3556acjim NULL, /* create per-dir config structures */
83c89da783ba8bdaef50ec1912443f7fad3556acjim NULL, /* merge per-dir config structures */
83c89da783ba8bdaef50ec1912443f7fad3556acjim server_create, /* create per-server config structures */
83c89da783ba8bdaef50ec1912443f7fad3556acjim server_merge, /* merge per-server config structures */
83c89da783ba8bdaef50ec1912443f7fad3556acjim command_table, /* table of config file commands */
83c89da783ba8bdaef50ec1912443f7fad3556acjim register_hooks /* register hooks */
83c89da783ba8bdaef50ec1912443f7fad3556acjim};
83c89da783ba8bdaef50ec1912443f7fad3556acjim