I have come across a situation that seems odd to me. It seems that backreference variables when building apache rewrite rules get lost after the first use.
My requirement is changing an old URL pattern to conform to a new path pattern, e.g:
www.example.com/documents/newsletter/newsletter-issue-50.htm
to become
www.example.com/sites/default/newsletter/50/English/newsletter-issue-50.htm
As you can see, the new URL pattern needs to have the issue number specified in 2 places.
My rewrite rule is as follows:
RewriteRule ^documents/newsletter/newsletter-issue-(.*).htm$ http://www.example.com/sites/default/newsletter/$1/English/newsletter-issue-$1.htm [R=301,L]
When I use this rule, I still get a 404 because the resultant URL misses to replace the second "$1" with the issue number , in this case "50". What I get is
http://www.example.com/sites/default/newsletter/50/English/newsletter-issue-.htm
I have used this test site and it confirms that the second backreference variable is not being evaluated at all. Am sure am missing something here, since it should be a simple rule to put in place.
Any help on this would be greatly appreciated.
Thanks.
Strangely enough, I works in the rewrite tester if you surround with 2 sets of parenthesis:
RewriteRule ^documents/newsletter/newsletter-issue-((.*))[.]htm$ http://www.example.com/sites/default/newsletter/$1/English/newsletter-issue-$1.htm [R=301,L]
I have also escaped the file extension prefix
Related
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]
I tried going through some of the mod_rewrite questions on the site, but didn't find an answer to my problem (the fact that most questions were titled "mod_rewrite doesn't work" didn't help make that task any easier, hopefully my title is a little more helpful).
this is the content of my /somepath/.htaccess:
RewriteEngine On
RewriteRule ^go/(.*) /cgi-bin/goto.cgi?$1
# ^^^ WORKS: /somepath/go/200001..
RewriteRule ^go?(.*) /cgi-bin/goto.cgi$1
# ^^^ WORKS: /somepath/go?200001..
ErrorDocument 404 /cgi-bin/goto.cgi?error404
In testing, I made goto.cgi simply return $ENV{QUERY_STRING}, $ENV{QUERY_STRING_UNESCAPED} and $ENV{PATH_INFO}. Currently, the above rules mean that I am getting the QUERY_STRING passed on correctly when the urls:
/somepath/go/200001
/somepath/go?200001
/somepath/go?/200001
are accessed, but not when
/somepath/go/?200001
is accessed, in which case $ENV{QUERY_STRING}, $ENV{QUERY_STRING_UNESCAPED} and $ENV{PATH_INFO} are empty.
So the question is, what rule can I use so that
/somepath/go/?200001
gives my script the ?200001 or even /?200001 part back?
The first rule is destroying the query string of the example that fails, since $1 will be empty and an empty query string in the substitution removes any existing query string.
And the second rule is gibberish.
RewriteRule ^go/(.+)$ /cgi-bin/goto.cgi?$1
RewriteRule ^go/?$ /cgi-bin/goto.cgi
I am having problems with mod_rewrite which is throwing me the same error 404 is as follows:
RewriteRule ^music.mp3?id=(.*)$ music.php?id= [L]
i need url /music.mp3?id=1 and real url /music.php?id=1
any idea??
I think something is misunderstood in the path RewriteRule
You can't match against the query string (everything after the ? in the URL) in a RewriteRule. But you're not really matching against it anyways, it looks like you just need to appended to your target URI, so:
RewriteRule ^music\.mp3$ music.php [L]
Should be good enough. Any query string parameters (like ?id=1) will automatically get appended at the end.
In your expression (the engine rule), what you want to say is:
"When the url starts with music.mp3?id=, take whatever is after the = and change the URL to music.php?id= and put the part after id="
In regular expressions the . character has special meaning. If you want to say "the dot character", and not give it special meaning, you need to escape it, but putting a \ behind it, like this:
^music\.mp3?id=(.*)$
#Jon Lin already gave you the other part, which is about query strings.
I need a basic redirect in a .htacess file, from a directory URL to a file:
RewriteRule ^(.*)/mydirectory/(.*)$ myfile.php?q=$2
It is not working. The problem is I can't get it to work unless I do:
RewriteRule (.*)mydirectory(.*)$ myfile.php?q=$2
in which case the captured string ($2) is "mydirectory" (?!), and of course the rule would apply to any URL containing "mydirectory" as a substring, even if it's not between slashes, which is no good.
The test URL is:
http://localhost/base/mydirectory/some-other-string
What I expect is:
http://localhost/base/myfile.php?q=some-other-string"
What I get with the first rule is nothing (rule does not apply/not working), and "myfile.php?q=base/mydirectory" with the second rule, respectively.
The same happens if I use RewriteCond: as soon as I add the damned forward slashes, the rule does not apply anymore. I even escaped the forward slashes, although there's no need for that, to no avail.
I'm not a mod_rewrite expert, but I'm no stranger to it. IMO, the first rule should work, but it doesn't. I'm probably doing something horribly wrong, but I'm too close to see it.
Please take a look, it's driving me nuts.
Many thanks.
Slashes have special meanings in regular expressions you need to escape them:
RewriteRule ^(.*)\/mydirectory\/(.*)$ myfile.php?q=$2
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.