Index: docs/manual/mod/core.xml
===================================================================
--- docs/manual/mod/core.xml	(revision 387131)
+++ docs/manual/mod/core.xml	(working copy)
@@ -1041,6 +1041,108 @@
 </directivesynopsis>
 
 <directivesynopsis>
+<name>ExternalListenerPort</name>
+<description>Listening port of external device</description>
+<syntax>ExternalListenerPort <var>portnumber</var></syntax>
+<default>ExternalListenerPort 0</default>
+<contextlist><context>server config</context><context>virtual host</context>
+<context>directory</context></contextlist>
+<usage>
+    <p>When Apache HTTP Server constructs a <em>self-referential</em>
+    URL, it needs to include its listening port in the URL so the client
+    can connect back to the correct server instance. However, in
+    situations where the Apache HTTP Server is running behind an
+    external device, the httpd listener port is not necessarily the port
+    to which the client connects. Examples of such devices are a reverse
+    proxy, load balancer or SSL offload appliance. In these cases, the
+    listening port of the front-end device needs to be included in the
+    self-referential URL. The <code>ExternalListenerPort</code>
+    specifies this port number.</p>
+    
+    <p>The effect of <code>ExternalListenerPort</code> is subject to the
+    values of <directive module="core">UseCanonicalName</directive> and
+    <directive module="core">UseCanonicalPhysicalPort</directive>. If
+    <code>UseCanonicalName on</code> is in effect, the server will use
+    <code>ExternalListenerPort</code> to construct self-referential
+    URLs.</p>
+    
+    <example><title>Example</title>
+        <p>An external load balancer is listening on port 80 and
+        forwarding http traffic to port 8080. Self-referential URLs
+        should not include port 8080, but instead implicitly specify
+        port 80 (the default port for HTTP traffic):</p>
+        &lt;VirtualHost 10.1.2.3:8080&gt;<br />
+        <indent>
+            ServerName www.example.com<br />
+            # Don't trust what the client tells us<br />
+            UseCanonicalName on<br />
+            ExternalListenerPort 80<br />
+            ...<br />
+        </indent>
+        &lt;/VirtualHost&gt;<br />
+        <p>Self-referential URLs will be of the form
+        <code>http://www.example.com/...</code>.</p>
+    </example>
+    
+    <p>Use <code>ExternalListenerPort 0</code> to disable an inherited
+    setting.</p>
+</usage>
+<seealso><directive module="core">UseCanonicalName</directive></seealso>
+<seealso><directive module="core">UseCanonicalPhysicalPort</directive></seealso>
+<seealso><directive module="core">ExternalListenerPort</directive></seealso>
+</directivesynopsis>
+
+<directivesynopsis>
+<name>ExternalListenerScheme</name>
+<description>Protocol scheme used by external listening device</description>
+<syntax>ExternalListenerScheme http|https</syntax>
+<default>ExternalListenerScheme http</default>
+<contextlist><context>server config</context><context>virtual host</context>
+<context>directory</context></contextlist>
+<usage>
+    <p>When Apache HTTP Server constructs a <em>self-referential</em>
+    URL, it includes the <em>protocol scheme</em> used by the server. If
+    the Apache HTTP Server is running behind an external SSL offload
+    device, the client connects to the Apache HTTP Server over https
+    even though the server itself is running plaintext http. Examples of
+    such devices include a reverse proxy, load balancer or appliance
+    that processes SSL connections. In this case, self-referential URLs
+    have to include the <code>https://</code> protocol scheme to keep
+    the client from connecting to the server using the wrong scheme. The
+    <code>ExternalListenerScheme</code> specifies whether the scheme
+    used for self-referential URLs is <em>http</em> or
+    <em>https</em>.</p>
+    
+    <p>This directive should be used in combination with <directive
+    module="core">ExternalListenerPort</directive>.</p>
+    
+    <example><title>Example</title>
+        <p>An external load balancer is processing incoming SSL
+        connections on port 443 and forwards the connection data as
+        plaintext http connections to the Apache HTTP Server on port
+        8080. Self-referential URLs should specify the https protocol
+        and implicitly specify port 443, the default protocol for HTTPS
+        traffic:</p>
+        &lt;VirtualHost 10.1.2.3:8080&gt;<br />
+        <indent>
+            ServerName www.example.com<br />
+            # Don't trust what the client tells us<br />
+            UseCanonicalName on<br />
+            ExternalListenerPort 443<br />
+            ExternalListenerScheme https<br />
+            ...<br />
+        </indent>
+        &lt;/VirtualHost&gt;<br />
+        <p>Self-referential URLs will be of the form
+        <code>https://www.example.com/...</code>.</p>
+    </example>
+</usage>
+<seealso><directive module="core">UseCanonicalName</directive></seealso>
+<seealso><directive module="core">UseCanonicalPhysicalPort</directive></seealso>
+<seealso><directive module="core">ExternalListenerScheme</directive></seealso>
+</directivesynopsis>
+
+<directivesynopsis>
 <name>FileETag</name>
 <description>File attributes used to create the ETag
 HTTP response header</description>
