mod_rewrite - How to keep rewritten addresses without changing html links - regex

Let's say I have a website with given sites:
index.php
info.php
In order to hide the "index.php" part of the URL and to change "info.php" to "info" I create the following .htaccess:
RewriteEngine On
RewriteRule ^info$ info.php
RewriteRule ^.$ index.php
It works just fine when I type the new URLs directly into address bar, but inside index.php I have the:
<a href="info.php">
and so when I click the link, it directs me to the info page and displays "info.php" in the URL. If I want to see just "info" in the URL after clicking the link, do I have to change the links inside HTML code? Or is there a way to make .htaccess file do it automatically?

You can put this code in your DOCUMENT_ROOT/.htaccess file for changing these links automatically:
RewriteEngine On
RewriteBase /
# To externally redirect /dir/file.php to /dir/file
RewriteCond %{THE_REQUEST} \s/+(?:index)?(.*?)\.php[\s?] [NC]
RewriteRule ^ /%1 [R=301,L,NE]
# To internally forward /dir/file to /dir/file.php
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{DOCUMENT_ROOT}/$1\.php -f [NC]
RewriteRule ^(.+?)/?$ /$1.php [L]
But it is highly recommended to change these links in your HTML page to avoid one external redirect.

Related

.htaccess how to remove file extensions and index files

I'm trying to achieve a few things through .htaccess ,but keep running into issues. Before you tell me I need to research better and there's already a solution on this or a different forum, please know I've already done that. I always try and figure out things on my own before coming here, but this one is truly stumping me. Everything I've tried has only partially worked. Any help or education here would be truly appreciated.
My site has the following simple structure:
(root)
| index.html
| .htaccess
|
|___portal-folder
| index.php
| home.php
|
|_____admin-folder
| index.php
I'm looking to achieve the following:
When a user navigates to any base directory, for instance site.com or site.com/portal-folder/ they don't see the index file name index.html or index.php in their browser.
Same holds true if the user navigates to the full URL site.com/index.html or site.com/portal-folder/index.php I would like the user to see site.com or site.com/portal-folder/ respectively in their browser.
Strip the file extension off all files in the browser. So for instance navigating to site.com/portal-folder/home.php would show as site.com/portal-folder/home in the browser
The following code I'm using kind of works, but I'm getting strange behavior. For instance:
navigating to site.com/portal-folder/index doesn't remove the index file name and show up as site.com/portal-folder/index instead of site.com/portal-folder/ in the browser
navigating to site.com/portal-folder/ doesn't remove the index file name and shows up as site.com/portal-folder/index.php in the browser.
navigating to site.com/portal-folder/index.php takes the user back to the root site.com
navigating to site.com/portal-folder/home works correctly, but navigating to site.com/portal-folder/home.php doesn't strip the .php extension off.
navigating to site.com works correctly, but navigating to site.com/index.html doesn't remove the index file name.
RewriteEngine On
DirectoryIndex index.html index.php
# remove trailing slash
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{THE_REQUEST} \s(.+?)/+[?\s]
RewriteRule ^(.+?)/$ /$1 [R=301,L]
# To internally forward /dir/file to /dir/file.php
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{DOCUMENT_ROOT}/$1.php -f
RewriteRule ^(.+?)/?$ /$1.php [L]
Server Information: Apache Version 2.4.46
Have it this way:
DirectoryIndex index.html index.php
RewriteEngine On
# To externally redirect /dir/file.php to /dir/file and optionally remove index
RewriteCond %{THE_REQUEST} \s/+(.*?/)?(?:index|(\S+?))(?:\.php|\.html)?[/\s?] [NC]
RewriteRule ^ /%1%2 [R=301,L,NE]
# remove trailing slash
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} ^(.+)/+$
RewriteRule ^ %1 [R=301,NE,L]
# To internally forward /dir/file to /dir/file.php
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{DOCUMENT_ROOT}/$1.php -f
RewriteRule ^(.+?)/?$ $1.php [L]

