{{tag>webserver apache}} ====== Apache rewrite hints ====== ===== Location of rewrite rules ===== When writing rewrite rules, take care where they are defined. According to documentation leading forward slash does not match in per directory contexts (.htaccess files and blocks). The following will work for example in vhost file, but not in .htaccess file. RewriteRule "^/cc" "/index.html" In .htaccess the rule should look like this: RewriteRule "^cc" "/index.html" so no leading slash. ===== Multiple rules with catch all rule at end ===== If there are multiple rules for a path and one catch all rule at the end, you need to use [END] flag and not [L] flag to apply the more specific rule. The last flag only stops evaluating rules from the current iteration. [[https://stackoverflow.com/a/6800150/6881647|See this SO answer]] e.g. (.htaccess) RewriteRule "^cc" "/altindex.html" [END] RewriteRule "(.*)" "index.html" If a URL starts like example.com/cc it will show the content from altindex.html (but won't actually redirect the url to show it in the browser url bar; use flag [R] if you want this). Every other url will present index.html content (example.com/bb, example.com/dd, example.com/oiiejwjfj, example.com/blahblah etc.). ===== Multiple rewrites ===== A rule like this will rewrite example.com/toz to example.com/zz which will in turn rewrite it to example.com/altindex.html. RewriteRule "^zz" "/altindex.html" [END] RewriteRule "^toz" "zz" [L] RewriteRule "(.*)" "index.html" Browser URL will still show example.com/toz. We need a redirect flag, [R], to change browser URL to example.com/altindex.html but this won't work in conjuction with [END] flag. A workaround is to add a query parameter "redirect" then check for that: RewriteCond %{QUERY_STRING} !redirected RewriteRule /site/(\d+)/([^/]+)\.html /site/$2/$1?redirected [R=301,L] What now happens is that the redirects are to URLs with "?redirected" added to them. And so the rule isn't applied the second time. ===== Understanding flags ===== [L] - last flag; The flag means "do not process any rules below in this iteration". So if there are 4 rules and the third rule has last flag, the 4th rule won't be processed now, but the process will start again from the 1st rule i.e. Apache will go to next iteration and will start matching all rules again from top. It won't stop the rewrite process. Use [END] flag for that. ===== Special characters ===== To rewrite a special character that appears in URL, for example the symbol for degree "°", hex BO in [[https://en.wikipedia.org/wiki/ISO/IEC_8859-1#Code_page_layout|ISO 8859 set]], check in the apache access log how apache sees the URL. ... 93.142.158.181 - - [06/Nov/2020:14:31:09 +0100] "GET /blog/astra-19-2'''%c2%b0'''e-ard-retains-dfb-pokal-tv-rights-until-2019/ HTTP/1.1" 404 16143 "https://sporteventz.com/it/component/tags/tag/football-fta-channels.html" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:82.0) Gecko/20100101 Firefox/82.0" ... We see there are 2 special characters '''%c2''' and '''%b0''' we need remove/replace in rewrite rule. Here is an example to remove them from url: RewriteRule "^en/blog/(\d{1,3}-)([a-z]+-)(\d{1,3}-\d{1,3})[\xc2]+[\xb0]+(.*).html" "/blog/$2$3$4/" [R=301,L] This results in url of '''astra-19-2e-ard-retains-dfb-pokal-tv-rights-until-2019/''' instead of '''astra-19-2°e-ard-retains-dfb-pokal-tv-rights-until-2019/''' ====== Tested on ====== * Apache 2.4 ====== See also ====== * [[wiki:rewrite_rule_examples|Apache rewrite rule examples]] ====== References ====== * https://httpd.apache.org/docs/2.4/rewrite/remapping.html * https://httpd.apache.org/docs/2.4/mod/mod_rewrite.html#rewriterule * https://stackoverflow.com/questions/11709634/convert-original-url-to-friendly-url * https://serverfault.com/a/519530/353235 * https://stackoverflow.com/a/6800150/6881647