Multiple rewrite rule with different parameters in the same position - apache

I would like to know if the following would be possible
RewriteRule ^([^/]*)/([^/]*)$ /search.php?type=$1&query=$2 [L]
RewriteRule ^([^/]*)/([^/]*)/([^/]*)$ /search.php?type=$1&query=$2&condition=$3 [L]
RewriteRule ^([^/]*)/([^/]*)/([^/]*)/([^/]*)$ /search.php?type=$1&query=$2&page=$3[L]
As you can see the first and third row are similiar with the only difference being the name of the third parameter, the second rule would be used for pages such as
/isbn/1203910293/new
whilst the third rule would be used for pages such as where page aliases page number
/title/harry-potter/2
I know this seems quite silly considering I can just call the condition parameter, but it would clear things up in the future if used the parameter page

The third rule pattern ^([^/]*)/([^/]*)/([^/]*)/([^/]*)$ will not match
/title/harry-potter/2
because the rule requires four parts, e.g.
/title/harry-potter/2/xyz
or at least a trailing slash
/title/harry-potter/2/
Instead it will be matched by the second rule pattern, because it has three parts too, just like
/isbn/1203910293/new
If you want to match page numbers, you need to match against a rule similar to the second rule, but be more specific, like e.g.
RewriteRule ^([^/]*)/([^/]*)/(\d+)$ /search.php?type=$1&query=$2&page=$3 [L]

Related

Need .htaccess recipe to display rss feed dynamically

I currently use the following recipe to route .rss files to a script that produces a rss feed dynamically:
RewriteRule ^(.*).rss$ /get-feed.pl?item=$1
It works perfectly for URLs like this:
www.example.com/articles.rss
What I would to like to do is change the URL to this:
www.example.com/rss/articles/
Everything I have tried doesn't work.
I just tried to put some slashes in the recipe but I'm not an expert in these recipes so they didn't work. Somethig like this didn't work: RewriteRule ^/rss/(.*)/$ /get-feed.pl?item=$1
("recipe" = regular expression / "regex" for short OR RewriteRule "pattern" from the Apache docs - At least I think that is what you are referring to? We are not baking a cake here! ;) )
That is very close, except that the URL-path that the RewriteRule pattern matches against does not start with a slash when used in a .htaccess (directory) context. So, it would need to be like this: ^rss/(.*)/$. If you had looked to see what your first rule was returning you would have seen that there was no slash prefix in the backreference that was captured (ie. the value of the item URL parameter).
However, there are other (minor) issues here...
The 2nd path segment cannot be empty, so it would be preferable to match something, rather than anything. eg. (.+) instead of (.*). However, this should be made more restrictive, so to match just a single path segement, instead of any URL-path (which is likely to fail anyway I suspect). eg. Presumably /rss/foo/bar/baz/ should not match?
Again, if you only want to match a string of the form articles then make the regex more restrictive so that it only matches letters (or perhaps letters + numbers + hyphens)?
You are missing the L (last) flag on this rule, which is a problem if you have other directives that follow.
So, if you are wanting to rewrite URLs of the form www.example.com/rss/articles/ (note the trailing slash) then try the following instead:
RewriteRule ^rss/([\w-]+)/$ /get-feed.pl?item=$1 [L]
Make sure the browser cache is cleared before testing.
And this would need to go near the top of the .htaccess file, before any existing rewrites.
Aside: A quick look at your original directive:
RewriteRule ^(.*).rss$ /get-feed.pl?item=$1
This is not strictly correct, as it potentially matches too much. The unescaped dot before rss matches any character. And the .* subpattern matches 0 or more characters of anything - it must be something. So, this should really be something like:
RewriteRule ^([\w-]+)\.rss$ /get-feed.pl?item=$1 [L]

confusion between two rewrite urls rules

