How do you match percent symbols in rewrite rules? - apache

I am redirecting URLs for a website, and have the following URL to match and redirect:
example.com/test-string-%2526-more-string/
However, I cannot match the %2526 portion of the string - it seems that Apache is treating the percentage symbol as a special character, and escaping it seems to make no difference. Here's the basic rule I'm trying:
RewriteRule ^test-string-\%2526-more-string/?$ /new-location.htm [R=301,L,NC]
With or without the escaping slash, this rule doesn't fire. I suspect the problem is with how apache processes encoded characters in URLs - %25 translates to a percentage symbol itself, so could Apache be translating "%25" to "%" before running the rule? Or is something else going on?

I experimented with lots of rewrite rules and in the end just went with this:
RewriteRule ^test-string-\%26-more-string/?$ /new-location.htm [R=301,L,NC]
So the %25 was converted to a % symbol.

Related

htaccess rewrite rule with strings that contain slashes

I have a mod rewrite rule like the following.
RewriteRule ^bands/([^/]*)$ /folder/index.php?palabra=$1 [L]
It works except when someone access a link that uses a word with a / symbol on the band name, for example the band ac/dc would not work and shows a 404 error.
Im guessing some kind of problem with the regex.
How can I avoid this problem?

Apache 301 redirect while preserving parts of URL

Is it possible to write a 301 Apache redirect and preserve a portion of the URL?
For example, I have pages that include -md in the title and want to redirect them to the same URL just without the trailing -md. I want to preserve the test-page-1 and test-page-2 portion, but I'm unsure how to write the Rewrite rule to achieve this.
/doctors/test-page-1-md ---> /pages/test-page-1
/doctors/test-page-2-md ---> /pages-test-page-2
How would I write the rewrite rule to look for the /test-page-1-md after the /doctors?
How would I preserve the test-page-1 and test-page-2 portions?
I've been working with this to start but I don't appear to be having much luck. I think my problem lies with the $1 variables.
RewriteRule ^doctors/$1-md /doctors/$1
This is RewriteRule syntax:
RewriteRule Pattern Substitution [flags]
Pattern is a perl compatible regular expression. The Substitution of a rewrite rule is the string that replaces the original URL-path that was matched by Pattern. So, in order to use $1 variable in Substitution, you first need to match it in Pattern :
RewriteEngine on
RewriteRule ^doctors/(.+)-md /pages/$1 [R=302]
(the above should work in .htaccess; if you use it in VirtualHost configuration, you have to start the Pattern with leading /, so: ^/doctors/(.+)-md). You can also change 302 to 301 once you are sure that everything is working as expected.

.htaccess -> Characters not escaping in rewrite string "(" ")"

I'm currently trying to add some redirects from a very old site that had PDFs and some of these PDFs have used brackets to contain the years.
For example:
/document%2070C11-name%20(2012).pdf
So the full URL I am trying to redirect is:
https://website.co.uk/document/1/document%2070C11-name%20(2012).pdf
I have previously setup many different redirects on this site but ones with the special characters seem to be causing an issue.
Here is the examples of what I have tried, and failed with so far:
RewriteEngine on
RewriteBase /
RewriteRule ^document/1/document%2070C11-name%20\(2008\).pdf$ document/newurl/ [R=301,L]
RewriteRule ^document/1/document%2070C11-name%20(.*)2008(.*).pdf$ document/newurl/ [R=301,L]
So I tried escaping the character and just trying a wildcard. Neither seemed to work on my Apache server. The code I used did seem to work when I tested it on:
http://htaccess.madewithlove.be/
But I am pretty stuck now and would love any help I can get.
Thanks,
Kane
To match %MN character in URL, you need to use \xMN in the RewriteRule pattern.
Hence this rule should work for you:
RewriteRule ^document/1/document\x2070C11-name\x20\(2008\)\.pdf$ /document/newurl/ [R=301,NC,NE,L]
This will redirect https://website.co.uk/document/1/document%2070C11-name%20(2008).pdf to https://website.co.uk/document/newurl/

Redirect apache urls with special characters