Index: server/core.c
===================================================================
--- server/core.c	(revision 387131)
+++ server/core.c	(working copy)
@@ -115,6 +115,9 @@
 
     conf->use_canonical_name = USE_CANONICAL_NAME_UNSET;
     conf->use_canonical_phys_port = USE_CANONICAL_PHYS_PORT_UNSET;
+    
+    conf->external_listener_port = 0;
+    conf->external_listener_scheme = EXTERNAL_LISTENER_SCHEME_HTTP;
 
     conf->hostname_lookups = HOSTNAME_LOOKUP_UNSET;
 
@@ -302,6 +305,14 @@
     if (new->use_canonical_phys_port != USE_CANONICAL_PHYS_PORT_UNSET) {
         conf->use_canonical_phys_port = new->use_canonical_phys_port;
     }
+    
+    if (new->external_listener_port != 0) {
+        conf->external_listener_port = new->external_listener_port;
+    }
+    
+    if (new->external_listener_scheme != EXTERNAL_LISTENER_SCHEME_HTTP) {
+        conf->external_listener_scheme = new->external_listener_scheme;
+    }
 
 #ifdef RLIMIT_CPU
     if (new->limit_cpu) {
@@ -927,12 +938,14 @@
         case USE_CANONICAL_NAME_DNS:
         case USE_CANONICAL_NAME_UNSET:
             if (d->use_canonical_phys_port == USE_CANONICAL_PHYS_PORT_ON)
-                port = r->parsed_uri.port_str ? r->parsed_uri.port :
+                port = d->external_listener_port ? d->external_listener_port : 
+                       r->parsed_uri.port_str ? r->parsed_uri.port :
                        r->connection->local_addr->port ? r->connection->local_addr->port :
                        r->server->port ? r->server->port :
                        ap_default_port(r);
             else /* USE_CANONICAL_PHYS_PORT_OFF or USE_CANONICAL_PHYS_PORT_UNSET */
-                port = r->parsed_uri.port_str ? r->parsed_uri.port :
+                port = d->external_listener_port ? d->external_listener_port : 
+                       r->parsed_uri.port_str ? r->parsed_uri.port :
                        r->server->port ? r->server->port :
                        ap_default_port(r);
             break;
@@ -946,11 +959,13 @@
              * used.
              */
             if (d->use_canonical_phys_port == USE_CANONICAL_PHYS_PORT_ON)
-                port = r->server->port ? r->server->port :
+                port = d->external_listener_port ? d->external_listener_port : 
+                       r->server->port ? r->server->port :
                        r->connection->local_addr->port ? r->connection->local_addr->port :
                        ap_default_port(r);
             else /* USE_CANONICAL_PHYS_PORT_OFF or USE_CANONICAL_PHYS_PORT_UNSET */
-                port = r->server->port ? r->server->port :
+                port = d->external_listener_port ? d->external_listener_port : 
+                       r->server->port ? r->server->port :
                        ap_default_port(r);
             break;
         default:
@@ -2447,7 +2462,53 @@
     return NULL;
 }
 