these two rules are confused :
RewriteRule ^health-institute-([a-zA-Z\-]+)-([a-zA-Z\-]+)$ search.php?city=$1&speciality=$2 [L]
RewriteRule ^health-institute-app-([a-zA-Z\-]+)$ search.php?city=$1 [L]
when I want to reach health-institute-app-mycity (2nd rule) the server consider app as a value and try to reach search.php?city=app&speciality=mycity (1st rule)
how can I say that these are two separate rules?
Yes, because the regex ^health-institute-([a-zA-Z\-]+)-([a-zA-Z\-]+)$ in the first rule also matches health-institute-app-mycity.
You need to reverse these two directives so the more specific rule is first.
For example:
RewriteRule ^health-institute-app-([a-zA-Z-]+)$ search.php?city=$1 [L]
RewriteRule ^health-institute-([a-zA-Z-]+)-([a-zA-Z-]+)$ search.php?city=$1&speciality=$2 [L]
(No need to backslash-escape the hyphen when at the start or end of the character class.)
HOWEVER, the regex in the (now) second rule is potentially ambiguous since the hyphen (-) is used to delimit the two values (city and speciality), but the hyphen is also included in both the character classes, so it can presumably be part of the values themselves. However, both city and speciality cannot both contain hyphens, despite the regex seemingly allowing this.
For example, how should a request for health-institute-foo-bar-baz-qux be resolved? Since the quantifier + is greedy, this will currently result in search.php?city=foo-bar-baz&speciality=qux. If there is ever a hyphen in the speciality (as suggested this could be the case by the regex) it will never be matched.

redirecting two pairs of numbers with htaccess

I have URLs which I need to strip and redirect the numbers for categories and products.
Category
example.com/9-bird-tables
Product
example.com/bird-tables/59-slate-roof-bird-table/
They need to be:
example.com/bird-tables/
example.com/bird-tables/slate-roof-bird-table/
So, the number appears in a different place depending on what you're viewing. I cant work out the rules and I'm running out of time. Can anyone help?. I've tried the following, but it only works for the first set of numbers, and not the second
RewriteRule ^[0-9]+-(.+?)/?$ $1 [L,R=301]
You can change your rule to this with 2 capturing groups:
RewriteRule ^(.*/)?\d+-(.+)$ $1$2 [L,R=301,NE]

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.

question regarding specific mod_rewrite syntax

I know there are other questions that are similar to this.. but I'm really struggling with mod_rewrite syntax so I could use some help.
Basically, what I am trying to do is have the following redirect occur:
domain.com/1/ redirect to domain.com/?id=$1 (also should work for www.domain.com)
What I have so far (that isn't working):
RewriteEngine On
ReRewriteRule ^/([0-9])$ /?id=$1
A few issues.
First is terminology: if you want when a user types domain.com/1/ that the request is served by index.php?id=1, then you are rewriting /1/ to index.php?id=1, not the other way around as you said.
Second, simple typo: RewriteRule, not ReRewriteRule.
Second, [0-9] is the right way to match a number, but it'll only match a single digit. If you want to handle /13 then you should match one or more instances [0-9] by writing [0-9]+.
Third, the target of your rule should be the file you want to serve. / is not a file or an absolute URL, write out the index.php if that's what you mean.
Third, you say you want to handle /1/, but your rule says that the matched request must end in a number, not a slash. If you want to accept the slash whether it's there or not, put that in the rule.
RewriteRule ^/?([0-9]+)/?$ index.php?id=$1 [L]
Does that work?
You've three issues:
RewriteRule is misspelt as point out by Michael, you need to worry about the trailing slash, and you need to stop processing rules when you've found the match:
RewriteRule ^/(\d+)/?$ /?id=$1 [L]
You have misspelled RewriteRule. Otherwise, I think your syntax looks correct.
RewriteEngine On
ReRewriteRule ^/([A-Za-z0-9]+)$ /?id=$1
--^^^---------
Actually, you should probably remove the /:
RewriteEngine On
RewriteRule ^([A-Za-z0-9$_.+!*'(),-]+)$ /?id=$1
------^^^---------
EDIT Added the +. Look at all the answers here. You need a composite of them., including the + and the [L] in addition to what I have here.
EDIT2 Also edited to include alpha characters in the id.
EDIT3 Added special characters to regex. These should be valid in a URL, but it's unusual to find them there.