Redirection by querying database value like stackoverflow.com URLs - apache

So I use the following htaccess code to redirect the URLs to clean looking URLs but, now what I need to happen is to have the original URLs to redirect to the new clean URLS.
Example
Original URL:
example.com/search/store_info.php?store=113&dentist=Dr.%20John%20Doe
Clean URL:
example.com/search/113/dr-john-doe
What I need is the "ORIGINAL URL" to redirect to the "CLEAN URL". Reason why I need this to happen is that both URLs are showing up in Google searches.
I only want the clean URL to show up and anytime the original URL is used it should automatically redirect to the clean URL. It currently doesn't do that.
Here is my htaccess file.
ErrorDocument 404 default
<IfModule mod_rewrite.c>
Options -MultiViews
RewriteEngine On
RewriteBase /search/
RewriteCond %{QUERY_STRING} .
RewriteCond %{THE_REQUEST} /store_info\.php\?store=([a-z0-9]+)&dentist=([^\s&]+) [NC]
RewriteRule ^ %1/%2/? [L,NE,R=301]
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d [OR]
RewriteCond %{REQUEST_URI} \.(?:jpe?g|gif|bmp|png|ico|tiff|css|js)$ [NC]
RewriteRule ^ - [L]
RewriteRule ^([a-z0-9]+)/([^\s.]*)[.\s]+(.*)$ $1/$2-$3 [NC,DPI,E=DONE:1]
RewriteCond %{ENV:DONE} =1
RewriteRule ^([0-9a-z]+)/([^\s.]+)$ $1/$2 [R=301,NE,L]
RewriteRule ^([a-z0-9]+)/([a-z0-9-]+)/?$ store_info.php?store=$1&dentist=$2 [QSA,L,NC]
</IfModule>
I've read about RedirectMatch however I don't know where to implement it into my htaccess file.

Inside your store_info.php have code like this:
<?php
$store = $_GET['store'];
if (empty($store)) {
header("HTTP/1.1 404 Not Found");
exit;
}
$dentist = $_GET['dentist']);
// pull dentist from DB by store id. Create this function in PHP and
// query your database
$dentistFromDB = preg_replace('/[\h.]+/', '-', $row['businessName']);
// DB returns an empty or no value
if (empty($dentistFromDB)) {
header("HTTP/1.1 404 Not Found");
exit;
}
// DB returned value doesn't match the value in URL
if ($dentistFromDB != $dentist) {
// redirect with 301 to correct /<store>/<dentist> page
header ('HTTP/1.1 301 Moved Permanently');
header('Location: /' . $store . '/' . $dentistFromDB);
exit;
}
// rest of the PHP code should come now
?>

You do not need to clutter your htaccess file anymore with arbitrary rules/directives. The current set of rules, with the %{THE_REQUEST} matching, and later with the %{ENV=DONE} conditionals are more than enough.
Just wait a few days for google to crawl your pages again, and the older unclean urls will disappear. You could also search around in Google Webmaster Tools to see if this can be triggered manually.
PS: You can remove the RewriteCond %{QUERY_STRING} . line from your first rule.

Related

.htaccess rule for adding .php extension and rule for fallback to route.php don't work together, only when used separately

Here is my .htaccess file, it's in the / directory and is working. I want to remove .php extensions from my site. So, I use the following rule to do so. RewriteRule ^([^\.]+)$ $1.php [NC,L].
This works but I also want to redirect my blog articles which use dynamic links with this RewriteRule ^([^?]*) route.php?blog=$1 these blogs pull an ID from a database and embed it into the URL and this works correctly.
My issue is that when I add the first paragraph code to remove .php extensions my blog redirect stops working. Below I will add my PHP code, for review in case I've done something wrong.
Options +FollowSymLinks
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^?]*) route.php?blog=$1
RewriteRule ^([^\.]+)$ $1.php [NC,L]
# Error Documents
#ErrorDocument 404 /error_404.php
#ErrorDocument 403 /error_403.php
<?php
// open database //
include($_SERVER['DOCUMENT_ROOT']."/config.php");
$blog = explode("/",$_REQUEST['blog']);
$months = array('','January','Feburary','March','April','May','June','July','August','September','October','November','December');
switch(count($blog))
{
case 3 : {
if($blog[0]=="blog")
{
if(intval($blog[2]) > 0)
{
// get selected blog
$sql = "select * from articles a, categories c where a.cat = c.catid and a.id = '".$blog[2]."' limit 0,1";
$res = $db->query($sql);
$rowcount = $res->num_rows;
if($rowcount > 0)
{
$id = $blog[2];
$blog = mysqli_fetch_assoc($res);
include($doc_path."/blog-single.php");
}
}
}
} break;
}
blog-single.php
<?php
$sql = "select * from categories c, articles a, relatedposts r where r.related_blog = ".$blog['id']." and a.id = r.related_post and c.catid = a.cat order by a.datetime";
$rows = $db->query($sql);
$found = $rows->num_rows;
if($found > 0)
{
?>
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^?]*) route.php?blog=$1
RewriteRule ^([^\.]+)$ $1.php [NC,L]
The "problem" here is that the first rule rewrites any request (that does not map to a file or directory) to route.php, passing the requested URL-path in the blog URL parameter. Consequently, the second rule (that appends .php to any URL-path that does not contain a dot) is never successful.
You need to reverse the rules and first check that the corresponding .php file exists before appending the .php extension. Any requests that are not mapped to a .php file will then fall through to route.php.
For example:
# Append ".php" extension if the ".php" file exists
RewriteCond %{DOCUMENT_ROOT}/$1.php -f
RewriteRule ^([^.]+)$ $1.php [L]
# Otherwise, drop through to "route.php"
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.+) route.php?blog=$1 [L]
The original subpattern [^?]* is not necessary, since the query string is not passed in the URL-path matched by the RewriteRule pattern.
Aside:
Note that neither of these rules handle requests to the document root (ie. the homepage) - as with your original directives. In other words, what do you expect to happen with a request for https://example.com/? Should this also be rewritten to route.php (is it already)? If so, then set the DirectoryIndex directive accordingly. For example, at the top of the .htaccess file:
DirectoryIndex route.php
Note that this will result in any request for the "homepage" being sent to route.php, but without the blog URL parameter (it would be empty anyway).
UPDATE: Although, looking at your PHP script, it doesn't look like you are expecting the document root (ie. an empty URL-path) being handled by route.php (your first script I assume)? In fact, your script would seem to expect 3 URL path segments only? In which case, you should consider making your regex more restrictive in .htaccess to prevent your script being unnecessarily called. This will allow the request to fall through to Apache's 404 error document.

