How add path to url if the url does not contain substring - apache

I need to redirect all requests from
https://example.com/* to https://example.com/test/* if the URL does not contain the test substring.
So far I have these rewrite rules
RewriteBase /
RewriteCond %{THE_REQUEST} !^/test
RewriteRule ^/?$ /test/$1 [R=301,L] # if the url does not contain test, redirect to url with test
RewriteCond %{THE_REQUEST}% test
RewriteRule ^test?(.*)$ /$1 [L] # mask the fact that the url is not https://example.com/ and instead is https://example.com/test but apache serve the website like if it was on root
If I access https://example.com it redirects to https://example.com/test but gives infinite loop because of the second rule.
How can I combine it, so request to https://example.com/test* do not get redirected but those request at https://example.com/* do without having to change www root directory and so it will work for all URLs.

UPDATE:
The test should be in url (for user experience), but the apache should route like if it was not in url and instead the request came to root url, so application routing is preserved internally without having to change the app itself.
Ah, Ok. However, you should be linking to the /test URLs within your app (so you do still need to "change the app", despite your last comment), otherwise /test isn't actually in the URLs that users and search engines see on the page (they will be redirected) and your users will experience an external redirect every time they click one of your links (bad for SEO and user experience).
The "redirect" implemented in .htaccess to prefix "old" URLs with /test is just for SEO - as with any "old" to "new" URL change. (It should not be required for your app to function - with /test in the URL-path - since your internal URLs should already include /test.)
Try it like this instead:
RewriteEngine On
# Insert "/test" at the start of the URL-path if absent in "direct" requests
RewriteRule %{ENV:REDIRECT_STATUS} ^$
RewriteRule !^test/ /test/$1 [R=301,L]
# Rewrite "/test" URLs back to root
RewriteRule ^test(?:$|/(.*)) /$1 [L]
The REDIRECT_STATUS environment variable is used to prevent a redirect loop. This is empty on the initial request from the client and set to the HTTP response status after the rewrite (below).
Test first with 302 (temporary) redirects and only change to 301 (permanent) when you are sure this is working as intended.
You will need to clear your browser cache before testing.

Related

How to redirect the page after rewrite the URL

I have to rewrite the URL so I have used the below code in my htaccess which is working
RewriteRule ^products/part/pumps/?$ pumps.php [L,NC]
if someone tries to access the url link exmple.com/products/part/pumps/ then it's showing the pumps.php data.
Now my issue is if some try to access the page example.com/pumps.php then how can I redirect to this link exmple.com/products/part/pumps/
I have tried but getting a redirecting error
Redirect 301 /pumps.php /products/part/pumps/
I have many pages and i have to redirect them also. sharing two example here
RewriteRule ^power\.php$ /products/engine/power/ [R=301,L]
RewriteRule ^connecting\.php$ /products/connection/power/connecting/ [R=301,L]
Use the following before your existing rewrite:
# External redirect
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule ^pumps\.php$ /products/part/pumps/ [R=301,L]
(But test first with a 302 redirect to avoid potential caching issues.)
By checking that the REDIRECT_STATUS environment variable is "empty" we can redirect only direct requests from the user and not the rewritten request by the later rewrite. After the request is successfully rewritten, REDIRECT_STATUS has the value 200 (as in 200 OK HTTP status).
The RewriteCond (condtion) directive must precede every RewriteRule directive that triggers an external redirect.
The Redirect directive (part of mod_alias, not mod_rewrite) is processed unconditionally and will end up redirecting the rewritten request, resulting in a redirect loop. You need to use mod_rewrite throughout.
Use the END flag instead of RewriteCond (requires Apache 2.4)
Alternatively, you can modify your existing rewrite to use the END flag (instead of L) to prevent a loop by the rewrite engine. The RewriteCond directive as mentioned above can then be omitted. But note that the END flag is only available on Apache 2.4+.
For example:
# External redirects
RewriteRule ^pumps\.php$ /products/part/pumps/ [R=301,L]
# Internal rewrites
RewriteRule ^products/part/pumps/?$ pumps.php [END,NC]
It is advisable to group all the external redirects together, before the internal rewrites.
Unfortunately, due to the varying nature of these rewrites it doesn't look like the rules can be reduced further.

