Skip to content

Instantly share code, notes, and snippets.

@jiphex
Created March 24, 2014 18:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jiphex/9746499 to your computer and use it in GitHub Desktop.
Save jiphex/9746499 to your computer and use it in GitHub Desktop.
Apache Weirdness

Apache Weirdness

Today I've spent a fairly large amount of time trying to track down a weird Apache edge-case, related to how self-referential URLs are generated. This is mostly-relevant if you're running Varnish (or any HTTP proxy really), and Apache 2.4 (although this probably affects other versions of Apache as well).

The configuration I'd normally use for Varnish/Apache is this:

[client] -> [varnish on port 80] -> [apache on high port, e.g 8080]

This normally (in my experience) works fine, and can be fairly transparent to the user.

The problem here, was that this particular client was using an [uncommonly used?] feature of Apache, documented here.

Let's say you have the following directory structure in your DocumentRoot:

htdocs
├── foo
│   └── index.html
└── index.html

The default Apache behaviour when someone requests http://some.uri.tld/foo - is to return an Apache redirect (301 with Location header) to http://some.uri.tld/foo/ (adding the trailing slash automatically).

If you're running Apache on Port 80, it seems like this just works, and you probably never noticed.

In my case, when hitting http://some.uri.tld/foo, I was getting a redirect to http://some.uri.tld:8080/foo - exposing Apache on the high port, and pushing visitors to the unvarnished face of the Apache server.

Initial googling lead me to this configuration directive, which appeared to answer all of my problems. However both it and UseCanonicalHostname default to off, which was what I wanted anyway, so this didn't appear to have any effect:

Apache httpd will not ever use the actual physical port number, instead relying on all configured information to construct a valid port number.

To try and workaround debug this, I changed Varnish to listen on port 80 on the main IP (and IPv6), and Apache to listen on an IPv6 address on port 80. I then configured Varnish to speak to the IPv6 backend [on port 80], thinking that, as Apache would be seeing requests come in on port 80, it'd return self-referential URLs which also pointed at port 80...

At this point, the top of the site's vhost file was as follows:

NameVirtualHost blah:8080
NameVirtualHost blahv6:8080
NameVirtualHost [random:new:ipv6:address]:80

<VirtualHost blah:8080 blahv6:8080 [random:new:ipv6:address]:80>
  .. stuff

(And Varnish was configured to listen on blah:80 and blahv6:80, with [random:new:ipv6:address]:80 as it's backend)

No dice, nothing changed. This made no sense, neither Apache nor Varnish are seeing anything on port 8080, the only place that port is referenced is in the configuration file, nothing's actually hitting the server[s] on port 8080 at all...

It's at this point that I started to wonder what "all configured information" actually meant, as it seemed like the non-matching VirtualHost host specifiers seem to affect how the server generates these self-referential URLs for every request.

It turns out that all configured information means that, yes, in this case, the port number of the first host specifier in the VirtualHost line, i.e 8080 (from blah:8080 above) is what Apache uses to generate it's canonical "self-referential" URLs.

Changing the order of the VirtualHost host specifiers in the config file above to the following fixed the redirect issue:

NameVirtualHost blah:8080
NameVirtualHost blahv6:8080
NameVirtualHost [random:new:ipv6:address]:80

<VirtualHost [random:new:ipv6:address]:80 blah:8080 blahv6:8080>
  .. stuff

The slash/directory redirects just work now, the Host header gets passed through as the target of the Location response, and the port isn't included as it's implied by the default HTTP protocol port (80).

I'm not really sure why UseCanonicalPhysicalPort didn't work here, I suspect that it's somehow interfered with by mod_dir.c that does the Location redirect to add the trailing slash, but a quick browse through the source code for it doesn't appear to show how.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment