Last active
September 17, 2020 20:19
-
-
Save cweekly/5ee064ddd551e1997d4c to your computer and use it in GitHub Desktop.
Example of using mod_rewrite (and mod_setenvif) to manipulate query string parameters, via temp env vars
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Mod_rewrite is great at manipulating HTTP requests. | |
# Using it to set and read temp env vars is a helpful technique. | |
# | |
# This example walks through fixing a query string: | |
# Extract good query params, discard unwanted ones, reorder good ones, append one new one. | |
# | |
# Before: /before?badparam=here&baz=w00t&foo=1&bar=good&mood=bad | |
# After: /after?foo=1&bar=good&baz=w00t&mood=happy | |
# | |
# Storing parts of the request (or anything you want to insert into it) in ENV VARs is convenient. | |
# Note the special RewriteRule target of "-" which means "no redirect; simply apply side effects" | |
# This lets you manipulate the request at will over multiple steps. | |
# | |
# In a RewriteRule, set custom temp ENV VARs via [E=NAME:value] | |
# Note it's also possible to set multiple env vars | |
# like [E=VAR_ONE:hi,E=VAR_TWO:bye] | |
# | |
# You can read these values using %{ENV:VAR_NAME}e <- little "e" is not a typo | |
# | |
# Tangent: | |
# Note you can also read these env vars the same way, if you set them via SetEnvIf[NoCase] | |
# (It won't work to use SetEnv, which runs too early for mod_rewrite to pair with it.) | |
# | |
# Regex details: | |
# (?:) syntax means "match but don't store group in %1 backreference" | |
# so (?:^|&) is simply the ^ beginning or an & delimiter | |
# (the only 2 possibilities for the start of a qs param) | |
# ([^&]+) means 1 or more chars that are not an & delimiter | |
RewriteCond %{QUERY_STRING} (?:^|&)foo=([^&]+) | |
RewriteRule ^/before - [E=FOO_VAL:%1] | |
RewriteCond %{QUERY_STRING} (?:^|&)bar=([^&]+) | |
RewriteRule ^/before - [E=BAR_VAL:%1] | |
RewriteCond %{QUERY_STRING} (?:^|&)baz=([^&]+) | |
RewriteRule ^/before - [E=BAZ_VAL:%1] | |
RewriteRule ^/before /after?foo=%{FOO_VAL}e&bar=%{BAR_VAL}e&baz=%{BAZ_VAL}e&mood=happy [R=301,L] | |
# That's it! No PHP needed! :) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Dear Cweekly,
I like your solution because it looks like could help me to order query params into a predefined order. It is possible to use it on every URL if any of predefined query params appear in the URL? I can't define "before" and "after" URLs by patterns. Query params may appear (optional) in every URL, but if they appear I would like to reorder them. Do you think it is possible?