RewriteRule to capture whole search string produces empty result - apache

I have the following rule in .htaccess:
RewriteRule ^order(.*)$ /index.php?p=order&product=$1 [L,NC]
It's a simplification because later on I want to add order\?product=(.*)
I access the website with:
http://website.com/order?product=L0231-03868 but in the $_GET I'm only getting this:
Array ( [p] => skonfiguruj-zamowienie [product] => )
The product is empty. What am I missing?
-- edit
the moment I add the question mark
RewriteRule ^order\?(.*)$ /index.php?p=order&product=$1 [L,NC]
I get 404

Your URI doesn't really have anything after order so there is nothing to capture in (.*).
Use QSA flag to append original query string after rewrite.
No need to repeat order on both sides.
Suggested rule:
RewriteRule ^(order)/?$ index.php?p=$1 [L,NC,QSA]
Because of QSA flag, your original query string product=L0231-03868 will be appended to p=order and you will get both parameters in php file.
Note about patter ^order\?(.*)$ generating 404. Remember that a ? will never be part of URI to be matched using RewriteRule hence this pattern containing a ? is guaranteed to always fail.

With your shown samples please try following htacces rules file. Make sure to keep your htaccess rules file along with index.php file, order folder(3 of them should reside inside root directory). Also clear cache before testing your URLs.
RewriteEngine ON
RewriteCond %{THE_REQUEST} \s/(order)\?(product)=(\S+)\s [NC]
RewriteRule ^ index.php?p=%1&%2=%3 [QSA,L]
To make it more Generic, as above rules are very samples specific only:
RewriteEngine ON
RewriteCond %{THE_REQUEST} \s/([^?]*)\?([^=]*)=(\S+)\s [NC]
RewriteRule ^ index.php?p=%1&%2=%3 [QSA,L]
Documentation link:
%{THE_REQUEST} is being used here, which contains complete request line.

Related

.htaccess rewrite urls with parameters

I am trying to rewrite my urls through a .htaccess file to make them more clean looking. I have
http://localhost:801/Test/test.php?school=19&name=Greenhaven-Elementary
and it needs to end up looking like
http://localhost:801/Test/test.php/19/Greenhaven-Elementary
In my .htaccess file I have the following
RewriteEngine On
RewriteRule ^([a-zA-Z0-9-/+]+)([0-9]+)$ test.php?school=/$1&name=$2/ [L]
I have tried other ways but being new at using .htaccess files I haven't been able to figure it out.
This should do what you're after:
RewriteEngine On
RewriteCond %{QUERY_STRING} school=(.+)&name=(.+) [NC]
RewriteRule ^(.*)$ http://localhost:801/Test/test.php/%1/%2? [R=301,NC,L]
So what does the above do?
First, it will take the query school= and name= as a condition, if this condition is met then it will grab any version of the variables using (.+).
It will then rewrite the URL using 301 redirection to show http://localhost:801/Test/test.php/anything/anything2. The use of %1 and %2 is to grab the variables from school= / name= and then we use ? to stop the original query string from appearing on the end of the newly rewritten URL.
Make sure you clear your cache before testing this.
EDIT:
I wrote this for the singular query:
RewriteEngine On
RewriteCond %{QUERY_STRING} item=(.+) [NC]
RewriteRule ^(.*)$ http://localhost:801/Test/%1? [R=301,NC,L]
This includes removing test.php and on my server works without issue and returns http://localhost:801/Test/anything

Apache .htaccess rewrite parameter to directory

