.htaccess redirect not redirecting - apache

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.

Related

.htaccess 301 redirect whole URL including Domain

I need to redirect around 300 URLs on a multidomain site that has the same URL structure on the different domains. For example:
https://www.example.com/de/products.html needs to be redirected to https://www.example.org/de/products.html
So my usual approach does not work:
RedirectMatch 301 /de/products.html$ /de/products.html
I would need something like
RedirectMatch 301 https://www.example.com/de/products.html$ https://www.example.org/de/products.html
which obviously doesn't work or I just didn't get to work.
Not sure if important, but it's a TYPO3 instance.
The mod_alias RedirectMatch directive matches against the URL-path only. To match the hostname you'll need to use mod_rewrite with an additional condition (RewriteCond directive) that checks against the HTTP_HOST server variable (the value of the Host HTTP request header).
Also, since the URL structure is the same on both domains then you only need a single rule - just use the same URL-path from the initial request. No need to do one-by-one redirects as you seem to be trying to do.
For example, the following would need to go at the top of the .htaccess file before any existing rewrites:
RewriteEngine On
# Redirect everything from example.com to example.org and preserve the URL-path
RewriteCond %{HTTP_HOST} ^(www\.)?example\.com [NC]
RewriteRule ^ https://www.example.org%{REQUEST_URI} [R=301,L]
This checks for both example.com and www.example.com.
The REQUEST_URI server variable already contains a slash prefix, hence it is omitted in the substitution string.
Test first with a 302 (temporary) redirect to avoid potential caching issues.
UPDATE:
But I don't want to redirect all URLs, just some.
To redirect a specific URL to the same URL at the target domain, as per your original example:
# Redirect "/de/product.html" only
RewriteCond %{HTTP_HOST} ^(www\.)?example\.com [NC]
RewriteRule ^de/products\.html$ https://www.example.org/$0 [R=301,L]
The above redirects https://www.example.com/de/products.html only to https://www.example.org/de/products.html.
The $0 backreference contains the entire URL-path that the RewriteRule pattern matches against.
How to extend your snippet with /de/ or /fr/ etc.? For example I want to redirect example.com/de/products.html but not example.com/products.html
Maybe the above example is what you require. Alternatively, to redirect /de/<something> (or /fr/<something>) only and not just /<something>, you could do something like this:
# Redirect "/<lang>/<something>" only, where <lang> is "de" or "fr"
RewriteCond %{HTTP_HOST} ^(www\.)?example\.com [NC]
RewriteRule ^(de|fr)/[^/]+$ https://www.example.org/$0 [R=301,L]
The above will redirect https://example.com/de/<something> to https://www.example.org/de/<something>.

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

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.

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.

How to rewrite url and redirect with apache mod rewrite?

I have got url:
ipaddress/panelname/main/index.php
How to rebuild it to
ipaddress/center/index.php
?
ofcourse we can see another pages, not only index.php, but this folders in url we can see forever.
I tryed to do this in .htaccess:
RewriteEngine on
RewriteRule ^center/([^/]+)/?$ panelname/main/$1 [L]
RewriteRule ^/panelname(.*)$ /center$1 [QSA,L,R=301,NC]
Redirect 301 ^/panelname(.*)$ /center$1
but i don't see redirect from panelname to center.
but if i type center all works good (but i don't shure, that it works good by my htaccess or by symlink, which i was created in filesystem)
How to rewrite all to another links and howto see redirect from old links to my new? Thank you.
RewriteRule in directory context (which .htaccess is), does never begin with a slash, because the common prefix is stripped from the matched portion first.
Redirect does match strings, not regex'es. The variant that works on a regex is RedirectMatch. Both only work on absolute URL's (the one beginning with a slash).
You either have to do the following:
RewriteRule ^panelname(.*)$ /center$1 [R,L]
or:
RedirectMatch 302 ^/panelname(.*)$ /center$1
Change [R] to [R=301] once you have tested that EVERYTHING works. If you choose the second option, only change 302 to 301 after testing that everything works.
If you want to show /center/index.php to your visitors and keep a redirect from old URL to this URL then you will need one redirect and one rewrite rule (that you already have).
RewriteEngine on
# external redirect from old URL to new one
RewriteCond %{THE_REQUEST} /panelname/main/(\S+) [NC]
RewriteRule ^ /center/%1 [R=302,L]
# internal forward from new URL to actual one
RewriteRule ^center/([^/]+)/?$ panelname/main/$1 [L]

Mod Rewrite -- redirect all content from subdirectory

I have a scenario where there is a a site with subdirectories and content etc originally in a subdirectory /main
The site and all content has been moved back to the root and is working fine
We need to rewrite so that any http call to /main/, /main/page1, /main/page2 etc is redirected back to the / directory but the uri /page1, /page2 etc
This is what we have so far
RewriteCond %{REQUEST_URI} ^/main/.*
RewriteRule ^/main/(.*) /$1 [L]
Any comments welcome
Thanks very much
In .htaccess context, the url that is matched in the first parameter of RewriteRule doesn't include a leading slash and doesn't include the query string. Having a leading slash will cause the rule to never match. In your case your RewriteCond is unnecessary, as it matches exactly what the RewriteRule would match. Change your rule to the following url and it should work. Please note that this is an internal rewrite (the client won't see this change). If you need a redirect (the client will display the url without main in the address bar), add the [R] flag to the rule.
RewriteRule ^main/(.*)$ $1 [L]
See the documentation.