how to redirect "www.somedomain.com/folder1/demo.jpg" request to some other page using mod_rewrite?

code block:
Options +FollowSymLinks
RewriteEngine On
RewriteCond %{HTTP_HOST} mysite.000webhostapp.com$ [NC]
RewriteCond %{HTTP_HOST} !folder1
RewriteRule ^(.jpg)$ http://mysite.00xxxtapp.com/folder1/$1 [R=301,L]
I think you want your filename in the new url as well? (not just ".jpg")
RewriteRule ([^/]+\.jpg)$ http://mysite.00xxxtapp.com/folder1/$1 [R=301,L]
or
RewriteRule ([^/]+\.jpg)$ /folder1/$1 [L]
if you want to keep seeing the old url
EDIT
So you need more than 1 rewriterule.
I suggest the steps
all "fake" urls redirect to some php script
all images in /folder1/ must be redirected or be made inaccessable (suggestion: put them outside the document root|)
RewriteEngine On
# all images in somefolder will be parsed through a php script
RewriteRule somefolder/([^/]+\.jpg)$ /imageshower.php [L]
# redirect to a no access image
RewriteRule folder/*\.jpg /no-access.jpg [R]
The php script will be able to do some checking like 'is the user logged in?' or does he have the rights
<?php
$filename = basename($_SERVER['REQUEST_URI']); // this still points to the jpg
if(is_file('folder/'. $filename) && is_allowed($user, $filename)) {
header('Content-Type: images/jpg'); // or other like .gif or .pdf etc
readfile('folder/'. $filename);
}
?>

.htaccess url rewriting is working but not the redirection

I'm working on a local server on an html/php application and I'm trying to use the Apache url rewrite module without success
The application was stored in ./Compta/index.php. I have to an .htaccess file in ./Compta/.htaccess
I would like to only use a rewritten url like :http://localhost/Compta/Test/
instead of : http://localhost/Compta/index.php?page=test
and redirect users if they try to go to the old url
The .htaccess file contains :
Options +FollowSymlinks
RewriteEngine on
RewriteRule ^([[:alnum:]]*)/$ /Compta/index.php?page=$1 [L]
RewriteRule ^([[:alnum:]]*)$ /Compta/index.php?page=$1 [L]
RewriteCond %{REQUEST_URI} ^/index\.php$
RewriteCond %{QUERY_STRING} ^page=([[:alnum:]]*)$
RewriteRule ^(.*)$ http://localhost/Compta/%1/ [L,R=301]
When I go to http://localhost/Compta/Test/ the following line is working and my code includes in a div the content of test.php :
RewriteRule ^([[:alnum:]]*)/$ /Compta/index.php?page=$1 [L]
When I go to http://localhost/Compta/Test the following line is working but in firefox the url is rewritten to http://localhost/Compta/index.php?page=Test and this is not happening with http://localhost/Compta/Test2; the url isn't rewritten.
RewriteRule ^([[:alnum:]]*)$ /Compta/index.php?page=$1 [L]
To fix this and to redirect the old url I added these lines :
RewriteCond %{REQUEST_URI} ^/index\.php$
RewriteCond %{QUERY_STRING} ^page=([[:alnum:]]*)$
RewriteRule ^(.*)$ http://localhost/Compta/%1/ [L,R=301]
But this is not working and when I go to http://localhost/Compta/index.php?page=Test the url isn't rewritten to http://localhost/Compta/Test/
Thank you in advance
I didn't find a solution with .htaccess but i found one with php so i added the following lines in top of my php files :
if(preg_match("/\/Compta\/index\.php\?page=([[:alnum:]]*)/",#$_SERVER['REQUEST_URI'],$page)&&!empty($page[1]))
{
$new_url = "/Compta/";
switch (strtolower($page[1])) {
case "test":
$new_url = $new_url."Test/";
break;
case "test2":
$new_url = $new_url."Test2/";
break;
default:break;
}
header("Status: 301 Moved Permanently", false, 301);
header("Location: ".$new_url);
exit;
}
I test if the url begin with "/Compta/index.php?page=" AND if there is a parameter for "page"
Then I initialise the variable which contain the new url
Switch the content of my parameter I modify the new url
and then I make the redirection to my new url :)

Multi language custom 404 htaccess rules causing redirect loop

I'm working on a multi language website where I need to set up a custom 404 page for each language. I've got the following rules in .htaccess which don't quite work right:
RewriteCond %{REQUEST_URI} !^/(ie)(/|$) [NC]
ErrorDocument 404 http://www.domain.com/ie/404/
RewriteCond %{REQUEST_URI} !^/(se)(/|$) [NC]
ErrorDocument 404 http://www.domain.com/se/404/
RewriteCond %{REQUEST_URI} !^/(nl)(/|$) [NC]
ErrorDocument 404 http://www.domain.com/nl/404/
#last rule becomes default
RewriteCond %{REQUEST_URI} !^/(en)(/|$) [NC]
ErrorDocument 404 http://www.domain.com/uk/404/
RewriteRule ^([a-z]{2})/404(/)?$ index.php?controller=utils&method=view404&lang=$1 [L]
RewriteRule ^([a-z]{2})/404.html$ index.php?controller=utils&method=view404&lang=$1 [L]
I think the issue may be with the ! in the RewriteCond, however removing this didn't help. If I visit domain.com/4t3409t0 (a page which doesn't exist) this matches the last RewriteCond and redirects to domain.com/uk/404 (which actually works).
However if I try a URL such as domain.com/ie/wfnwio it attempts to redirect to domain.com/ie/404 (as it should) and I get stuck in a redirect loop.
So it looks like when the last RewriteCond is met the rewrite works but for any others they fail.
I just need to set the ErrorDocument URL for each language, the functionality for redirecting non existing content to 404 already exists.
Thanks for any input,
James
I would suggest replacing all of that with something like this:
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-l
RewriteRule ^(ie|se|nl)/ $1/404 [R=404,L]
Explanation
The three conditions check that the requested file or folder does not exist
The rule checks that the requested url starts with one of the three countries then a /, captureing the country code to Group 1
It redirects to Group1/404, e.g. ie/404 with a 404 code
I got an idea from this comment.
In .htacces file:
ErrorDocument 404 "<script>window.location.href='/error.php?page='+window.location.href;</script>"
In error.php (in root directory) :
<?php
$lg="en"; // default 404 page language
$langs=array("az","tr","ru","en");
if(isset($_GET['page'])){
$page=$_GET['page'];
foreach($langs as $lang){
if(strpos($page,"lang=".$lang)!==false) { $lg=$lang; break; }
}
}
echo '<meta http-equiv="refresh" content="0;URL=/index.php?controller=utils&method=view404&lang='.$lg.'" />';
exit;
I think the issue I had was with the RewriteCond being incorrect. However I found a workaround as PHP stores the language in a session variable.
ErrorDocument 404 http://www.domain.com/404/
RewriteRule ^404(/)?$ index.php?controller=utils&method=view404 [L]
RewriteRule ^([a-z]{2})/404(/)?$ index.php?controller=utils&method=view404&lang=$1 [L]
RewriteRule ^([a-z]{2})/404.html$ index.php?controller=utils&method=view404&lang=$1 [L]
My workaround simply uses domain.com/404 as the default, which then sets the language via session if possible, or loads the UK 404 page if not.
If the language variable is set in the query string it is passed using the 2nd and 3rd rewrite rules.

How to edit this url with mod_rewrite

I have a godaddy linux server and I am wanting to edit my url's
Here is an example of 3 url's from my website
www.website.com/b.php?n=30&t=big
www.website.com/b.php?n=20&t=medium
www.website.com/b.php?n=10&t=small
I would like to be able to change them to
www.website.com/30/big
www.website.com/20/medium
www.website.com/10/small
MY IMAGE CODE
echo '<img src="gifs/' . $_GET["t"] . '/' . $_GET["n"] . '.gif">';
You can change them by changing all the links on your site from the /b.php?n=30&t=big style links to the /30/big style links. Then you can put these rules in the htaccess file in your document root:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^/?([^/]+)/(.*) /b.php?n=$1&b=$2 [L,QSA]
this will change the URI's back to the ones that route through b.php.
In the event that you have old URL's floating around the internet and they need to be changed to the new ones, you can use these in the same htaccess files:
RewriteCond %{THE_REQUEST} ^[A-Z]{3,9}\ /b\.php\?n=([^&]+)&t=([^&\ ]+)
RewriteRule ^/?b\.php$ /%1/%2 [L,R=301]
This will redirect the browser (or google index bot) to point permanently to the new URLs.