+static const char *set_external_listener_port (cmd_parms *cmd, void *d_, 
+                                               const char *arg)
+{
+    int port = 0;
+    core_dir_config *d = d_;
+    const char *err = ap_check_cmd_context(cmd, NOT_IN_LIMIT);
 
+    if (err != NULL) {
+        return err;
+    }
+
+    port = atoi(arg);
+    if (port <= 0 || port >= 65536) {
+        return apr_pstrcat(cmd->temp_pool, "The port number \"", arg, 
+                           "\" is outside the appropriate range ", 
+                           "(i.e., 1..65535).", NULL);
+    }
+
+    d->external_listener_port = port;
+
+    return NULL;
+}
+
+static const char *set_external_listener_scheme (cmd_parms *cmd, void *d_, 
+                                                 const char *arg)
+{
+    core_dir_config *d = d_;
+    const char *err = ap_check_cmd_context(cmd, NOT_IN_LIMIT);
+
+    if (err != NULL) {
+        return err;
+    }
+
+    if (strcasecmp(arg, "http") == 0) {
+        d->external_listener_scheme = EXTERNAL_LISTENER_SCHEME_HTTP;
+    } 
+    else if (strcasecmp(arg, "https") == 0) {
+        d->external_listener_scheme = EXTERNAL_LISTENER_SCHEME_HTTPS;
+    }
+    else {
+        return "paremeter must be 'http' or 'https'";
+    }
+
+    return NULL;
+}
+
+
 static const char *include_config (cmd_parms *cmd, void *dummy,
                                    const char *name)
 {
@@ -3203,6 +3264,12 @@
 AP_INIT_TAKE1("UseCanonicalPhysicalPort", set_use_canonical_phys_port, NULL,
   RSRC_CONF|ACCESS_CONF,
   "Whether to use the physical Port when constructing URLs"),
+AP_INIT_TAKE1("ExternalListenerPort", set_external_listener_port, NULL, 
+  RSRC_CONF|ACCESS_CONF, 
+  "External listening port for front-end proxy or offload device"),
+AP_INIT_TAKE1("ExternalListenerScheme", set_external_listener_scheme, NULL, 
+  RSRC_CONF|ACCESS_CONF,
+  "Protocol Scheme used by external listener (http|https)"),
 /* TODO: RlimitFoo should all be part of mod_cgi, not in the core */
 /* TODO: ListenBacklog in MPM */
 AP_INIT_TAKE1("Include", include_config, NULL,
Index: CHANGES
===================================================================
--- CHANGES	(revision 387131)
+++ CHANGES	(working copy)
@@ -2,6 +2,11 @@
 Changes with Apache 2.3.0
   [Remove entries to the current 2.0 and 2.2 section below, when backported]
 
+  *) core, http_core: Add ExternalListenerPort and ExternalListenerScheme
+     directives to inform the server of listeners that may be in front of 
+     it, such as reverse proxies, load balancers and SSL offload appliances.
+     [Sander Temme]
+
   *) mod_proxy_ajp: Crosscheck the length of the body chunk with the length of
      the ajp message to prevent mod_proxy_ajp from reading beyond the buffer
      boundaries and thus revealing possibly sensitive memory contents to the
Index: modules/http/http_core.c
===================================================================
--- modules/http/http_core.c	(revision 387131)
+++ modules/http/http_core.c	(working copy)
@@ -99,11 +99,25 @@
 
 static const char *http_scheme(const request_rec *r)
 {
+    core_dir_config *d = 
+      (core_dir_config *)ap_get_module_config(r->per_dir_config, &core_module);
+    
+    if (d->external_listener_scheme == EXTERNAL_LISTENER_SCHEME_HTTPS) {
+        return "https";
+    }
+
     return "http";
 }
 
 static apr_port_t http_port(const request_rec *r)
 {
+    core_dir_config *d = 
+      (core_dir_config *)ap_get_module_config(r->per_dir_config, &core_module);
+    
+    if (d->external_listener_scheme == EXTERNAL_LISTENER_SCHEME_HTTPS) {
+        return DEFAULT_HTTPS_PORT;
+    }
+
     return DEFAULT_HTTP_PORT;
 }
 
Index: include/ap_mmn.h
===================================================================
--- include/ap_mmn.h	(revision 387131)
+++ include/ap_mmn.h	(working copy)
@@ -117,6 +117,8 @@
  *                         removal of Satisfy, Allow, Deny, Order
  * 20060110.1 (2.3.0-dev)  minex and minex_set members added to
  *                         cache_server_conf (minor)
+ * 20060110.2 (2.3.0-dev)  Added external_listener_port and 
+ *                         external_listener_scheme to core_dir_config
  */
 
 #define MODULE_MAGIC_COOKIE 0x41503234UL /* "AP24" */
@@ -124,7 +126,7 @@
 #ifndef MODULE_MAGIC_NUMBER_MAJOR
 #define MODULE_MAGIC_NUMBER_MAJOR 20060110
 #endif
-#define MODULE_MAGIC_NUMBER_MINOR 1                     /* 0...n */
+#define MODULE_MAGIC_NUMBER_MINOR 2                     /* 0...n */
 
 /**
  * Determine if the server's current MODULE_MAGIC_NUMBER is at least a
Index: include/http_core.h
===================================================================
--- include/http_core.h	(revision 387131)
+++ include/http_core.h	(working copy)
@@ -522,6 +522,12 @@
 #define USE_CANONICAL_PHYS_PORT_UNSET (2)
     unsigned use_canonical_phys_port : 2;
 
+    int external_listener_port;
+
+#define EXTERNAL_LISTENER_SCHEME_HTTP  (0)
+#define EXTERNAL_LISTENER_SCHEME_HTTPS (1)
+    unsigned int external_listener_scheme : 1;
+
 } core_dir_config;
 
 /* Per-server core configuration */
