.htaccess : redirect permanent and stop new rules - .htaccess

I have that rule that works well
RedirectMatch 301 ^/(.*?)-/(.*)$ /$1/$2
It redirects for instance
http://example.com/category-/list/town/id/id2/country ->
http://example.com/category/list/town/id/id2/country
Problem is, later .htaccess adds some extra query parameters.
My goal is: when this rule is matches, then do not apply other .htaccess rules
I tried with:
RewriteRule ^/(.*?)-/(.*)$ /$1/$2 [R=301,L]
and rule is not applied at all !

As #hjpotter92 mentioned in the comments, the pattern is without the leading slash in .htaccess files. See Apache mod_rewrite Technical Details
In per-directory context (i.e., within .htaccess files and Directory blocks), these rules are being applied after a URL has already been translated to a filename. Because of this, the URL-path that mod_rewrite initially compares RewriteRule directives against is the full filesystem path to the translated filename with the current directories path (including a trailing slash) removed from the front.
To illustrate: If rules are in /var/www/foo/.htaccess and a request for /foo/bar/baz is being processed, an expression like ^bar/baz$ would match.
RewriteRule has a similar note in the section "Per-directory Rewrites".
So your rule should look like
RewriteRule ^(.*?)-/(.*)$ /$1/$2 [R,L]
If you have this RewriteRule, you don't need the RedirectMatch anymore.

Related

.htaccess redirect rule only root-domain [duplicate]

I am not a programmer of .htaccess code, I read the other related posts but do not understand them. Non of them do what I need.
I have a Wordpress site that runs on http://example.com/main but want to redirect http://example.com to http://otherexample.com/page.php. Also need that http://example.com/anyfile not be redirected.
Assuming example.com and otherexample.com point to different places then try something like the following in the root .htaccess file at example.com:
RedirectMatch 302 ^/$ http://otherexample.com/page.php
The regex ^/$ matches / only, ie. the root directory.
^ asserts the start-of-string (ie. URL-path)
/ matches a literal slash
$ asserts the end-of-string
UPDATE: I found that secondary.com also is redirected.
If you have multiple domains pointing to the same place and you only want to redirect one of them then you'll need to use mod_rewrite to check the hostname first before redirecting.
For example, the following would need to go at the top of the .htaccess file before the WordPress front-controller:
RewriteCond %{HTTP_HOST} ^(www\.)?example\.com [NC]
RewriteRule ^$ http://otherexample.com/page.php [R=302,L]
Note that the RewriteRule pattern matches against the URL-path less the slash prefix, hence the regex ^$ (different to the RedirectMatch directive), which matches an empty URL-path (ie. the root directory only).

Redirection rule doesn't work in my .htaccess

I broke my head trying to find where the issue is:
I have the following redirection rule:
RewriteRule ^/productname(.*) https://website.com/category [R=301,NC,L]
but it doesn't work and I can't get why. Because this rule:
Redirect 301 ^/productname(.*) https://website.com/category/subcategory/productname
works fine.
Would appreciate any help
RewriteRule ^/productname(.*) https://website.com/category [R=301,NC,L]
That won't work in per-directory .htaccess files because the URL-path matched by the RewriteRule pattern is less the directory-prefix (the filesystem path of where the .htaccess file resides). The directory-prefix always ends in a slash, so the URL-path that is matched by the RewriteRule pattern never starts with a slash.
From the Apache docs for the RewriteRule directive:
In per-directory context (Directory and .htaccess), the Pattern is matched against only a partial path, for example a request of "/app1/index.html" may result in comparison against "app1/index.html" or "index.html" depending on where the RewriteRule is defined.
The directory path where the rule is defined is stripped from the currently mapped filesystem path before comparison (up to and including a trailing slash). The net result of this per-directory prefix stripping is that rules in this context only match against the portion of the currently mapped filesystem path "below" where the rule is defined.
So, you would need to do remove the slash prefix, for example:
RewriteRule ^productname https://website.com/category [R=301,NC,L]
The trailing (.*) on the RewriteRule pattern is superfluous in this example.
Redirect 301 ^/productname(.*) https://website.com/category/subcategory/productname
This rule wouldn't "work fine". I think you mean RedirectMatch.
Note that RewriteRule and Redirect (and RedirectMatch) belong to different modules. mod_rewrite and mod_alias - you should avoid mixing redirects from both modules as you can get unexpected conflicts.