I've got an application that has been migrated to a newer platform. The tasks are similar and I'd like to redirect a GET parameter to a directory. For example
http://gallery/index.php?gal=ABC => http://photos/gal/ABC
and
http://gallery/?gal=DEF => http://photos/gal/DEF
and the anything that doesn't get caught redirect it to http://photos
I've tried
RewriteEngine on
RewriteCond %{QUERY_STRING} ^(\w+)=(\w+)$
RewriteRule ^(/index.php)$ /%1/%2?
However all I get is a 404 and no redirection. Similarly, I've tried
RedirectMatch ^/index\.php\?=gal(.*) http://photos/gal/$1
but I'm having trouble escaping the ? in the original URL.
What would be the proper way of going about this?
Create a .htaccess file and insert the following code:
RewriteCond %{QUERY_STRING} ^(.+)=(.+)$
RewriteRule ^index.php$ http://photos %1/%2? [L,NC,R=301]
Your order is reversed. Rewrite it in front of you
RewriteRule /(.+)\/(.+) index.php?$1=$2
The question is old but might be still relevant for others, so I suggest a slightly different general approach:
RewriteEngine On
RewriteCond %{QUERY_STRING} key=([0-9a-zA-Z]+) [NC]
RewriteRule (.*) /%1? [R=302,L]
Notes:
QUERY_STRING in the condition checks for a param name "key" and catches it's value
The rewrite rule adds the param value as directory using %1. Note the ? removes the original query part from end result

removing directory in apache mod_rewrite

I have a PHP site which replaces an ASP site, so the path structure is different.
In the URLs, I need to match http://apache.site/Cartv3/Details.asp & redirect to another location. What is the correct syntax to match that URL fragment?
I've already tried
RewriteCond %{REQUEST_URI} CartV3/results1.asp?Category=60
RewriteRule ^(.*)$ home-study/A-Levels/1/page-1 [R=301,L]
and
RewriteRule ^CartV3/Details\.asp?ProductID=1004 home-study/A-Levels/1/page-1 [R=301,L]
You meed to read more about mod_rewrite. Remember RewriteRule doesn't match query string. You attempt needs to be rewritten as:
Options +FollowSymLinks -MultiViews
# Turn mod_rewrite on
RewriteEngine On
RewriteBase /
RewriteCond %{QUERY_STRING} ^Category=60$ [NC]
RewriteRule ^CartV3/results1\.asp$ /home-study/A-Levels/1/page-1? [R=302,L,NC]
Once you verify it is working fine, replace R=302 to R=301. Avoid using R=301 (Permanent Redirect) while testing your mod_rewrite rules.
PS: ? after page-1 is a special mod_rewrite syntax to strip original query string. If you want to keep original query string in rewritten URL then take out ? in the end.
The problem here is that you are trying to match the query string, which has to be done by a separate RewriteCond. If you want the match specifically "Category=60", then you can add it as a Condition:
RewriteCond %{QUERY_STRING} Category=60
RewriteCond %{REQUEST_URI} /CartV3/results1.asp
RewriteRule .* home-study/A-Levels/1/page-1?
This will match http://example.com/CartV3/results1.asp?Category=60 and redirect. The ? at the end of the rule stops "?Category=60" being to the resulting URI.
If you don't care about the value in the query string, then you can remove the first condition.

mod_rewrite weird problem

