Sometimes I’ll work on something just to see what it looks like when it’s done. I guess this Apache rewrite might be something like that — I wanted to change the WordPress search query from /?s=value
to /s/value
, just to make the URL look a little prettier. :) There are probably a few ways to do this, and if you’d like to share some alternatives, feel free to post a comment.
There are two parts to this problem; The first, executing a search query from an /s/value
URL, is easily addressed by a rewrite and proxy command. The second problem — how to rewrite a regular search query, but not a proxied search query — is a little tricker. I decided to add an htproxy hostname to my domain with an IP of 127.0.0.1. Then in a rewrite condition, I check for the htproxy hostname, and skip the rewrite if it’s a proxied request. The htproxy hostname must be included in the website’s Apache config as a ServerAlias
.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
# rewrite-search.conf # Beautify WordPress search query string with rewrites. # by Jean-Sebastien Morisset (https://surniaulula.com/) # sets %{server_name} to config value instead of %{http_host} value UseCanonicalName On # if not proxied, rewrite the wordpress search query as a path string RewriteCond %{HTTP_HOST} !^htproxy\. RewriteCond %{QUERY_STRING} ^s=([^&]+)&?(.*)$ RewriteRule ^/$ http://%{SERVER_NAME}/s/%1?%2 [noescape,redirect=permanent,last] # if there's a search string in the path, then proxy the search query RewriteRule ^/s/(.*)$ http://htproxy.%{SERVER_NAME}/?s=$1&%{QUERY_STRING} [proxy,last] |
I’ve set UseCanonicalName
to on so %{SERVER_NAME}
will be a known fixed value. The alternative might have been to hardcode the complete host and domain name in the rewrite rules, but then I couldn’t have shared this code (as-is) between multiple websites.
I would have liked to make the RewriteCond %{HTTP_HOST} !^htproxy\.
rewrite condition less generic, by using htproxy.%{SERVER_NAME}
for example, but Apache refused to cooperate (might be a bug). I also tried using the %{HTTP_PROXY_CONNECTION}
variable, but couldn’t find enough information on it to make it work. A test that wasn’t based on the hostname would have allowed me to skip the use of a dedicated hostname to accept proxy requests.