Using htaccess to get rid of /index.php link?

I can open my site like this:
www.mysite.com
or like this:
www.mysite.com/index.php
I want to create a htaccess rule that redirects www.mysite.com/index.php to www.mysite.com. But all my attempts have other side effects. I've tried:
Redirect index.php home.php
RewriteRule ^index.php?$ home.php [NC,L]
RewriteRule ^index.php/?$ redirect_to_home.php [NC,L]
But all of these mess up the original index.php call. So it does redirect but then the normal mysite.com link doesnt work anymore.
Any ideas?
Could you please try following.
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} -f
RewriteCond %{THE_REQUEST} index\.php
RewriteCond %{REQUEST_URI} ^(.*/)index\.php$
RewriteRule ^ %1 [R=301,L]
Explanation:
Making RewriteEngine On to make the rules work.
Mentioning condition by RewriteCond to REQUEST_FILENAME which checks if mentioned file in browser is present.
Then checking if THE_REQUEST which has complete details of request(including URL and GET/POST method) if it has index.php in it.
Now checking if REQUEST_URI is having index\.php in requested url, where saving everything before it to temp buffer memory to retrive its value later(basically its domain name).
Finally in RewriteRule to redirect complete URL with index.php to till domain name only as per requirement(R=301 is for permanent redirection on browser side).
Use this redirect rule to remove /index.php from any path:
RewriteEngine On
RewriteCond %{THE_REQUEST} /index\.php [NC]
RewriteCond %{REQUEST_URI} ^(.*/)index\.php$ [NC]
RewriteRule ^ %1 [L,R=301,NE]

How can I load content from two different folders (based on the subdomain) and keep the old URLs?

My website is example.com.
In my public_html folder, I have two folders. One is called main, and the other is called report.
When somebody navigates to example.com, I want to serve content from the main folder, but I want their URL to remain the same.
So, if they navigate to example.com/file.html, I want them to see the file.html file that's in the main folder, but I don't want their URL to change to example.com/main/file.html.
Similarly, if they navigate to report.example.com/report1.pdf, I want them to see the report1.pdf file that's in the report folder, but I don't want their URL to change to report.example.com/report/report1.pdf.
The closest thing I've been able to achieve is this:
DirectoryIndex index.php index.html index.htm
RewriteEngine on
RewriteBase /
RewriteCond %{HTTP_HOST} ^example.com$ [NC]
RewriteRule ^((?!main).*)$ /main/$1
RewriteCond %{HTTP_HOST} ^report.example.com$ [NC]
RewriteRule ^((?!report).*)$ /report/$1 [L]
That seems to work to some extent, but:
If somebody navigates to http://example.com/report/index.html, the server incorrectly loads the index.html file from the public_html/report folder rather than the public_html/main/report folder. Normally that path would make sense, but in this case I'm trying to change that behavior.
If somebody navigates to http://report.example.com/test, the server correctly displays the public_html/test/index.html file, but redirects them to http://report.example.com/report/test/.
How can I load the correct files and keep the URLs correct?
This should do:
RewriteCond %{HTTP_HOST} ^example.com$ [NC]
RewriteCond %{ENV:REDIRECT_STATUS} !200
RewriteRule ^ /main%{REQUEST_URI} [L]
RewriteCond %{HTTP_HOST} ^reports.example.com$ [NC]
RewriteCond %{ENV:REDIRECT_STATUS} !200
RewriteRule ^ /reports%{REQUEST_URI} [L]

Error getting .htaccess to direct googlebot using _escaped_fragment_

