On Thu, Jul 21, 2011 at 02:21:19PM +0100, Federico Schwindt wrote:
> On Thu, Jul 14, 2011 at 4:40 AM, David Gwynne <[email protected]> wrote:
> > 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.
> >[..]
> > ok?
>
> no as it is. please don't use atoi, use ap_strtol.
it seems a bit unfair of you to hold me to a higher standard than
the rest of the apache codebase, but ill live :)
> to check for `:' you can use strchr(). i believe you need an ap_pstrdup() for:
>
> + cmd->server->server_hostname = arg;
other stuff stores arg directly, so i assumed that was ok. again,
i'll live :)
> the strtonum() is wrong. it should be 65535 (the value is inclusive)
cool.
> but you could replace that bit just calling server_port().
but then id be calling atoi...
> you need to update the documentation as well.
true.
here's an update diff to the code:
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 25 Jul 2011 06:45:38 -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 25 Jul 2011 06:45:38 -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 25 Jul 2011 06:45:38 -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 ((unsigned)ap_strtol(v, NULL, 10));
+}
+
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, 65535, &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 = ap_pstrdup(cmd->pool, 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)" },