.htaccess redirect not redirecting

I am trying to Redirect pages to new location on the same website using .htaccess
the physical file name is displayitems.php but there is a rule in .htaccess
RewriteRule ^buy-online-(.*) ./displayitems.php?url=$1
which is to handle the user friends URLs and works well.
Now i want to redirects these user friendly urls to new location which is on the same website for eg.
redirect https://example.com/buy-online-alhabib-rings4-sku-1658906163 https://example.com/products/jewelry/buy-online-alhabib-rings4-sku-1658906163 [R=301]
redirect https://example.com/buy-online-alhabib-rings3-sku-1658906162 https://example.com/products/jewelry/buy-online-alhabib-rings3-sku-1658906162 [R=301]
redirect https://example.com/buy-online-alhabib-rings2-sku-1658906161 https://example.com/products/jewelry/buy-online-alhabib-rings2-sku-1658906161 [R=301]
redirect https://example.com/buy-online-alhabib-rings1-sku-1658906160 https://example.com/products/jewelry/buy-online-alhabib-rings1-sku-1658906160 [R=301]
these user friendly url doesn't have any extensions like ".php" ".htm" etc
but nothing happening.
I have added this code in php file to check if url doesn't contain \products\ than redirect it to new location with the same name, for testing i just redirect it with 302 once all tested i will change it to 301
if (strpos($_SERVER['REQUEST_URI'], "/products/") === false) { $NewAddress = strtolower("Location:". $ini['website_address_https'] . "products/".$Product['categoriesname']."/".$Product['BrandName'].$_SERVER['REQUEST_URI']); header("$NewAddress",TRUE,302); }
redirect https://example.com/buy-online-alhabib-rings4-sku-1658906163 https://example.com/products/jewelry/buy-online-alhabib-rings4-sku-1658906163 [R=301]
There are 3 main issues here:
The mod_alias Redirect directive takes a root-relative URL-path (starting with a slash) as the source URL, not an absolute URL. So the above will never match.
You have mixed syntax with mod_rewrite. [R=301] is a RewriteRule (mod_rewrite) flags argument and has nothing to do with the mod_alias Redirect directive. Redirect takes the HTTP status code as an optional second argument. eg. Redirect 301 /buy-online-alhabib-rings4-sku-1658906163 ...
Since you are using mod_rewrite (ie. RewriteRule) for your internal rewrite, you should use mod_rewrite for external redirects as well to avoid potential conflicts. These redirects then need to go before your internal rewrite.
Additionally,
In the 4 redirects you have posted it looks like you are simply injecting /products/jewelry at the start of the URL-path. This does not need 4 separate rules, providing you are wanting to redirect all URLs that following this particular format.
Try the following instead:
RewriteEngine On
# Inject (redirect) "/product/jewelry" at the start of the URL-path
RewriteRule ^buy-online-alhabib-rings\d-sku-\d+$ /products/jewelry/$0 [R=301,L]
# Internal rewrite
RewriteRule ^buy-online-(.*) displayitems.php?url=$1 [L]
The $0 backreference in the first rule contains the entire URL-path that is matched by the RewriteRule pattern.
Note that I also removed ./ from the start of the substitution string in the last rule. This is unnecessary here.

How do I redirect just my home page and keep rest of the URLs as it is?