I am trying to get my pages indexed on google using a prerendering service for my backbone app.
I know the setup works fine when I specifically add googlebot to the useragent list but Ive been advised against this in favor of using the _escaped_fragment_ method. Only problem is the _escaped_fragment_ parameter isn't getting passed correctly. Can some help please?
thanks!!!
# html5 pushstate (history) support:
<ifModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTP_HOST} ^example\.com$ [OR]
RewriteCond %{HTTPS} !on
RewriteRule ^(.*)$ https://www.example.com/$1 [R=301,L]
# If requested resource exists as a file or directory
# (REQUEST_FILENAME is only relative in virtualhost context, so not usable)
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -f [OR]
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -d
# Go to it as is
RewriteRule ^ - [L]
# If non existent
# If path ends with / and is not just a single /, redirect to without the trailing /
RewriteCond %{REQUEST_URI} ^.*/$
RewriteCond %{REQUEST_URI} !^/$
RewriteRule ^(.*)/$ $1 [R,QSA,L]
# Handle Prerender.io
RequestHeader set X-Prerender-Token "xxxxxxxx"
RewriteCond %{HTTP_USER_AGENT} baiduspider|facebookexternalhit|twitterbot|rogerbot|linkedinbot|embedly|quora\ link\ preview|showyoubot|outbrain|pinterest|slackbot|vkShare|W3C_Validator [NC,OR]
RewriteCond %{QUERY_STRING} _escaped_fragment_
# Proxy the request
RewriteRule ^(?!.*?(\.js|\.css|\.xml|\.less|\.png|\.jpg|\.jpeg|\.gif|\.pdf|\.doc|\.txt|\.ico|\.rss|\.zip|\.mp3|\.rar|\.exe|\.wmv|\.doc|\.avi|\.ppt|\.mpg|\.mpeg|\.tif|\.wav|\.mov|\.psd|\.ai|\.xls|\.mp4|\.m4a|\.swf|\.dat|\.dmg|\.iso|\.flv|\.m4v|\.torrent|\.ttf|\.woff))(.*) http://service.prerender.io/https://www.example.com/$2 [P,L]
# If non existent
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !index
RewriteRule (.*) index.html [L,QSA]
</ifModule>
All the apache modules are loaded and working.
So the .htaccess is actually correct... here Google's official answer.
Quote from http://productforums.google.com/forum/#!category-topic/webmasters/crawling-indexing--ranking/bZgWCJTnl08%5B1-25%5D by John Mueller (google employee)
Looking at your blog's homepage, one thing to keep in mind is that the Fetch
as Googlebot feature does not parse the content that it fetches. So when you
submit toddmoyer.net/blog/ , it fetches that URL. After fetching the URL, it
doesn't parse it to check for the "fragment" meta tag, it just returns it to
you. However, if you fetch toddmoyer.net/blog/#! , then it should rewrite the
URL and fetch the URL toddmoyer.net/blog/?_escaped_fragment_= .
When we crawl and index your pages, we'll notice the meta-tag and act
accordingly. It's just the Fetch as Googlebot feature that doesn't check for
meta-tags, and instead just returns the raw content.

htaccess: redirect old domain and all pages to a new domain