I need this redirection with mod_rewrite, but I don't have any success.
The url is http://www.domain.com/descargar catálogo
I thought this would work:
RewriteRule ^descargar%20catálogo$ /url/whatever.php [NC,NE]
Any solution for this. I have tried with NE and without, etc...
This gives me internal error:
RewriteRule ^descargar catálogo$ /url/whatever.php [NC,NE]
Other things I tried but didn't work:
RewriteRule ^descargar%20cat%C3%A1logo /url/whatever.php
RewriteRule ^descargar\ cat%C3%A1logo /url/whatever.php
URLs cannot contain non-ASCII characters. Escaping the character to represent the actual way the URL is transmitted should do it:
cat%C3%A1logo

Apache rewrite rule leading slash

Leading slash first argument: ignored?
What's the syntax difference between
RewriteRule help help.php?q=noslash [L] #1
RewriteRule /help help.php?q=withslash [L] #2
If I hit http://localhost/help, it goes to #1, if I hit http://localhost//help it still goes to #1.
Am I right in saying the leading slash in the first argument to RewriteRule is essentially ignored?
Leading slash second argument: error?
Also, why doesn't this rewrite rule work?
RewriteRule help /help.php [L] #1
Putting a leading slash in front of the second arg actually creates a 500 error for the server. Why?
I should note I'm using a .htaccess file to write these rules in
Strangely enough,
RewriteRule ^/help help.php?q=2 [L]
The above rule fails and never matches.
This rule:
RewriteRule ^help help.php?q=1 [L]
Matches http://localhost/help, http://localhost//help and http://localhost///help
It appears RewriteRule never sees leading slashes of the path, and as TheCoolah said they are collapsed (to 0.. when using a .htaccess file anyway) no matter how many there are.
For the second part of the question,
RewriteRule ^help /help.php
I'm getting the answer from Definitive Guide to Apache Mod_rewrite
... a rewrite target that does not begin with http:// or another protocol
designator is assumed to be a file system path. File paths that do not begin with a slash are interpreted as being relative to the directory in which the rewriting is taking place.
So /help.php looks in the root of the system for a file called help.php, which on my system it cannot find.
To make /help.php appear as a relative URL (relative to the root of the site) you can use the [PT] directive:
RewriteRule ^/help /help.php [PT]
That directs http://localhost/help to http://localhost/help.php.
Regarding double slashes: Most Web servers silently collapse multiple slashes into a single slash early in the request processing pipeline. This is true for at least Apache, Tomcat and Jetty. Most Unix-based file systems work the same way. If you really want to check for this, you need to do something like:
RewriteCond %{REQUEST_URI} ^(.*)//(.*)$
help matches "help" anywhere in the path.
/help matches nothing since the rewriterule directive omits the leading slash for matching purposes (i.e., you must use ^, not / or ^/, to reference the current directory).
(This can be very confusing if you've used %{REQUEST_URI} in rewritecond because %{REQUEST_URI} does begin with a trailing slash. When matching against %{REQUEST_URI}, ^ and ^/ are equivalent and a directory name will always be preceded by a slash character regardless of whether or not it is in the top-level directory.)
The server error is caused by an infinite loop. "help" becomes "/help.php" which is then matched by the same directive that did the rewriting. So, after the first match, "/help.php" becomes "/help.php" infinitely resulting in a URL that can't be resolved.
I believe such loops can be fixed with the end flag (i.e., [end]), but that flag requires Apache 2.3.9+ whereas Apache 2.2 seems to be more common in deployment. It'd probably be better to just fix the regular expression anyway; ^help$ would seem to be the better choice here.
The way RewriteRule works is that if the given regular expression matches any part of the path part of the URL (the part after the host and port but before the query string), then the entire path part is completely replaced with the given substitution. This explains the behaviour you're seeing in the first part of your question.
I'm not sure what could be causing the 500 errors on the second part; maybe the collapsing of doubled slashes doesn't happen after the rewrite engine has run and then generates a server error.
The reason for the 500 Error is an infinitive Loop:
help gets rewritten to /help
/help gets stripped to help
help gets rewritten to /help
etc. until the MaxRewrites limit is hit -> 500
Whereas if the rule rewrites help to help, Apache is smart enough to abort rewriting at that point.