in my environment i have nginx in front of apache to offload ssl
and to let me easily point different parts of the uri namespace at
all crazy backends we have. this works fine except if the apache
wants to canonicalise something on the "ssl" backends. because the
ssl is done in nginx, apache doesnt know that it should use https
as the scheme rather than just http and redirects the user to the
wrong port.

this diff models the newer apache behaviour of letting you specify
the scheme/method as part of the ServerName directive.

i can set virtualhosts up like this now:

# nginx has an ssl listener on 443 that proxies to this backend
# using plain http.
<VirtualHost _default_:280>
        ServerName https://internal.eait.uq.edu.au

        # other shizz

</VirtualHost>

with this diff apache canonicalises with https at the start of the
url instead of the default of http.

please note i dont like userland (too many strings), and im generally
unfamiliar with apache internals, so i would appreciate both eyes
and tests.

ok?

Index: src/include/http_core.h
===================================================================
RCS file: /cvs/src/usr.sbin/httpd/src/include/http_core.h,v
retrieving revision 1.12
diff -u -p -r1.12 http_core.h
--- src/include/http_core.h     24 Aug 2007 11:31:29 -0000      1.12
+++ src/include/http_core.h     14 Jul 2011 03:33:02 -0000
@@ -138,6 +138,8 @@ API_EXPORT(const char *) ap_get_remote_l
 API_EXPORT(char *) ap_construct_url(pool *p, const char *uri, request_rec *r);
 API_EXPORT(const char *) ap_get_server_name(request_rec *r);
 API_EXPORT(unsigned) ap_get_server_port(const request_rec *r);
+API_EXPORT(const char *) ap_get_server_method(const request_rec *r);
+API_EXPORT(unsigned) ap_get_default_port(const request_rec *r);
 API_EXPORT(unsigned long) ap_get_limit_req_body(const request_rec *r);
 API_EXPORT(void) ap_custom_response(request_rec *r, int status, char *string);
 API_EXPORT(int) ap_exists_config_define(char *name);
Index: src/include/httpd.h
===================================================================
RCS file: /cvs/src/usr.sbin/httpd/src/include/httpd.h,v
retrieving revision 1.30
diff -u -p -r1.30 httpd.h
--- src/include/httpd.h 25 Feb 2010 07:49:53 -0000      1.30
+++ src/include/httpd.h 14 Jul 2011 03:33:02 -0000
@@ -141,12 +141,8 @@ extern "C" {
 #define DEFAULT_HTTP_PORT      80
 #define DEFAULT_HTTPS_PORT     443
 #define ap_is_default_port(port,r)     ((port) == ap_default_port(r))
-#define ap_http_method(r)   (((r)->ctx != NULL && ap_ctx_get((r)->ctx, \
-    "ap::http::method") != NULL) ? ((char *)ap_ctx_get((r)->ctx,       \
-    "ap::http::method")) : "http")
-#define ap_default_port(r)  (((r)->ctx != NULL && ap_ctx_get((r)->ctx, \
-    "ap::default::port") != NULL) ? atoi((char *)ap_ctx_get((r)->ctx,  \
-    "ap::default::port")) : DEFAULT_HTTP_PORT)
+#define ap_http_method(r)   ap_get_server_method(r)
+#define ap_default_port(r)  ap_get_default_port(r)
 
 /* --------- Default user name and group name running standalone ---------- */
 /* --- These may be specified as numbers by placing a # before a number --- */
Index: src/main/http_core.c
===================================================================
RCS file: /cvs/src/usr.sbin/httpd/src/main/http_core.c,v
retrieving revision 1.27
diff -u -p -r1.27 http_core.c
--- src/main/http_core.c        10 May 2010 02:00:50 -0000      1.27
+++ src/main/http_core.c        14 Jul 2011 03:33:02 -0000
@@ -804,6 +804,42 @@ ap_get_server_port(const request_rec *r)
            : port;
 }
 
+API_EXPORT(const char *)
+ap_get_server_method(const request_rec *r)
+{
+       const char *method;
+
+       if (r->ctx != NULL) {
+               method = ap_ctx_get(r->ctx, "ap::http::method");
+               if (method != NULL)
+                       return (method);
+       }
+
+       if (r->server->ctx != NULL) {
+               method = ap_ctx_get(r->server->ctx, "ap::http::method");
+               if (method != NULL)
+                       return (method);
+       }
+
+       return ("http");
+}
+
+API_EXPORT(unsigned)
+ap_get_default_port(const request_rec *r)
+{
+       const char *v = NULL;
+
+       if (r->ctx != NULL)
+               v = ap_ctx_get(r->ctx, "ap::default::port");
+       if (v == NULL && r->server->ctx != NULL)
+               v = ap_ctx_get(r->server->ctx, "ap::default::port");
+
+       if (v == NULL)
+               return (DEFAULT_HTTP_PORT);
+
+       return (atoi(v));
+}
+
 API_EXPORT(char *)
 ap_construct_url(pool *p, const char *uri, request_rec *r)
 {
@@ -1751,6 +1787,43 @@ static const char *set_server_string_slo
     return NULL;
 }
 
+static const char *
+set_server_name(cmd_parms *cmd, void *dummy, char *arg)
+{
+       const char *err = ap_check_cmd_context(cmd,
+           NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
+       const char *part;
+       int port;
+
+       if (err != NULL)
+               return (err);
+
+       if (strncmp("https://";, arg, 8) == 0) {
+               ap_ctx_set(cmd->server->ctx, "ap::http::method", "https");
+               ap_ctx_set(cmd->server->ctx, "ap::default::port", "443");
+               arg += 8;
+       } else if (strncmp("http://";, arg, 7) == 0) {
+               /* defaults are fine */
+               arg += 7;
+       } else if (strstr(arg, "://") != NULL)
+               return ("unsupported scheme");
+
+       part = strstr(arg, ":");
+       if (part != NULL) {
+               port = (int)strtonum(part + 1, 1, 65536, &err);
+               if (err != NULL) {
+                       return ap_pstrcat(cmd->temp_pool,
+                           "The port number \"", part + 1, "\" is ", err, 
NULL);
+               }
+               cmd->server->port = port;
+               cmd->server->server_hostname = ap_pstrndup(cmd->pool, arg,
+                   part - arg);
+       } else 
+               cmd->server->server_hostname = arg;
+
+       return (NULL);
+}
+
 static const char *server_type(cmd_parms *cmd, void *dummy, char *arg)
 {
     const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
@@ -3152,8 +3225,7 @@ static const command_rec core_cmds[] = {
 { "ServerAdmin", set_server_string_slot,
   (void *)XtOffsetOf (server_rec, server_admin), RSRC_CONF, TAKE1,
   "The email address of the server administrator" },
-{ "ServerName", set_server_string_slot,
-  (void *)XtOffsetOf (server_rec, server_hostname), RSRC_CONF, TAKE1,
+{ "ServerName", set_server_name, NULL, RSRC_CONF, TAKE1,
   "The hostname of the server" },
 { "ServerSignature", set_signature_flag, NULL, OR_ALL, TAKE1,
   "En-/disable server signature (on|off|email)" },

Reply via email to