I know that there is a lot of examples on Stackoverflow but I still miss something.
I'm trying to redirect http://old.domain.com/fr/ to http://brand.new-domain.com/fr/ with the following rules, but that doesn't work:
# Enable Rewrite Engine
RewriteEngine On
RewriteBase /
# Add a trailing slash to paths without an extension
RewriteCond %{REQUEST_METHOD} !=POST
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_URI} !(\.[a-zA-Z0-9]{1,5}|/)$
RewriteRule ^(.*)$ $1/ [L,R=301]
# Redirect domain
Options +FollowSymLinks
RewriteCond %{HTTP_HOST} ^old.domain.com [OR]
RewriteCond %{HTTP_HOST} ^other-old.domain.com [NC]
RewriteRule ^(.*)$ http://brand.new-domain.com/$1 [r=301,L]
# Remove index.php
# Uses the "exclude method"
# http://expressionengine.com/wiki/Remove_index.php_From_URLs/#Exclude_List_Method
# This method seems to work best for us, you might also use the include method.
# http://expressionengine.com/wiki/Remove_index.php_From_URLs/#Include_List_Method
# Exclude root files
RewriteCond $1 !^(index\.php) [NC]
# Exclude EE folders
RewriteCond $1 !^(assets|ee-admin|images|templates|themes|fr|nl)/ [NC]
# Exclude user created folders
RewriteCond $1 !^(assets|css|img|js|swf|uploads)/ [NC]
# Exlude favico, robots, ipad icon
RewriteCond $1 !^(favicon\.ico|robots\.txt|pple-touch-icon\.png) [NC]
# Remove index.php
RewriteCond %{QUERY_STRING} !^(ACT=.*)$ [NC]
RewriteCond %{QUERY_STRING} !^(URL=.*)$ [NC]
RewriteRule ^(.*)$ /index.php?/$1 [L]
It correctly redirect when I call the root URL, but not when I call a page. What am I doing wrong?
Thanks in advance!
Pv
When writing mod_rewrite rules, the rules get applied in the order that they appear.
To redirect an old domain to a new domain, you'll want that rule to be first in your .htaccess or httpd.conf file — all other rules should appear after it.
If you only want to redirect a certain directory, the following rule will do so, while allowing the rest of the site to function normally:
<IfModule mod_rewrite.c>
RewriteEngine On
# Redirect Only Matching Directories
RewriteCond %{REQUEST_URI} ^/(fr|fr/.*)$
RewriteRule ^(.*)$ http://brand.new-domain.com/fr/$1 [R=301,L]
</IfModule>
If you want to redirect the entire site, the following rule will do so:
<IfModule mod_rewrite.c>
RewriteEngine On
# Redirect Entire Site to New Domain
RewriteCond %{HTTP_HOST} ^old.domain.com$ [OR]
RewriteCond %{HTTP_HOST} ^other-old.domain.com$ [NC]
RewriteRule ^(.*)$ http://brand.new-domain.com/$1 [R=301,L]
</IfModule>
If you care about letting crawlers know your content has moved and want to make the transition as seamless as possible, be sure to keep the 301 Redirect flag in the RewriteRule.
This will ensure that users and search engines are directed to the correct page.
While we're on the subject, as part of the EE 2.2 release, EllisLab now "officially" offers limited technical support for removing index.php from ExpressionEngine URLs.
Simply add or update your code to the following, making sure to consider any rules you may already have in place:
<IfModule mod_rewrite.c>
RewriteEngine On
# Removes index.php
RewriteCond $1 !\.(gif|jpe?g|png)$ [NC]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /index.php/$1 [L]
# If 404s, "No Input File" or every URL returns the same thing
# make it /index.php?/$1 above (add the question mark)
</IfModule>
Try to use the following ruke as the first one:
# Redirect domain
Options +FollowSymLinks
RewriteCond %{HTTP_HOST} ^old.domain.com [OR]
RewriteCond %{HTTP_HOST} ^other-old.domain.com [NC]
RewriteRule ^(.*)$ http://brand.new-domain.com/$1 [R=301,L]
Also mind the upper case R with is the short form for the lower case redirect.
Have you tried using mod_alias simple redirect instructions (a core module that you have), before trying the hacky-mod-rewrite thing?
I would do a VirtualHost with ServerName old.domain.com and in this VH I would add this rule:
Redirect /fr http://brand.new-domain.com/fr
from doc:
Then any request beginning with URL-Path will return a redirect request to the client at the location of the target URL. Additional path information beyond the matched URL-Path will be appended to the target URL.
So get a separate VirtualHost for brand.new-domain.com (with ServerName brand.new-domain.com) and in this one do not set the Redirect Rule.
If you still want to handle the 2 domains in the same VirtualHost then you'll have to use mod-rewrite as even RedirectMatch cannot check the request domain on the query.