How can I use htaccess to redirect a URL based on it's segments?

I have some old URLs that have since changed. Right now they are going to my 404 page, so I need to redirect them to the new URLs. The original URLs look like this:
http://example.com/en/blog/events-private/name-of-event
The new URLs look like this, without the "blog" segment:
http://example.com/en/events-private/name-of-event
This is what I'm trying but it's not working:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^/en/blog/events-private/(.*) /en/events-private/$1
</IfModule>
What am I missing?
This isn't using mod_rewrite but this seems to work:
RedirectMatch 301 ^/en/blog/events-private/(.*) /en/events-private/$1
RewriteRule ^/en/blog/events-private/(.*) /en/events-private/$1
In .htaccess the RewriteRule pattern matches against the URL-path after the directory-prefix (that leads to the .htaccess file) has first been removed. The directory-prefix always ends in a slash, so the URL-path that is matched here never starts with a slash. In other words, you simply need to remove the slash prefix:
RewriteRule ^en/blog/events-private/(.*) /en/events-private/$1 [R=301,L]
(and don't forget the R and L flags.)
Note that this contrasts the use of mod_rewrite in a server (or virtualhost) context. In this context you do need the slash prefix! Because in a server context, the pattern matches against the full URL-path.
Also, the RewriteBase directive in this example is superfluous (since you aren't using a relative substitution). And the <IfModule mod_rewrite.c> wrapper should probably be removed (unless this is intended to function on systems without mod_rewrite).

.htaccess redirect all subfolders to specific path

I have multiple sites (subdirectories). I want to redirect all URLs of the format /(*)/login to /other/login.
I have tried:
RewriteRule ^/(.*)/login /other/login
#and
^(.*)/login /other/login
I've also tried Redirect.
Additionally, I notice that some subfolders have their own .htaccess files also. Do I need to put the redirect rule in the subfolder's .htaccess file? There surely must be a more efficient way.
I notice some subfolder have their own .htaccess files also, do I need to put the redirect rule in the subfolder .htaccess files?
Any mod_rewrite directives in child .htaccess files will, by default, completely override the mod_rewrite directives in any parent .htaccess file, they are not inherited. However, you can change this behaviour. On Apache 2.2 this is quite limited as you would need to change the child .htaccess file anyway, so it would probably be easier to simply duplicate this directive in the child config. But on Apache 2.4.8+ you can do all this in the parent .htaccess file. For example:
RewriteEngine On
RewriteOptions InheritDownBefore
RewriteCond %{REQUEST_URI} !^/other
RewriteRule ^[^/]+/login$ /other/login [R=302,L]
The InheritDownBefore option results in the current mod_rewrite directives being applied before the mod_rewrite directives in any child configs.
The RewriteCond directive is required in order to prevent a redirect loop (if the /other subdirectory does not have its own .htaccess file containing mod_rewrite directives).
This is an external "redirect" (as stated in your question). The URL changes in the browser's address bar. You can possibly change this to an internal rewrite (as your current directive implies) by removing the R flag (although this may depend on your application).
If you simply want a "redirect" then you could probably use a mod_alias RedirectMatch directive instead of the above mod_rewrite directives. This runs separately to mod_rewrite, but note that any mod_rewrite directives (in child configs) are processed first. For example:
RedirectMatch 302 ^/(?!other)[^/]+/login$ /other/login
The RedirectMatch directive uses a regex, whereas Redirect (also mod_alias) uses simple prefix matching. So, you couldn't match this specific pattern using a simply Redirect.
The (?!other) part is a negative lookahead (zero-width assertion) that checks that the URL-path being matched does not start other - in order to avoid a redirect loop.
Note also that RewriteRule does not use the slash prefix on the URL-path, whereas, RedirectMatch does. And there is no need to capture the URL-path (ie. by enclosing the regex in parentheses) if this is not required.
I have try several variants (you can see marked lines, that doesn't works),
my .htaccess:
#AddType application/x-httpd-php .html .htm
RewriteEngine on
RewriteRule ^(.*)$ index.php?path=$1 [NC,L,QSA]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
#RewriteRule ^([^/]*)+^(.*)$ index.php?dir=$1&path=$2 [NC,L,QSA]
#RewriteRule ^(.*)$ index.php?path=$1 [NC,L,QSA]
#FallbackResource index.php
It works with all urls: /, /index, /index.html, /main/main.html.
Then echo var_dumps($_GET); gives:
array(1) { ["path"]=> string(10) "index.html" }
Now all requests goes into index.php.

Redirect All Unused Link on a subdomain to a domain

I want to redirect all the unused link in my subdomain.olddomain.com to newdomain.com
i tried this but it doesn't seem to work for subdomain
RewriteCond %{HTTP_HOST} !^subdomain\.olddomain\.com [NC]
RewriteRule ^/(.*) http://www.newdomain.com/$1 [L,R=301]
I manage to make the code below but the issue is it does not redirect or catch all the unused like. It only redirects the root and returns page error when accessing unused link(e.g. tag) An example url look like below (OsCommerce)
sub.domain.com/product_info.php?products_id=999&osCsid=29f8a9504d1c4de90a1a1e4106344280
RewriteCond %{HTTP_HOST} !^www\.newdomain\.com$ [NC]
RewriteRule ^(.*)$ http://www.newdomain.com/$1 [R=301,L]
Additional Info:
What I am trying to do is redirect all the link coming from subdomain.olddomain.com to newdomain.com so for example when someone visit subdomain.olddomain.com/tags/vanilla or subdomain.olddomain.com/product_info.php?products_id=999&osCsid=29f8a9504d1c4de90a1a1e4106344280m they will automatically be redirected to newdomain.com , the newdomain.com is located in another server server
From the documentation (emphasis mine):
Per-directory Rewrites
The rewrite engine may be used in .htaccess files and in sections, with some additional complexity.
To enable the rewrite engine in this context, you need to set "RewriteEngine On" and "Options FollowSymLinks" must be enabled. If
your administrator has disabled override of FollowSymLinks for a
user's directory, then you cannot use the rewrite engine. This
restriction is required for security reasons.
When using the rewrite engine in .htaccess files the per-directory prefix (which always is the same for a specific directory) is
automatically removed for the RewriteRule pattern matching and
automatically added after any relative (not starting with a slash or
protocol name) substitution encounters the end of a rule set. See the
RewriteBase directive for more information regarding what prefix will
be added back to relative substitutions.
If you wish to match against the full URL-path in a per-directory (htaccess) RewriteRule, use the %{REQUEST_URI} variable in a
RewriteCond.
The removed prefix always ends with a slash, meaning the matching occurs against a string which never has a leading slash. Therefore, a
Pattern with ^/ never matches in per-directory context.
Although rewrite rules are syntactically permitted in and sections (including their regular expression counterparts),
this should never be necessary and is unsupported. A likely feature to
break in these contexts is relative substitutions.
The .htaccess-file is per-directory context, so your rule will never ever match anything. Your rule should look like:
RewriteCond %{HTTP_HOST} !^subdomain\.olddomain\.com [NC]
RewriteRule ^(.*)$ http://www.newdomain.com/$1 [L,R=301]
This is assuming that newdomain.com does not use this .htaccess file, as that would cause an infinite redirect.

Resources