SEO URL and Rewrite Rule force on one domain - apache

I have a rewrite rule to force user to go from example.com to www.example.com. This is for SEO reasons so that I have no duplicated websites and content on my Google results.
# BEGIN Spark
AddDefaultCharset UTF-8
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTP:Authorization} ^(.*)
RewriteRule .* - [e=HTTP_AUTHORIZATION:%1]
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/$ /$1 [L,R=301]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^ index.php [QSA,L]
RewriteCond %{HTTP_HOST} ^example.com
RewriteRule (.*) https://www.example.com/$1 [R=301,L]
</IfModule>
<IfModule mod_deflate.c>
<FilesMatch "\.(html|php|txt|xml|js|css|ttf|otf|ico|json|svg|)$">
SetOutputFilter DEFLATE
</FilesMatch>
</IfModule>
# END Spark
My question. If now people post a link example.com/news they always will redirect to the frontpage like www.example.com. How can I manage that they still can use and post short URLs like example.com/news1 or example.com/news2 and will redirect to www.example.com/news1 or www.example.com/news2 respectively.

You've put the rule in the wrong place. It needs to go before the internal rewrite (to the front-controller: index.php). eg. at the top of the file, not at the end.
By placing it last it will only correctly redirect physical directories (which includes the homepage) and static resources (images, CSS, JS, etc.). All other "short URLs" that are routed through the front-controller will be redirected to index.php and you'll see the "frontpage".
And... to avoid a double redirect when requesting example.com with a URL that contains a trailing slash then include an absolute URL in the trailing slash removal rule and include your non-www to www rule immediately after that.
For example:
RewriteEngine On
# Remove trailing slash
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/$ https://www.example.com/$1 [L,R=301]
# Redirect non-www to www
RewriteCond %{HTTP_HOST} ^example.com
RewriteRule (.*) https://www.example.com/$1 [R=301,L]
RewriteCond %{HTTP:Authorization} ^(.*)
RewriteRule .* - [e=HTTP_AUTHORIZATION:%1]
# Front-controller
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^ index.php [L]
You will need to clear the browser cache before testing since the erroneous 301 (permanent) redirects will have been cached by the browser. (Test with 302 - temporary - redirects to avoid caching issues.)
Aside: An additional concern is that these directives are inside a # BEGIN Spark ... # END Spark code block - which makes it look as if these directives are perhaps maintained by some automated process? In which case, they might be overwritten?

Related

Redirecting the url entered with htaccess to a different location in the same way

When I enter my example.com url I want to redirect to example.com/en/ but when I enter example.com/demo I want to redirect to example.com/us/demo. The word demo here is just variable. how can I do that ?
My .htaccess code:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
RewriteBase /tr/
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /tr/index.php [L]
</IfModule>
Try the following before your existing directives (ie. before the <IfModule> section):
# Redirect "/" to "/en/"
RewriteRule ^$ /en/ [R,L]
# Redirect "/demo" to "/us/demo"
RewriteCond %{REQUEST_URI} !^/(en|us)/
RewriteRule (.*) /us/$1 [R,L]
The first rule redirects example.com/ to example.comn/en/. The second rule redirects everything else to /us/<url>, providing the URL-path does not already start /en/ or /us/.
If you also need to make an exception for your static assets... eg. Should a request for /assets/images/img.png also be redirected? Then include an additional condition (as the 2nd condition) on the second rule:
# Redirect "/demo" to "/us/demo" (and exclude static assets)
RewriteCond %{REQUEST_URI} !^/(en|us)/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule (.*) /us/$1 [R,L]
Note that these are 302 (temporary) redirects.

.htaccess 301 redirect with exclusion does not work

