flexibility in .htaccess for mod_rewrite rules - apache

i would like to redirect my old php files to new seo friendly ones:
user.php?user=$var1&task=$var2 -> url/$var1/$var2
There are 2 problems. $var2 is not set every time, so i do not know how to deal that and the querystring is always added at the end.
I use the following redirect rule for testing (without $var2)
RewriteCond %{THE_REQUEST} ^(.+)user\.php(.+)$
RewriteCond %{QUERY_STRING} user=([^/]+)$
RewriteRule ^(.+)\.php$ %1 [R]
I get this:
url/$var1/?user=$var1
Second problem is the rewrite rule so that url/$var1 -> user.php?user=$var1
Without it i get a server error.
In the moment i tried this static one for testing, but this is not the only rule so that the Condition is wrong here
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^([^/]+)/?$ user.php?user=$1 [L]
How i get the correct results and more flexibility with the variables?
mod_rewrite is not my world in the moment, so i hope you can bring light in the dark.
Thx ruven

1) The way to prevent the query string at the end there is to add a ? at the end of the URL you rewrite to.
RewriteCond %{THE_REQUEST} ^GET\ /user\.php
RewriteCond %{QUERY_STRING} user=([^&=]+)$
RewriteRule ^user\.php %1? [R]
And in case both var1 and var2 are set it would be
RewriteCond %{THE_REQUEST} ^GET\ /user\.php
RewriteCond %{QUERY_STRING} user=([^&=]+)$
RewriteCond %{QUERY_STRING} task=([^&=]+)$
RewriteRule ^user\.php %1/%2? [R]
Combine these (the second one first) and it should redirect as needed
2) Since this is a kind of 'catch all' URL you should put this as the last option in your .htaccess and redirect everything that is not a file or a directory to user.php and then let user.php figure out if the user exists, and if not respond with HTTP 404.
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]+)$ user.php?user=$1 [L]
(I've removed the / at the end as it's not a good idea to have two URLs for the exact same content).

Related

how to remove query string from url using htaccess