I have a strange problem with mod_rewrite, the rules that are relevant here are:
RewriteRule ^(.*)\/igre\-(.*)\.php\?Page=([0-9]+)$ game.php?GameUrl=$2&Page=$3 [L]
RewriteRule ^(.*)\/igre\-(.*)\.php$ game.php?GameUrl=$2&Page=1 [L]
And a corresponding URL might look something like this:
example.com/miselne-igre/igre-shirk.php?Page=2
example.com/miselne-igre/igre-shirk.php
The problem is that the first rule has no effect. If I use the first URL from the example I always get 1 into the Page variable, which shows that the second rule is used.
So what's wrong with the first one? And why is the second rule even matching a URL with ".php?Page=XYZ" at the end, if I said that the URL ends with ".php"?
ps: other rules in the .htaccess file are working fine...
The query string is not part of the URI path that is being processed by the RewriteRule directive. You have to use the RewriteCond directive to process the query string.
RewriteCond %{QUERY_STRING} ^Page=[0-9]+$
RewriteRule ^[^/]+/igre-([^/]+)\.php$ game.php?GameUrl=$1&%0 [L]
RewriteRule ^[^/]+/igre-([^/]+)\.php$ game.php?GameUrl=$1&Page=1 [L]
But you can still simplify this by using the QSA flag (query string append):
RewriteRule ^[^/]+/igre-([^/]+)\.php$ game.php?GameUrl=$1 [L,QSA]
mod_rewrite is not using the query in it's rewriting process. Therefor you first RewriteRule is ignored. You could combine it with a RewriteCond (haven't tested it though) like so:
RewriteCond %{QUERY_STRING} Page=([0-9]+)
RewriteRule ^(.*)\/igre\-(.*)\.php\?Page=([0-9]+)$ game.php?GameUrl=$2 [L, qsappend]
# qsappend appends the original query, in this case (Page=xx)
Ah, like Gumbo said; you can also use %1 to back reference to the page numer.
Is it just me or are your arguments back-to-front?
Do you mean:
RewriteRule ^(.*)\/(.*)\-igre\.php\?Page=([0-9]+)$ game.php?GameUrl=$2&Page=$3 [L]
RewriteRule ^(.*)\/(.*)\-igre\.php$ game.php?GameUrl=$2&Page=1 [L]
You wanted to match miselne-igre not igre-miselne.
Obviously this doesn't address the main issue, but thought I'd throw that in.
Dom

Why is Apache mod_rewrite not behaving as expected

I want to redirect URLs from an old site that used raw URL requests to my new site which I have implemented in CodeIgniter. I simply want to redirect them to my index page. I also would like to get rid of "index.php" in my URLs so that my URLs can be as simple as example.com/this/that. So, this is the .htaccess file I have created:
RewriteEngine on
Options FollowSymLinks
RewriteBase /
RewriteCond $1 ^assets
RewriteRule ^(.*)$ example/production/$1
RewriteCond %{QUERY_STRING} .+
RewriteRule ^(.*)$ index.php? [R=301]
RewriteCond $1 !^(index\.php|example|robots\.txt)
RewriteRule ^(.*)$ index.php/$1
It should also be noted that my index.php is actually a symlink to example/production/index.php.
Now, the first rule works as expected - all my styles and images show up just fine, it's the second two rules I'm having trouble with. The second rule is basically to destroy the query string and redirect to my index page (externally). So, I found this in the Apache manual:
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.
However, when I try to access one of the old pages, instead of redirecting to my index page, I get a 404 page not found error. I have figured out a workaround by making it an internal redirect, but I would really like it to be external.
The next problem, and the one that has been baffling me the most is with the third rule. I would expect this to do something like the following. If I type in:
http://example.com/this/thing
I would expect it to re-route to
http://example.com/index.php/this/thing
Unfortunately, this does not work. Instead, no matter what I type in, it always routes to my index page as if nothing else was in the URL (it just goes to http://example.com/).
Furthermore, and even more confusing to me, if I replace that rule with the following:
RewriteCond $1 !^(index\.php|example|robots\.txt)
RewriteRule ^(.*)$ index.php/this/thing
If I type in a URL such as http://example.com/other/thing, then it will go to http://example.com/index.php/this/thing as expected, BUT if I type in http://example.com/this/thing it goes to http://example.com/ (my index page). I can't make heads or tails out of it. Any help would be greatly appreciated.
This should solve your index.php problem and it will simply detect if a robots.txt is available:
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
hmmm - this doesn't seem to work either. The problem is my URLs aren't really asking for a filename or directory anyway. For example: example.com/index.php/this/thing should call the 'thing' method of the 'this' controller. – Steven Oxley
The condition is: If request is NOT a file and NOT a directory, so that was right, what you should have done is combine the appending of the request string:
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php/$1 [L]