December 19, 2011

Apache’s mod_rewrite and mod_alias can be very useful, but they can also be a huge pain to debug when a problem arises. Luckily, there are a few things that can help, and since you’re probably not the first person attempting to rewrite or redirect something in a specific way, you’ll likely be able to find the answer by just searching around intelligently once you understand the basics.
The first resource that I use would be the Apache mod_rewrite and mod_alias documentation. It might seem tedious, but Apache HTTP Server actually has some of the best documentation in the industry. If you spend 10 minutes reading the actual documentation and give understanding it a shot, you’ll probably find the majority of your questions answered. Make sure you check out the section of the mod_rewrite docs that covers the RewriteLog directive, since having a log turns guesswork into something debuggable.

The next tool that I like to use is curl, since it shows you the http headers and lets you see exactly what the client and server are saying to each other. `curl` is a pretty standard utility that comes installed on many flavors of *nix and it’s available for download for many platforms, including Windows, cygwin, and Mac OSX. Let’s check out an example of a simple 302 “Found” redirect:
[code]
$ curl –verbose –head –location example.com
* About to connect() to example.com port 80 (#0)
* Trying 192.0.43.10… connected
* Connected to example.com (192.0.43.10) port 80 (#0)
> HEAD / HTTP/1.1
> User-Agent: curl/7.21.7 (i386-redhat-linux-gnu) libcurl/7.21.7 NSS/3.12.10.0 zlib/1.2.5 libidn/1.22 libssh2/1.2.7
> Host: example.com
> Accept: */*
>
* HTTP 1.0, assume close after body
< HTTP/1.0 302 Found
HTTP/1.0 302 Found
< Location: http://www.iana.org/domains/example/
Location: http://www.iana.org/domains/example/
< Server: BigIP
Server: BigIP
* HTTP/1.0 connection set to keep alive!
< Connection: Keep-Alive
Connection: Keep-Alive
< Content-Length: 0
Content-Length: 0
<
* Connection #0 to host example.com left intact
* Issue another request to this URL: ‘http://www.iana.org/domains/example/’
* About to connect() to www.iana.org port 80 (#1)
* Trying 192.0.32.8… connected
* Connected to www.iana.org (192.0.32.8) port 80 (#1)
> HEAD /domains/example/ HTTP/1.0
> User-Agent: curl/7.21.7 (i386-redhat-linux-gnu) libcurl/7.21.7 NSS/3.12.10.0 zlib/1.2.5 libidn/1.22 libssh2/1.2.7
> Host: www.iana.org
> Accept: */*
>
< HTTP/1.1 200 OK
HTTP/1.1 200 OK
< Date: Fri, 16 Dec 2011 21:22:21 GMT
Date: Fri, 16 Dec 2011 21:22:21 GMT
< Server: Apache/2.2.3 (CentOS)
Server: Apache/2.2.3 (CentOS)
< Last-Modified: Wed, 09 Feb 2011 17:13:15 GMT
Last-Modified: Wed, 09 Feb 2011 17:13:15 GMT
< Vary: Accept-Encoding
Vary: Accept-Encoding
< Connection: close
Connection: close
< Content-Type: text/html; charset=UTF-8
Content-Type: text/html; charset=UTF-8
<
* Closing connection #1
* Closing connection #0
[/code]
If we look hard enough, we can get a lot of info about the request from this. You can see the actual HTTP code of the 302 redirect in the line “< HTTP/1.0 302 Found", with the left angle bracket indicating that this is a response from the server (right angle brackets are commands sent by the client -- curl, in this case). The above curl command, `curl --verbose --head --location example.com` tells us that curl should be verbose, it should just send a "HEAD" HTTP request instead of GET, and that it should follow any "Location: [...]" responses that it receives from the server (telling it to go to a new location). In this case, as we've seen above, curl will re-run the request with the updated location as the input URL. This behavior mimics that of browsers, but it isn't the default curl behavior. There are some cases when we might need to more closely simulate a browser. If your application handles GET requests and ignores HEAD, you might need to omit '--head' and instead just use '-o /dev/null' to write the downloaded file out to nowhere. You could also just leave this out, which will dump the page source to your STDOUT (effectively the same as '-o -'). You might also need to specify a user agent string to trigger specific site behavior such as a mobile site. Let's try with example.com again. We're going to simulate a request from an iPhone running iOS 5.0 using Safari, with the '--trace-ascii' for full geek mode which will show us even more details that could be useful for optimized mobile content. We'll also use the '--limit-rate' option for curl to slow down the transfer to a crawl (2G cellular GPRS speeds that an average connection might see -- 25kbit/sec): [code] $ curl --trace-ascii - --location -o /dev/null --user-agent 'Mozilla/5.0 (iPhone; CPU iPhone OS 5_0 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Version/5.1 Mobile/9A334 Safari/7534.48.3' --limit-rate 25k example.com == Info: About to connect() to example.com port 80 (#0) % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0== Info: Trying 192.0.43.10... == Info: connected == Info: Connected to example.com (192.0.43.10) port 80 (#0) => Send header, 198 bytes (0xc6) 0000: GET / HTTP/1.1 0010: User-Agent: Mozilla/5.0 (iPhone; CPU iPhone OS 5_0 like Mac OS X 0050: ) AppleWebKit/534.46 (KHTML, like Gecko) Version/5.1 Mobile/9A33 0090: 4 Safari/7534.48.3 00a4: Host: example.com 00b7: Accept: */* 00c4: == Info: HTTP 1.0, assume close after body <= Recv header, 20 bytes (0x14) 0000: HTTP/1.0 302 Found <= Recv header, 48 bytes (0x30) 0000: Location: http://www.iana.org/domains/example/ <= Recv header, 15 bytes (0xf) 0000: Server: BigIP == Info: HTTP/1.0 connection set to keep alive! <= Recv header, 24 bytes (0x18) 0000: Connection: Keep-Alive <= Recv header, 19 bytes (0x13) 0000: Content-Length: 0 <= Recv header, 2 bytes (0x2) 0000: 0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0 == Info: Connection #0 to host example.com left intact == Info: Issue another request to this URL: 'http://www.iana.org/domains/example/' == Info: About to connect() to www.iana.org port 80 (#1) == Info: Trying 192.0.32.8... == Info: connected == Info: Connected to www.iana.org (192.0.32.8) port 80 (#1) => Send header, 215 bytes (0xd7) 0000: GET /domains/example/ HTTP/1.0 0020: User-Agent: Mozilla/5.0 (iPhone; CPU iPhone OS 5_0 like Mac OS X 0060: ) AppleWebKit/534.46 (KHTML, like Gecko) Version/5.1 Mobile/9A33 00a0: 4 Safari/7534.48.3 00b4: Host: www.iana.org 00c8: Accept: */* 00d5: <= Recv header, 17 bytes (0x11) 0000: HTTP/1.1 200 OK <= Recv header, 31 bytes (0x1f) 0000: Server: Apache/2.2.3 (CentOS) <= Recv header, 46 bytes (0x2e) 0000: Last-Modified: Wed, 09 Feb 2011 17:13:15 GMT <= Recv header, 23 bytes (0x17) 0000: Vary: Accept-Encoding <= Recv header, 40 bytes (0x28) 0000: Content-Type: text/html; charset=UTF-8 <= Recv header, 22 bytes (0x16) 0000: Accept-Ranges: bytes <= Recv header, 24 bytes (0x18) 0000: Connection: close <= Recv header, 37 bytes (0x25) 0000: Date: Fri, 16 Dec 2011 21:47:36 GMT <= Recv header, 14 bytes (0xe) 0000: Age: 101 <= Recv header, 22 bytes (0x16) 0000: Content-Length: 2966 <= Recv header, 2 bytes (0x2) 0000: <= Recv data, 1170 bytes (0x492) 0000: ..................

Nexcess
Nexcess

Nexcess, the premium hosting provider for WordPress, WooCommerce, and Magento, is optimized for your hosting needs. Nexcess provides a managed hosting infrastructure, curated tools, and a team of experts that make it easy to build, manage, and grow your business online. Serving SMBs and the designers, developers, and agencies who create for them, Nexcess has provided fully managed, high-performance cloud solutions for more than 22 years.


We use cookies to understand how you interact with our site, to personalize and streamline your experience, and to tailor advertising. By continuing to use our site, you accept our use of cookies and accept our Privacy Policy.