Once my friend help me to solve this issue, I have written code like that. Where example.com/blog-detail?slug=slugvalue it goes to blog-detail.php and this url example.com/project?slug=test goes to project.php.
RewriteEngine ON
##Checking condition and getting matches in variables to be used while redirect in next rule.
RewriteCond %{THE_REQUEST} \s([^?]*)\?slug=(\S+)\s [NC]
RewriteRule ^ %1/%2? [R=301,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(?:[^/]*)/(.*)/?$ blog-detail.php?slug=$1 [QSA,L]
I think it's work for only blog-detail page now i face the issue with this url
https://www.example.com/project?slug=test, it redirect me to 404 page, could you help me here.
With your shown samples, attempts; please try following htaccess rules file. Please make sure to clear your browser cache before testing your URLs.
I have added 2 solutions here, so either use 1st rules set OR use 2nd rules set ONLY ONE at a time please.
1st solution: With 2 different rules set for each php file please try following rules.
RewriteEngine ON
###Rules for blog-detail.php redirect and rewrite.
##Checking condition and getting matches in variables to be used while redirect in next rule.
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteCond %{THE_REQUEST} \s(blog-detail)\?slug=(\S+)\s [NC]
RewriteRule ^ /%1/%2? [R=301,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(?:[^/]*)/(.*)/?$ blog-detail.php?slug=$1 [QSA,L]
###Rules for project.php redirect and rewrite.
##Checking condition and getting matches in variables to be used while redirect in next rule.
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteCond %{THE_REQUEST} \s(project)\?slug=(\S+)\s [NC]
RewriteRule ^ /%1/%2? [R=301,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(?:[^/]*)/(.*)/?$ project.php?slug=$1 [QSA,L]
2nd solution: A Generic solution with capturing groups to deal with both kind of php files together.
RewriteEngine ON
###Rules for blog-detail.php OR project.php redirect and rewrite.
##Checking condition and getting matches in variables to be used while redirect in next rule.
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteCond %{THE_REQUEST} \s([^?]*)\?slug=(\S+)\s [NC]
RewriteRule ^ /%1/%2? [R=301,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]*)/(.*)/?$ /$1.php?slug=$2 [QSA,L]
NOTE1: Please keep both your php files(project.php and blog-detail.php) should be kept along with your htaccess rules file.
NOTE2: For JS/CS rewrite/redirect:
You may need to use base tag to fix your js and other relative resources. If you are linking js files using a relative path then the file will obviously get a 404 because its looking for URL path. for example if the URL path is /file/ instead of file.html then your relative resources are loading from /file/ which is not a directory but rewritten html file. To fix this make your links absolute or use base tag. In the header of your webpage add this <base href="/"> so that your relative links can load from the correct location.

Redirection is not working with mod_rewrite in htaccess

I need to redirect few URIs having query string like:
/pages/foo.bar?pageId=123456 to http://some.site/spam/egg/
/pages/foo.bar?pageId=45678 to http://another.site/spaming/egging/
I have this in my htaccess:
RewriteEngine On
RewriteCond %{REQUEST_URI} ^/pages/foo.bar$
RewriteCond %{QUERY_STRING} ^pageId=123456$
RewriteRule ^.*$ http://some.site/spam/egg/ [R=301,L]
RewriteCond %{REQUEST_URI} ^/pages/foo.bar$
RewriteCond %{QUERY_STRING} ^pageId=45678$
RewriteRule ^.*$ http://another.site/spaming/egging/ [R=301,L]
But its not working, showing 404. What am i doing wrong?
You need to move these 2 rules i.e. before all other rules just below RewriteEngine On line as other rules might be overriding this.
(Based on your comments) Your culprit rule is this rule:
RewriteRule . index.php [L]
Which is actually rewriting every request to index.php and changing value of REQUEST_URI variable to /index.php thus causing this condition to fail:
RewriteCond %{REQUEST_URI} ^/pages/foo.bar$
From your example, you get redirected to
http://some.site/spam/egg/?pageId=123456
http://another.site/spaming/egging/?pageId=45678
You can use your browser developer tools to see the redirection (in the Network tab).
Maybe the query strings in the redirected URL lead to a 404? You can add a ? at the end of your redirection to clear the query string:
RewriteCond %{REQUEST_URI} ^/pages/foo.bar$
RewriteCond %{QUERY_STRING} ^pageId=45678$
RewriteRule ^.*$ http://another.site/spaming/egging/? [R=301,L]

Check URL and stop processing using htaccess

I want to check URL using htaccess. Developer might want run special file - specialfile.php. I use htaccess:
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} /specialfile\.php$
RewriteRule .* [L] #don't change adress
RewriteRule ^$ public/index.html [NC,L]
RewriteRule (.*) public/$1 [NC,L]
My idea was: if rewriteCond %{REQUEST_URI} !/specialfile.php$ true than htaccess should use RewriteRule .* [L] - that should mean that specialfile.php will be run and this all. But it doesn't work because it runs next rule: RewriteRule (.*) public/$1 [NC,L].
I think you are using the RewriteCond not correctly. The conditions only affect the next RewriteRule that follows.
Check out the example on the Apache Homepage. Since your 2nd RewriteRule is evalutated, I think your conditions are not correct. To get a litte bit more information about the rewriting, you should increase the log level. This is also documented here.
Your 2nd rule ^$ matches only an empty request btw. That's why it probably does not work as you expect it to.

How can I math a regular expression to write an htaccess rule

I want this URL
http://rebateninja.com/index.php?page=home
To be previewed like this via htaccess
http://rebateninja.com/home
I know it is not that hard and I have done that before, but for some reason it is not working now at all. My .htaccess contains the following:
RewriteEngine On
RewriteRule (index.php\?page=)(.*) /$2 [NC,R=301,L]
What I am doing wrong? Perhaps it is related to my Apache version? I have lost my entire morning without success!!! Thanks for your answers.
You can't match against the query string in a RewriteRule, you need to use a RewriteCond with either %{THE_REQUEST} or %{QUERY_STRING} and use a % to backreference groupings:
RewriteCond %{THE_REQUEST} ^(GET|POST|HEAD)\ /index\.php\?page=([^&\ ]+)
RewriteRule /%2? [L,R=301]
That externally redirects the browser so that the URL in the address bar changes. In order to internally rewrite it back you need to do:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /index.phjp?page=$1 [L]
Try this.
RewriteRule ^index.php\?page=(.*)$ /$1 [NC,R=301,L]

Apache mod_rewrite query string before page and remove extention

I've scavenged the web for answers to my mod_rewrite woes and I feel I'm at the end of my wits. I will have a URL like such: http://www.website.com/dashboard.php?username=stackoverflow. This url isn't the prettiest of such. So my goal is to do a few things here...
Eliminate the extension of the php file (I've been able to do this so far with the code I'll show below, but I don't know that it will stay according to the other things I need to do)
Eliminate the "www" prefix
Move the username query string (only if it's "username", I don't want to match "id" or such) directly after ".com/"
Move the php filename (without the extension) after query string.
The final URL should look like such: http://website.com/stackoverflow/dashboard or perhaps http://website.com/stackoverflow/profile.
The code I have right now which eliminates the file extension is such:
Options +FollowSymLinks
RewriteEngine On
RewriteBase /
# remove .php ONLY if requested directly
RewriteCond %{THE_REQUEST} (\.php\sHTTP/1)
RewriteRule ^(.+)\.php$ /$1 [R=301,L,QSA]
# remove trailing slash ONLY if it is not an existing folder
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/$ /$1 [L,R=301]
# rewrite to FILENAME.php if such file does exist and is not a folder
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.php -f
RewriteRule ^(.*)$ /$1.php [L,QSA]
Sadly this only fixes one of my issues and after looking at it, I'm getting the feeling there would be a better way to do this...
(1, 3, 4) As I understand you want to use pretty URLs, but backed by PHP pages. So it should be like this:
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(\w+)/profile$ /dashboard.php?username=$1 [L]
It will make http://website.com/stackoverflow/profile working as http://www.website.com/dashboard.php?username=stackoverflow
(2)
# Redirect www.site.com to site.com with 301
RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
RewriteRule ^(.*)$ http://%1/$1 [R=301,L]