Whenever there is a request like this to the server
https://%{HTTP_HOST}/app/accounturi/services
I want to redirect it to
https://%{HTTP_HOST}/appLegacy/accounturi/services
here accounturi
will be a dynamic one. I'm trying this in apache2.
I tried the below and stuck on the RewriteRule.
RewriteEngine On
RewriteCond %{REQUEST_URI} ^/(.*)services/?$ [NC]
RewriteRule ^(.*)$ https://%{HTTP_HOST}/appLegacy/
Hey, I'm sorry that I messed up with my question. I need to rewrite not redirect.
So the user should still be able to see
https://%{HTTP_HOST}/app/accounturi/services
but the request should take the response from
https://%{HTTP_HOST}/appLegacy/accounturi/services
Please help with this. I'm directly writing this in the apache2 default configuration under
<VirtualHost *:443>
I already enabled HTTPS to redirect in below <VirtualHost *:80>
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}
RewriteCond %{REQUEST_URI} ^/(.*)services/?$ [NC] RewriteRule ^(.*)$ https://%{HTTP_HOST}/appLegacy/
This would 302 (temporary) redirect any URL that ends with services
or services/
to https://<hostname>/appLegacy/
, losing the trailing <accounturi>/services
part.
You are also failing to check for /app
at the start of the URL-path? (Which makes me think your .htaccess
file is inside the /app
subdirectory? But there is nothing else to suggest that.)
If the .htaccess
file is located inside the /app
subdirectory then the rule should be like this instead:
RewriteRule ^([^/]+/services)/?$ /appLegacy/$1 [R=302,L]
I'm assuming the dynamic accounturi
part of the URL-path consists of a single path-segment (as in your example).
The preceding RewriteCond
directive is not required. The $1
backreference contains the URL-path as captured from the RewriteRule
pattern (this excludes any optional trailing slash that might be present on the request). Note that since the .htaccess
file is inside the /app
subdirectory, this is excluded from the URL-path that is captured.
You don't need to specify an absolute URL as the target since you appear to redirecting to the same host. However, you might choose to include this in order to enforce HTTPS.
If, however, the .htaccess
file is in the document root then the directive would need to be like this instead and explicitly check for the /app
subdirectory:
RewriteRule ^app/([^/]+/services)/?$ /appLegacy/$1 [R=302,L]
UPDATE#1:
I want to rewrite not redirect . and I'm directly mentioning this in the default configuration page
If this rule is being used directly inside the <VirtualHost: *:443>
(as per your update) then you would need to adjust the rule as follows:
RewriteRule ^/app/([^/]+/services)/?$ /appLegacy/$1 [L]
Note the slash prefix on the RewriteRule
pattern, since in a virtualhost context the RewriteRule
pattern matches the full root-relative URL-path. And the removal of the R
flag.
This internally rewrites the request, as opposed to redirecting.
Aside:
I already enabled HTTPS to redirect in below <VirtualHost *:80>
RewriteEngine On RewriteCond %{HTTPS} off RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}
You don't need to use mod_rewrite here. A simple mod_alias Redirect
would suffice and be more efficient. And this should be a 301 (permanent) redirect, not a 302 (temporary) which this will default to. For example:
Redirect 301 / https://example.com/
You would, however, need to hardcode the canonical hostname in the rule.
UPDATE#2:
sometimes we don't pass 'accounturi' with the URL, so in that case it should rewrite to
https://%{HTTP_HOST}/appLegacy/services
So theaccounturi
is an optional one.
To make the accounturi
(2nd path segment) optional then change the rule like this:
RewriteRule ^/app/(([^/]+/)?services)/?$ /appLegacy/$1 [L]
It basically makes the [^/]+/
part (2nd path segment) optional, by surrounding it in parentheses followed by ?
. Only the entire path segment is optional, not just the delimiting /
(slash).
Aside: This also allows an optional trailing slash (carried over from the initial "redirect" above). Since this is now a rewrite, the optional trailing slash should probably be removed if it's not required since it potentially promotes duplicate content (two different URLs returning the same resource). If you did need to allow URLs with and without a trailing slash then an additional rule should be added (before the rewrite) that redirects from one to the other (the canonical URL).
tried the below. Seems it's working fine.
RewriteRule ^/app/((.*)+/?services)/?$ /appLegacy/$1 [L]
This "works" (kind of) but has a couple of big flaws:
Very inefficient. The use of the (.*)+
subpattern doesn't make much sense (one or more of potentially nothing). The (unnecessary) capturing subgroup does not actually capture anything and makes the regex very inefficient as it results in an enormous amount of backtracking. This regex is the same as ^/app/(.*/?services)/?$
, which is more efficient. But...
Matches too much. By simply making the /
(before services
) optional this potentially matches far too much, since it matches /app/<anything>services
, which includes URLs like /app/foo/bar/bazservices
(note the multiple path segments and no slash before services
).