differences between rewrite rules - apache

can you explain to me what are differences between these rewrite rules?
rewriterule ^news/category/(.*)/([0-9]+)/?$ index.php?p=news&category=$1&page=$2 [L,QSA]
rewriterule ^news/category/(.+)/([0-9]+)/*$ index.php?p=news&category=$1&page=$2 [L,QSA]
differences between (.*) and (.+) and differences between /?$ and /*$ ?
and
rewriterule ^news/category/(.*)/?$ index.php?p=news&category=$1 [L,QSA]
rewriterule ^news/category/(.+?)/*$ index.php?p=news&category=$1 [L,QSA]
differences between (.*) and (.+?) ?
thanks for your help!

You have the technical answer from Gert.
My "non-technical" is:
line #1: if the URL has a string or nothing, followed by a slash and a number or nothing, ending with / or not, then apply the rewriterule
line #2: if the URL has a string, followed by a slash and a number or nothing, ending with whatever, then apply the rewriterule
Here are the URL problems you can have:
with #1, this will be considered "valid": news/category//548/.
with #2, this will be considered "valid": news/category/whatever/548/this-is-a-problematic564string.
You can apply the same principle to your second comparison/question.

(.*) Matches between zero and unlimited times, as many times as possible giving back as needed (greedy)
(.+) Matches between one and unlimited times, as many times as possible giving back as needed (greedy)
(.+?) Matches between one and unlimited times, as few times as possible expanding as needed (lazy)
Go to regex101.com for debugging of your regex
the /?$ and /*$ I'm not sure. It always matches.

Related

Replace ? with / in rewrite rules

I need to achieve this map given below :
https://www.domain1.com/open.html?cuSDyh&utm_medium=rep-email
to
https://www.domain2.com/c/cuSDyh?utm_medium=rep-email
I write a rewrite rule to achieve this which seems wrong as "?" is not replaced in the end result.
RewriteRule ^/open.html?(.*)$ https://www.domain2.com/c/$1 [NC,R=301,L]
Can anyone help me to find the right rewrite rule for this one?
RewriteRule ^/open.html?(.*)$ https://www.domain2.com/c/$1 [NC,R=301,L]
There are a couple of problems here that prevents the rule from working:
The RewriteRule pattern (1st argument) matches against the URL-path only, which notably excludes the query string. To match the query string you need an additional condition (RewriteCond directive) and match against the QUERY_STRING server variable.
The URL-path matched by the RewriteRule pattern does not start with a slash.
Note that the RewriteRule pattern is a regex. The unescaped ? in the above regex is a special meta character (a quantifier) that makes the preceding token optional. So, in your example, the l is optional. (Although you match everytihng that follows anyway, so the ? is entirely redundant.)
FROM: /open.html?cuSDyh&utm_medium=rep-email
TO: /c/cuSDyh?utm_medium=rep-email
I'm assuming the first URL-parameter (eg. cuSDyh in your example) consists of letters only (lower or uppercase) and is not a name=value pair (as per your example). There can be 0 or more URL parameters that follow the first URL parameter.
Try the following instead:
RewriteCond %{QUERY_STRING} ^([a-z]+)(?:&|$)(.*) [NC]
RewriteRule ^open\.html$ /c/%1?%2 [NE,R=302,L]
The %1 and %2 backreferences match the captured subgroups in the preceding CondPattern. ie. %1 matches the first URL parameter (eg. cuSDyh in your example) and %2 matches all subsequent URL params, excluding the delimiter.
The NE flag (not NC) is required on the RewriteRule directive to prevent the query string part of the URL being doubly URL-encoded in the redirect response. (The QUERY_STRING variable is already URL-encoded.)
If there are no additional URL parameters after the first then the above rule will essentially append an empty query string (denoted by the trailing ?). However, the trailing ? is removed automatically by Apache in the redirect response.
To avoid potential caching issues, always test first with a 302 (temporary) redirect and only change to a 301 (permanent) redirect - if that is the intention - once testing is complete.

.htaccess rule that only accepts a specific value in a list

I want to accept this url structure, where $level can only be one of these values: a-, a+, b-, b+, ab-, ab+
domain.com/notes/a-
domain.com/notes/a+
domain.com/notes/b-
domain.com/notes/b+
domain.com/notes/ab-
domain.com/notes/ab+
I tried this approach, but I was unsuccessful.
RewriteRule ^notes/([a|o|b|ab]-+)$ /notes.php?level=$1 [L]
You're nearly there, but + is a special character so it has to be escaped, and alternation (pipe character) goes in parentheses. I removed 'o' that wasn't in your list. (?:) just says don't capture this.
RewriteRule ^notes/((?:a|b|ab)(?:-|\+))$ notes.php?level=$1 [L]

RewriteRule comes back to the same directory

I am trying to make two rewrite rules which should point to different files. However, they somehow are pointing to the same PHP file.
Can somebody help take a look please?
RewriteRule ^destinations/([a-z]+)-(.*)$ /a.php?x=$1&y=$2 [NC]
This should be linked to www.example.com/destination/us-united-state
RewriteRule ^destinations/([a-z]+)-(.+)-(.+)$ /b.php?a=$1&b=$2&c=$3 [NC]
This should be linked to www.example.com/destination/us-united-state-california
A regular expression finds the longest possible match. So, ([a-z]+)-(.*)$ will match one or more a through z characters followed by a dash followed by ANYTHING.
([a-z]+)-(.+)-(.+) requires two dashes, but the above expression will match these too.
be sure that you have the correct number of dashes matched:
RewriteRule ^destinations/([a-z]+)-([^-]+)$ /a.php?x=$1&y=$2 [NC]
and rename the page to
www.example.com/destination/us-unitedstate
then
RewriteRule ^destinations/([a-z]+)-([^-]+)-([^-]+)$ /b.php?a=$1&b=$2&c=$3 [NC]
to match pages like
www.example.com/destination/us-unitedstate-california
Use an other delimiter between us and united-state and between united-state and california. There is no way you can detect if the three seperate words in www.example.com/destination/us-united-state are actually two or three 'things'. I advice using slashes as delimiter instead: www.example.com/destination/us/united-state and www.example.com/destination/us/united-state/california.
Your rules would be:
RewriteRule ^destinations/([a-z]+)/([^/]+)/?$ /a.php?x=$1&y=$2 [NC]
RewriteRule ^destinations/([a-z]+)/([^/]+)/([^/]+)/?$ /b.php?a=$1&b=$2&c=$3 [NC]
This uses [^/]+, which matches anything but the / character. This prevents a capturing group from matching something like us/united-states where it should only match us. Please note that this code is untested as I can't test on this computer.

Rewriting 2nd parameter in query string

Like so many I am struggling with what ought to be a simple rewrite
The initial form is something like:
http://cassie-family.co.uk/individual.php?pid=I807&ged=Cassy%20Family%20History.ged
The last parameter only needs rewriting, as in:
http://cassie-family.co.uk/individual.php?pid=I807&ged=Cassie%20-%20Cassy%20Family%20History
I have tried to trap the first parameter using:
RewriteCond %{QUERY_STRING} ^pid=([^&]+) [NC]
The nearest (incorrect) RewriteRule is:
RewriteRule ^(.*)$ individual.php&pid=%1&ged=Cassie%20-%20Cassy%20Family%20History [L, NC, R=301]
The moment I try to replace the '&' after individual.php with the correct '?' the URL is written as:
http://cassie-family.co.uk/individual.php
So.. the parameter is being trapped correctly but the rewrite rule is clearly mangled. The error lies in here:
^(.*)$ individual.php&
What construct should I be using to replace only the 2nd (passed-in) parameter value (which is always the same fixed string) with a different 2nd value (which is always the same but slightly different fixed string)? Adding a B flag seems to make no difference.
All suggestions welcome,
Thanks,
Ric

Mod_rewrite. Redirect url with Special Characters (question marks)

I have a website with joomla and I need to redirect (301) some links
They are in this form (index.php?Itemid= identify them - all links that doesn't have this part shouldn't be redirected)
/index.php?Itemid=544&catid=331:savona&id=82356:smembramento-dei-cantieri-baglietto-di-varazze-lopposizione-delle-maestranze&option=com_content&view=article
This should work
RewriteRule ^index.php?Itemid(.*)$ http://www.ligurianotizie.it/archive/index.php?Itemid$1 [L,R=301]
But the first ? (question mark) seems to cause problems.
In fact, if we suppose that the links are without the question mark
/index.phpItemid=544&catid=331:savona&id=82356:smembramento-dei-cantieri-baglietto-di-varazze-lopposizione-delle-maestranze&option=com_content&view=article
I would use
RewriteRule ^index.phpItemid(.*)$ http://www.ligurianotizie.it/archive/index.php?Itemid$1 [L,R=301]
and everything is perfect. But unfortunately real links has that question mark, and I have to find a solution.
What I have to do with that question mark?
Is the ? character escaped? try to add the NE (noescape) flag like this:
RewriteRule ^index.php?Itemid(.*)$ http://www.ligurianotizie.it/archive/index.php?Itemid$1 [L,R=301,NE]
The part behind the question mark is the query string. You can use RewriteCondto determine if it is not empty, and based on that make the decision to redirect.
Note: Query String
The Pattern will not be matched against the query string. Instead, you must use a RewriteCond with the %{QUERY_STRING} variable. You can, however, create URLs in the substitution string, containing a query string part. Simply use a question mark inside the substitution string, to indicate that the following text should be re-injected into the query string. When you want to erase an existing query string, end the substitution string with just a question mark. To combine a new query string with an old one, use the [QSA] flag.
Source: http://httpd.apache.org/docs/2.0/mod/mod_rewrite.html
This should help you:
RewriteEngine On
RewriteBase /
RewriteCond %{QUERY_STRING} Itemid
RewriteRule ^index.php(.*)$ http://www.ligurianotizie.it/archive/index.php$1 [L,R=301]
Every link containing "Itemid" will be redirected, the others not.