I need to redirect some URLs as they are pointing to same page. For example:
https://www.example.com/home
https://www.example.com/Home
https://www.example.com/index.php
These all URLs need to refirect to:
https://www.example.com/
So I am using this in .htaccess file it is working fine :
Redirect 301 /home https://www.example.com/
But the issue is when I try to access the URL like this:
https://www.example.com/home/sub
It redirects to resulting in 404:
https://www.example.com//sub
I need this URL to work as it is instead of 404 or any redirect:
https://www.example.com/home/sub
Redirect 301 /home https://www.example.com/
Because the mod_alias Redirect directive is prefix-matching and everything after the match is copied onto the end of the target URL. So, when you request /home/sub, /sub is copied on to https://www.example.com/, resulting in https://www.example.com//sub.
I imagine you also have mod_rewrite directives. You should avoid mixing redirects from both modules, so try the following instead using mod_rewrite at the top of the root .htaccess file:
RewriteEngine On
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule ^(home|index\.php)$ / [R=301,L]
The condition that checks against the REDIRECT_STATUS environment variable ensures that only direct requests are processed, as opposed to internally rewritten requests which will result from having a front-controller pattern (which I assume you have later in the file).
You will need to clear the browser cache since the erroneous 301 (permanent) redirect will have been cached by the browser. Test with 302s to avoid potential caching issues.
Reference:
https://httpd.apache.org/docs/2.4/mod/mod_alias.html#redirect
https://httpd.apache.org/docs/2.4/mod/mod_rewrite.html#rewriterule

Exclude a URL from folder redirection

I am redirecting all URLs from www.example.com/forums to www.example.com/blog/.
so I made this rule in .htaccess:
RewriteRule ^forums blog/$1 [L,R=301]
the thing is that I want to exclude some URLs that also begin with forums/ and redirect them to particular URL other than /blog.
For example, forums/8/some-made-up-word-here-1681 to /studies/some-made-up-studies.
Right now, it redirects to /blog like all URLs that start with forum/
You just need to include the more specific redirects first, before the more general rule. For example:
RewriteEngine On
# Specific redirects
RewriteRule ^forums/8/some-made-up-word-here-1681 /studies/some-made-up-studies [R,L]
# Redirect all other URLs that start /forums
RewriteRule ^forums/?(.*) /blog/$1 [R,L]
I've also modified your existing directive to redirect /forums/<something> to /blog/<something>, which I assume was perhaps the original intention, since you were using a $1 backreference in the substitution, but did not have a capturing group in the RewriteRule pattern. Your original directive would have redirected /forums/<something> to /blog/.
I've also included a slash prefix on the substitution. This is required for redirects, although you may have set RewriteBase instead, in which case you do not need to do this.
You will need to clear your browser cache before testing, since the earlier catch-all 301 will have been cached hard by the browser. For this reason it is often easier to test with temporary 302s in order to avoid the caching problem. Change the above temporary redirects to 301s only after you have confirmed this is working as intended.
UPDATE: To redirect all URLs that start /forums to /blog/, without copying the remainder of the URL, then change the last directive to read:
# Redirect all other URLs that start /forums
RewriteRule ^forums /blog/ [R,L]
Basically, the $1 in your original directive was superfluous.

redirect exact url to another url

There are a bazillion examples online of doing redirects via apache's htaccess, but I can't find any example of redirecting a full URL match to another full URL.
For instance, I have an existing website at
https://example.com
How do I redirect some specific URLs for that domain to a different one:
https://example.com/login --> https://my.example.com/login
https://example.com/register --> https://my.example.com/register
For every other every other path on example.com I need to remain untouched so my site still works fine (i.e. /blog shouldn't redirect somewhere else).
You can use the following :
RewriteEngine on
RewriteCond %{HTTP_HOST} ^(www\.)?example\.com$ [NC]
RewriteRule ^(login|register)/?$ http://my.example.com/$1 [L,R]
This will redirect example.com/login or example.com/register to http://my.example.com/
You can alternatively accomplish this using the RedirectMatch directive (if the newurl is on a diffrent webserver) :
RedirectMatch ^/(login|register)/?$ http://my.example.com/$1