Why does this .htaccess not work? - .htaccess

I have a url like this:
http://domain.com/index.php?id=223
And this .htaccess code:
RewriteEngine On
RewriteRule ^([^/]*)\.html$ /index.php?id=$1 [L]
From what I understand this should output:
http://domain.com/223.html
But its not doing anything, can someone please explain how this works and what I'm doing wrong?

Your original rule takes any file that does not include a slash and ends with ".html" at the root level (including a file called ".html") and redirects the request to a file called index.php and it takes the first part of the filename from the request (before the dot) and passes it as a query called "id."
RewriteRule ^([^/]*)\.html$ /index.php?id=$1 [L]
Since this is .htaccess you should take the slash off
You should do this:
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^([^/]+)\.html$ /index.php?id=$1 [L]
In your html itself in the links, you'll need to call filename.html.
<a href='/223.html'>Some page with an id of 223</a>
For SEO you can take the start match off
RewriteRule ([^/]+)\.html$ /index.php?id=$1 [L]
This would make it so you could reference a file like:
/somedirectory/someseotitle/223.html
Additionally you should then create 301 redirects from all of the id=$id links and make them go to their intended targets with the full URL. The code below would go into the index.php file at the top before any cookies are set or sessions started. As an example of what you could do... I'm only guessing about table structure:
<?php
if ($_SERVER['REQUEST_URI']=='/index.php' && !empty($_GET['id']){
if (is_numeric($_GET['id'])){
$id = $_GET['id'];
$cquery = "select count(*) from table where id = $id";
$count = mysqli_result(mysqli_query($cquery),0);
if($count == 1){
$tquery = "select title from table where id = $id";
$result = mysqli_query($tquery);
while ($row=mysqli_fetch_array($result)){
$title = urlencode($row['title']);
$headerString = "Location: /$title/$id.html";
header( "HTTP/1.1 301 Moved Permanently" );
header($headerString);
}
}
}
}
?>

In addition to what you already have in .htaccess you will need a rule for external redirection of /index.php?id=223 to /223.html. This should be your complete .htaccess:
Options +FollowSymLinks -MultiViews
# Turn mod_rewrite on
RewriteEngine On
RewriteBase /
RewriteCond %{THE_REQUEST} ^[A-Z]{3,}\s/+(?:index\.php|)\?id=([^&\s]+) [NC]
RewriteRule ^ /%1.html? [R=302,L]
RewriteRule ^([^.]+)\.html$ /index.php?id=$1 [L,QSA,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.

Related

How can I redirect url with .htaccess like instagram?

If the link does not have any value, redirect to index.php.
Example;
www.mydomain.com/ --> index.php
If the link is www.example.com/post/value, redirect to post.php.
Example;
www.mydomain.com/post/cDfS58Q --> post.php
If the link only consists of value, redirect to profile.php.
Example;
www.mydomain.com/jhon.34 --> profile.php
My test:
RewriteRule ^post/([0-9a-zA-Z-_/.]+)$ post.php?$1 [QSA,L]
RewriteRule ^([0-9a-zA-Z-_/.]+)$ profile.php?$1 [QSA,L]
but they all go to post.php.
Set the rewrite rules for each scenario except for the link that does not have any value. The default file that opens when visiting a website is the index file so you don't need to explicitly set it.
Go from longest URI to smallest because the condition of the smaller URI usually satisfies the conditions for the bigger URI.
Try somethig like this:
# Mod Rewrite setup
Options +FollowSymlinks
RewriteEngine on
AddDefaultCharset UTF-8
# First enter the one with the longest URI
RewriteCond %{REQUEST_URI} ^/?post/([0-9a-zA-Z-_/.]+)/?$
RewriteRule ^(.*)$ /post.php?data=%1 [NC,L]
# Then the one with only value
RewriteCond %{REQUEST_URI} ^/?([0-9a-zA-Z-_/.]+)/?$
RewriteRule ^(.*)$ /profile.php?data=%1 [NC,L]
I did it in a different way ;
htaccess
RewriteRule ^p/(.*)$ post.php?$1 [QSA,L]
RewriteRule ^([0-9a-zA-Z]+)$ index.php?$1 [QSA]
RewriteRule ^([0-9a-zA-Z]+)/$ index.php?$1 [QSA]
index.php
<?php
if (!empty($_SERVER['QUERY_STRING'])) {
//Profile.php will be included here.
echo "You are in profile now.";
}else {
//Homepage.php will be included here.
echo "You are in profile now.";
}
?>
Url : www.localhost.com/adsasd
Output : You are in profile now.
Url : www.localhost.com/
Output : You are in homepage now.

how to Rewrite Single Page url in .htaccess

I need to rewrite only 1 specific URL
from
http://www.domainname.com/index.php?route=payment/axis/callback
to
http://www.domainname.com/payment/axis/callback
I tried these two from stack overflow, I don't know why its not working
1st one :
RewriteRule ^([A-Za-z0-9-]+)/?$ index.php?route=payment/axis/callback [NC,L]
2nd one :
RewriteRule ^index.php?route=payment/axis/callback payment/axis/callback [L]
Try this:
4) Rewriting yoursite.com/user.php?username=xyz to yoursite.com/xyz
Have you checked zorpia.com.If you type http://zorpia.com/roshanbh233 in browser you can see my profile over there. If you want to do the same kind of redirection i.e http://yoursite.com/xyz to http://yoursite.com/user.php?username=xyz then you can add the following code to the .htaccess file.
RewriteEngine On
RewriteRule ^([a-zA-Z0-9_-]+)$ user.php?username=$1
RewriteRule ^([a-zA-Z0-9_-]+)/$ user.php?username=$1
See the full page here.
Hope it helps!
I wouldn't use .htaccess with RewriteRule, since there are often problems with it. A simple workaround (with PHP redirect):
<?php
if($_GET['route'] == 'payment/axis/callback') {
header("Location: http://www.domainname.com/payment/axis/callback");
}
?>
You can either use h0ch5tr4355's workaround or you can try this:
RewriteEngine on
RewriteCond %{QUERY_STRING} ^route=payment/axis/callback$
RewriteCond %{SCRIPT_FILENAME} index.php
RewriteRule (.*) /payment/axis/callback [NC,QSD]
If you instead of a rewrite would like it to redirect to the new url you can add R=301 to the flags of the RewriteRule.

Rewrite url to pretty after redirect to folder - htaccess laravel

Hello I have a "protected" folder on my server. In its .htaccess file for conditional redirect of some users I use the following rules:
RewriteCond %{REMOTE_ADDR} ^1\.2\.3\.4*
RewriteCond %{REQUEST_URI} !^/special
RewriteRule ^$ /special [R,NE,NC]
In the /special folder I have a .htaccess file with the following rules:
RewriteCond %{REMOTE_ADDR} !^1\.2\.3\.4$
RewriteRule ^(.*)$ / [R=301,NE,NC,L]
The application in the folder will be laravel based so my content will have to be served from index.php file residing in /special/laravel/public/index.php
I want the URL to look like /special/.
What rules should I put and where for this to happen?
This is a follow up to my previous question:
https://stackoverflow.com/questions/24487012/redirecting-specific-ip-to-special-content-htaccess-vs-php
Simply rewrite the URL with .htaccess: (goes in /)
DirectoryIndex index.php
#Redirect to /special/laravel/public if you haven't already and the IP is okay
RewriteCond %{REMOTE_ADDR} ^1\.2\.3\.4*
RewriteCond %{REQUEST_URI} !^/special/laravel/public
RewriteRule ^(/special)(/laravel)?(.+) /special/laravel/public$2 [L]
#if IP does not match and you ARE in the folder, then Redirect to root
RewriteCond %{REMOTE_ADDR} !^1\.2\.3\.4*
RewriteCond %{REQUEST_URI} ^/special/laravel/public
RewriteRule .? / [R=301,L]
I think that'll work. I didn't test it though. I can add to it if you need me to. And of course for your use case you may need to add some more RewriteConds in there for validating the REMOTE_ADDR.
The way I handle it:
.htaccess:
RewriteCond %{REQUEST_URI} !^/load_page.php$
RewriteRule ^(.+)$ /load_page.php [QSA, L]
That causes the server to redirect internally to load_page.php if the requested URL is not load_page. Without the RewriteCond, I believe it would cause an infinite redirect. This should work, but I didn't test it because it's different from my implementation, since mine also handles rewriting URLS to have trailing slashes and never show .php which makes it a bit more complex and quite different.
load_page.php:
$SITE_ROOT = $_SERVER['DOCUMENT_ROOT'];
$URL = $_SERVER['REQUEST_URI'];
ob_start();
if (conditionOne){
//change $URL here if you need to or do nothing
} else if (conditionTwo){ //check the IP or whatever you want to here
if (aCondition){//if $URL starts with '/special'
$URL = str_ireplace('/special/','/special/laravel/public/',$URL,1);
}
if (is_dir($SITE_ROOT.$URL))$URL .='index.php';
}
if (!file_exists($SITE_ROOT.$URL))$URL = '/error/404.php';
include($SITE_ROOT.$URL);
$content = ob_get_clean();
echo $content;
It's something to that affect. The user doesn't see load_page.php and they don't see that you changed the URL to special/laravel/public, but you include the correct file.

Remove index.php?route= from OpenCart

I'm a .NET developer but my friend called me for support.I made some changes with .htaccess but i'm corrupted SEO.
Everything started with "www" tag on url.I see we get some errors when we are not using "www" and i'm changed .htaccess.I'm added rewrite rule and redirected mysite.com to www.mysite.com.Our problems are solved but now we have another problem.
We are using Opencart - SEO and it's enabled.Our products seems like
http://www.mysite.com/epson-claria-uyumlu-yazici-kartus-dolum-murekkebi-500g.html
when we are reaching with www.
But if i remove "www" tag on url, it seems like
http://www.mysite.com/index.php?_route_=epson-claria-uyumlu-yazici-kartus-dolum-murekkebi-500g.html
and it corrupt SEO.
I want to see second url like first one.
I'm tried play with seo_url.php , .htaccess but it doesn't change anyting.
I'm also tried solution on Remove index.php?route=common/home from OpenCart but it's not worked for me.
Now my seo_url.php is default, i get back my changes.And my .htaccess is
# SEO URL Settings
RewriteEngine On
# If your opencart installation does not run on the main web folder make sure you folder it does run in ie. / becomes /shop/
RewriteBase /
RewriteRule ^sitemap.xml$ index.php?route=feed/google_sitemap [L]
RewriteRule ^googlebase.xml$ index.php?route=feed/google_base [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !.*\.(ico|gif|jpg|jpeg|png|js|css)
RewriteRule ^([^?]*) index.php?_route_=$1 [L,QSA]
RewriteCond %{QUERY_STRING} ^route=common/home$
RewriteRule ^index\.php$ http://www.mysite.com? [R=301,L]
RewriteCond %{HTTP_HOST} !^www\.mysite\.com$
RewriteRule (.*) http://www.mysite.com/$1 [R=301,L]
RewriteRule ^(.*)$ index.php?_route_=$1 [L]
Please help me before i get crazy.I spend 3 hours for that.
Thank you for all,
Greetings
Try This Its working for me using .htaccess.
RewriteCond %{THE_REQUEST} \ /index\.php\?_route_=?([^&\ ]*)
RewriteRule ^ /%1? [L,R]
Also have the same problem and any that I found not solved my problem. But! I remember that I also working with Laravel and in this engine well working url path. Don't ask why I associated OpenCart with Laravel. So I enable SEO radio button in System -> Settings -> Server you also can disable it I don't see difference in the site work.
This solution consist from several part:
1. In your root folder replace .htaccess file content with next shapshot:
<IfModule mod_rewrite.c>
<IfModule mod_negotiation.c>
Options -MultiViews -Indexes
</IfModule>
RewriteEngine On
# Handle Authorization Header
RewriteCond %{HTTP:Authorization} .
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
# Redirect Trailing Slashes If Not A Folder...
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} (.+)/$
RewriteRule ^ %1 [L,R=301]
# Handle Front Controller...
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php?route=$1 [L]
</IfModule>
2. Go to /system/library/url.php and find link method and replace it with next:
public function link($route, $args = '', $secure = false) {
if ($this->ssl && $secure) {
$url = $this->ssl . 'index.php?route=' . $route;
} else {
$url = $this->url . 'index.php?route=' . $route;
}
if ($args) {
if (is_array($args)) {
$url .= '&' . http_build_query($args);
} else {
$url .= str_replace('&', '&', '&' . ltrim($args, '&'));
}
}
foreach ($this->rewrite as $rewrite) {
$url = $rewrite->rewrite($url);
}
$url = str_replace('index.php?route=', '', $url);
return $url;
}
Since you changed .htaccess in root folder and change url generating method you also need remember about admin part. If you what see pretty url in admin just copy .htaccess from root folder to /admin folder.
If you want save orignal url in admin side you must little bit change link method with next:
public function link($route, $args = '', $secure = false) {
if ($this->ssl && $secure) {
$url = $this->ssl . 'index.php?route=' . $route;
} else {
$url = $this->url . 'index.php?route=' . $route;
}
if ($args) {
if (is_array($args)) {
$url .= '&' . http_build_query($args);
} else {
$url .= str_replace('&', '&', '&' . ltrim($args, '&'));
}
}
foreach ($this->rewrite as $rewrite) {
$url = $rewrite->rewrite($url);
}
// Skip admin path
if (strpos($_SERVER['REQUEST_URI'], '/admin') !== 0) {
$url = str_replace('index.php?route=', '', $url);
}
return $url;
}
Result:
Before
http://YOUR_SITE/index.php?route=product/product&product_id=52
After
http://YOUR_SITE/product/product&product_id=52
Before
http://YOUR_SITE/index.php?route=account/login
After
http://YOUR_SITE/account/login
Just try this..
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule .* index.php/$0 [PT,L]
Old question i know but maybe someone would find it helpful: The reason SEO urls break if you change the HTACCESS rule is that they depend on _route_ for clarification that "yes this is a request for a clean url, no its not a standard route".
If you change index.php?_route_= in the HTACCESS you must also change the _route_ IF conditionals in /catalog/controller/common/seo_url.php. It may get heavily wonked out though if you do this, try it on test stores first.
Nothing should be seeing the _route_ except you in the logs or things like analytics logs since its a masked utility uri. If you see real humans are asking what the link is, then take action. Otherwise, its best to leave it.

How to pass-through requests not going to specific directories to index.php/path?

In my present project I've got several directories: application (my MVC files, which mustn't be accessed), images, css, and js. Effectively I want all requests to images/css/js to proceed unchanged, but all others I wish to call index.php/my/path.
My .htaccess currently looks like this, and is wreaking havoc with my routing.
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteCond $1 !^(index\.php|images|js|css|robots\.txt)
RewriteRule ^(.*)$ http://example.com/index.php/$1 [L]
</IfModule>
This isn't working as relative URLs start stacking up, such as: example.com/blog/view/1/blog/view/2.
When I attempt something like,--
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteCond %{REQUEST_URI} !^/(index\.php|images|js|css|robots\.txt)
RewriteRule ^ index.php%{REQUEST_URI} [PT]
</IfModule>
I get this error with any request: No input file specified.
How can I force all requests not to my whitelisted directories to call, not redirect to (redirection murders posting, I found), index.php/path? IE, when /blog/view/1 is requested by the browser, .htaccess calls index.php/blog/view/1. The reference files at Apache's site aren't too clear about how to do this sort of thing—that, or, I am just missing the point of what I'm reading about RewriteRule.
And, I really want to understand this. Why will your answer work? Why are my attempts failing?
This is what I have in my .htaccess for my framework:
<IfModule mod_rewrite.c>
RewriteEngine on
#This will stop processing if it's images
RewriteRule \.(css|jpe?g|gif|png|js)$ - [L]
#Redirect everything to apache
#If the requested filename isn’t a file….
RewriteCond %{REQUEST_FILENAME} !-f
#and it isn’t a folder…
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?$1 [L,QSA]
#L = (last - stop processing rules)
#QSA = (append query string from requeste to substring URL)
</IfModule>
Hope this helps.
PS: Maybe you want to remove the lines to stop redirecting if it's a file or folder ;)
Antonio helped me get on the right track, so here's the resulting .htaccess:
<IfModule mod_rewrite.c>
RewriteEngine on
# skip if whitelisted directory
RewriteRule ^(images|css|js|robots\.txt|index\.php) - [L]
# rewrite everything else to index.php/uri
RewriteRule . index.php%{ENV:REQUEST_URI} [NE,L]
</IfModule>
You're going to have to do that using PHP. For example, if you wanted to split your URI into something like domain.tld/controller/action/param, then you could use the following PHP code as a start:
<?php
// Filter URI data from full path
$uri_string = str_replace($_SERVER['SCRIPT_NAME'], '', $_SERVER['REQUEST_URI']);
$uri_string = trim($uri_string, '/'); // Make sure we don't get empty array elements
// Retrieve URI data
$uri_data = explode('/', $uri_string);
In that case, $uri_data[0] is the controller, $uri_data[1] is the action, and beyond that are parameters. Note that this isn't a foolproof method, and it's never a great idea to trust user-entered input like this, so you should whitelist those controllers and actions which can be used.
From here, knowing the controller and having a consistent directory structure, you can require_once the proper controller and call the action using variable variables.
This is what I use in my .htaccess file for my CMS:
Options -Indexes
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.+)$ index.php/$1 [NC,L]
And then in my index.php file I have:
$path_info = '';
$path_info = isset($_SERVER['PATH_INFO']) ? $_SERVER['PATH_INFO'] : $path_info;
$path_info = isset($_SERVER['ORIG_PATH_INFO']) ? $_SERVER['ORIG_PATH_INFO'] : $path_info;
$request = explode('/', trim($path_info, '/'));
// if $request[0] is set, it's the controller
// if $request[1] is set, it's the action
// all other $request indexes are parameters
Hope this helps.

Resources