I try to use a simple 301 redirect
from domain1.com/folder/ to domain2.com/
but excluding domain1.com/folder/subfolder
I use the following code in .htaccess:
RedirectMatch 301 ^/folder/((?!subfolder).*)$ https://domain2.com/$1
but it simply redirects all the requests, including the requests to subfolder.
Please, help to fix the line to make it work as described. Thank you!
here is the complete code of .htaccess
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /folder/
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /folder/index.php [L]
</IfModule>
RedirectMatch 301 ^/folder/((?!subfolder).*)$ https://domain2.com/$1
Try it like this using mod_rewrite instead:
(NB: This assumes the .htaccess file is located in the document root.)
# /.htaccess
# Redirect all direct requests, except "subfolder"
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteCond $1 !^subfolder($|/)
RewriteRule ^folder/(.*) https://domain2.com/$1 [R=301,L]
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /folder/
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /folder/index.php [L]
</IfModule>
It is important that the redirect goes before the rewrite to your front-controller.
You will need to ensure your browser cache is cleared before testing and test with a 302 (temporary) redirect to avoid potential caching issues.
UPDATE:
Yes, /folder has it's own .htaccess (this is the file I am working at all this time). Yes, /folder is where Wordpress is installed.
In that case you would need to change the above redirect to read as follows (it won't do anything otherwise):
# /folder/.htaccess
# Redirect all direct requests, except "subfolder"
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteCond $1 !^subfolder($|/)
RewriteRule (.*) https://domain2.com/$1 [R=301,L]
Basically, you need to remove folder/ from the start of the regex that matches the URL-path. The URL-path that the RewriteRule pattern matches against is relative to the directory that contains the .htaccess file.
The addition of the check against the REDIRECT_STATUS env var is to ensure that rewritten requests to the WP front-controller (when subfolder is requested) are not redirected.
You can also "simplify" the WordPress directives that follow (although if these are enclosed in # BEGIN WordPress / # END WordPress comment markers then you should leave the directives as they are since they are maintained by WordPress). For example:
RewriteEngine On
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . index.php [L]
The RewriteBase directive is not required. And neither is the <IfModule> wrapper. (But as I said above, only change this if you are hand-coding the .htaccess and not letting WordPress maintain it.)

Creating .htaccess for Vue.js website with prerendering

I have .htaccess file with content below (it's slightly modified example from vue-router documentation):
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.html$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.html [L]
RewriteCond %{HTTP_HOST} ^www.example.com$
RewriteRule ^(.*)$ http://example.com/$1 [R=301,L]
</IfModule>
I want to:
redirect from www. to non-www (this is in in the above code and works)
add a rule to remove trailing slashes (so, a server should redirect from http://example.com/ to http://example.com)
redirect URLs like http://example.com/? to http://example.com
I tried to remove trailing slashes by:
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)/$ /$1 [L,R=301]
But server falls into redirect loop (301 to 302, 302 to 301, and so on) and I don't have any idea how to fix this.
The website is based on Vue.js with prerendering, so if it has http://example.com/contact page, the server should render file from /contact/index.html directory.

.htaccess extensionless url and 301 redirect loop

I have spent count-less hours trying to develop a good .htaccess to offer extensionless urls for SEO purposes. Almost every modern website I see has extensionless URL's and being a fairly new site I want to take this approach.
I have been able to successfully convert the site, using .htaccess, to extensionless. For example:
example.com/page.php will become example.com/page1 in the URL
HOWEVER, existing pages that are the same location (such as contact.php page) will do a LOOP when doing a 301 redirect. So, for example, so that a search engine doesn't think /contact.php and /contact are two different pages, the existing indexed /contact.php has a 301 redirect to /contact
However, the /contact url pulls its data from /contact.php behind the scenes and .htaccess knows this and then wants to apply the 301 redirect again to the behind the scenes /contact.php to /contact causing a loop. I cannot figure out how to stop this.
Bottom line is that I want a 301 redirect from /contact.php to /contact with /contact in the URL reflecting the contents of /contact.php physical file.
Here is my .htaccess to works well except for pages that have 301 redirects.
I'm also interested in any other issues you may see in my .htaccess :)
.htaccess
Options -MultiViews
Options +FollowSymLinks
RewriteEngine on
RewriteBase /
## 301 Redirects
# 301 Redirect 1
RewriteCond %{QUERY_STRING} ^$
RewriteRule ^contact\.php$ /contact? [R=301,NE,NC,L]
## Exclude appropriate directories from rewrite rules ^(blogsphere)
RewriteRule ^(blogsphere) - [L]
## Unless directory, remove trailing slash
# If requested URL ending with slash does not resolve to an existing directory
RewriteCond %{REQUEST_FILENAME} !-d
# Externally redirect to remove trailing slash
RewriteRule ^(.+)/$ $1 [QSA,L]
## Redirect external .php requests to extensionless url
# Any type of POST/GET should be a condition so that it doesnt rewrite without that data (end fileames in submissionscript)
RewriteCond %{REQUEST_URI} !^/([a-z-]+)\-(submissionscript)(.*)$
#Request has to end in .php
RewriteCond %{THE_REQUEST} ^(.+)\.php([#?][^\ ]*)?\ HTTP/
RewriteRule ^(.+)\.php$ $1$2 [QSA,L]
## If it is not a directory then internal resolve request to end with .php for extensionless php urls (/page will internally resolve to /page.php)
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^((?!(\.|\.php)).)*$ $0.php [QSA,L]
Have it like this:
Options -MultiViews
Options +FollowSymLinks
RewriteEngine on
RewriteBase /
# skip blogsphere directory for rewrite
RewriteRule ^(blogsphere) - [L]
## Unless directory, remove trailing slash
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{THE_REQUEST} \s(.+?)/+[?\s]
RewriteRule ^(.+?)/$ $1 [R=301,L]
# remove .php extension from URL - external redirect
RewriteCond %{REQUEST_URI} !^/([a-z-]+)-(submissionscript)(.*)$
RewriteCond %{THE_REQUEST} \s/+(?:index)?(.*?)\.php[\s?] [NC]
RewriteRule ^ %1 [R=301,L,NE]
# internally rewrite a file to file.php
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{DOCUMENT_ROOT}/$1.php -f [NC]
RewriteRule ^(.+?)/?$ $1.php [L]

trailing slashes in 301 redirect

I've tried to look through the multiple mod_rewrite questions, so I apologize if this is a duplicate.
I'm trying set it so that if you go to domain.com/about.php it removes .php and if you go to domain.com/about it simply remains like that.
Options +FollowSymlinks
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.+)$ /$1.php [L,QSA]
RewriteRule ^(.*)/$ /$1 [L,R=301]
So, right now if you go to domain.com/about it displays the page, but if you go to domain.com/about.php it doesn't remove the extension.
Additionally, I have 301 redirects
redirect 301 /our-clients http://www.domain.com/about-ourclients
That works perfect, but if the user goes to domain.com/our-clients/ with the trailing slash, they are directed to about-ourclients.php
Any advice on how to rewrite my rules?
This should do the job:
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]
It will redirect all direct requests to php files: /something.php will be redirected to /something
Will remove the trailing slash IF requested resource is not directory. So if you requesting /home/ and you do have such folder, then it will NOT be redirected to /home.
Will internally rewrite requests to the same named PHP file IF it does exist. If you are requesting /about and you have /about.php then it will do rewrite; If you have no /about.php then nothing happens (well, at least not on these rules -- if you have more rules then such request can be matched later .. or 404 error page will be shown).
If you are requesting /about, you have /about.php and you also have /about folder, then request will go into folder. If you do not want this to happen ( /about should always be rewritten to /about.php) then you need to remove RewriteCond %{REQUEST_FILENAME} !-d from last block. But since you have exactly the same condition in your current .htaccess then I assume it is desired behaviour.