Strange RewriteRule causes errors - .htaccess

I use PrestaShop on Litespeed server, here is a part of .htaccess of admin panel:
# Keep legacy entry points
RewriteRule ^(ajax|ajax_products_list|ajax-tab|backup|cron_currency_rates)\.php - [P]
RewriteRule ^(displayImage|drawer|footer\.inc|functions|get-file-admin)\.php - [P]
RewriteRule ^(grider|header\.inc|init|login|password|pdf|searchcron)\.php - [P]
# If the URL is a legacy on index.php?controller=..., do not rewrite (let the legacy take it)
RewriteCond %{QUERY_STRING} (^|&)controller=|(^|&)tab=
RewriteRule .* - [P]
I see many logs regarding those:
2021-10-30 16:01:17.163186 WARN [225891] [T0] [REWRITE] Detects bad proxy action without updating target URL. Ignore. while parsing: RewriteRule ^(ajax|ajax_products_list|ajax-tab|backup|cron_currency_rates)\.php - [P]
2021-10-30 16:01:17.163218 WARN [225891] [T0] [REWRITE] Detects bad proxy action without updating target URL. Ignore. while parsing: RewriteRule ^(displayImage|drawer|footer\.inc|functions|get-file-admin)\.php - [P]
2021-10-30 16:01:17.163228 WARN [225891] [T0] [REWRITE] Detects bad proxy action without updating target URL. Ignore. while parsing: RewriteRule ^(grider|header\.inc|init|login|password|pdf|searchcron)\.php - [P]
2021-10-30 16:01:17.163243 WARN [225891] [T0] [REWRITE] Detects bad proxy action without updating target URL. Ignore. while parsing: RewriteRule .* - [P]
2021-10-30 16:01:17.581695 WARN [225890] [T0] [REWRITE] Detects bad proxy action without updating target URL. Ignore. while parsing: RewriteRule .* - [P]
Can anyone describe what are those RewriteRules and why I get those errors?
Thanks!

The use of the P flag is clearly an error in this context. I would have said it was a typo, was it not on every rule! They probably meant to use PT (passthrough), although L (last) (or END) would be preferable.
The purpose of these directives is to prevent further processing (ie. other rewrites from occurring) of these particular "legacy" URLs.
Change [P] to [L] on all 4 of these rules to resolve this.
For example:
RewriteRule ^ - [L]
(Also changing .* to ^ on the last rule, since it doesn't need to actually match everything, it just needs to be successful for everything.)

Related

Why is there a error 500 on a Subdomain to folder

This is what's inside the .htaccess file:
RewriteEngine on
RewriteCond %{HTTP_HOST} ^(.*)\.domain\.com
RewriteRule ^(.*)$ Subdomains/%1/$1 [L,NC,QSA]
When I'm on the domain (eg: x.example.com), it displays error 500. What am I doing wrong?
Example:
x.example.com -> show example.com/Subdomains/x but keep the URL of x.example.com
y.example.com -> show example.com/Subdomains/y but keep the URL of y.example.com
z.example.com -> show example.com/Subdomains/z but keep the URL of z.example.com
RewriteCond %{HTTP_HOST} ^(.*)\.example\.com
RewriteRule ^(.*)$ Subdomains/%1/$1 [L,NC,QSA]
Without any other directives to prevent it, the above will result in an internal rewrite loop, which will result in a 500 Internal Server Error response to the browser.
For example, if you request https://sub.example.com/foo then...
Request is rewritten to /Subdomains/sub/foo.
In a directory context (ie. htaccess) the rewriting process starts over, passing /Subdomains/sub/foo as in the input to the next round of processing...
Request is rewritten to /Subdomains/sub/Subdomains/sub/foo.
The rewriting process starts over...
Request is rewritten to /Subdomains/sub/Subdomains/sub/Subdomains/sub/foo.
The rewriting process starts over...
etc. until the server gives up. (Default is after 10 internal rewrites.)
The L flag does not stop all processing in a directory context (ie. htaccess). It simply stops the current round of processing. The rewrite process continues until the URL passes through unchanged.
The quick fix on Apache 2.4 is to simply replace the L flag with END. This causes all processing to stop. No further passes through the rewrite engine occur.
For example:
RewriteCond %{HTTP_HOST} ^(.*)\.example\.com
RewriteRule (.*) Subdomains/%1/$1 [END]
The NC and QSA flags are superfluous here.
Note that the regex ^(.*)\.example\.com matches any number of sub-subdomains, including www itself, if that is a concern?
Without using the END flag (Apache 2.4) then you would need to explicitly check that you have not already rewritten the URL. One way is to prevent any further rewrites if /Subdomains/.... has already been requested:
RewriteCond %{HTTP_HOST} ^(.*)\.example\.com
RewriteRule ^((?!Subdomains/).*)$ Subdomains/%1/$1 [L]
Note that if you have another .htaccess file located in the /Subdomains/<sub> subdirectory that also uses mod_rewrite then this will have also prevented a rewrite loop since mod_rewrite directives are not inherited by default.
UPDATE: Is there a way to check if the folder dosent exist then just redirect to domain.com?
Yes, you can do this, for example:
# If subdomain does not map to a subdirectory then redirect to root of main domain
RewriteCond %{HTTP_HOST} ^(.*)\.(example\.com)
RewriteCond %{DOCUMENT_ROOT}/Subdomains/%1 !-d
RewriteRule ^ https://%2/ [R=302,L]
# Otherwise, internally rewrite the request to subdirectory (if not already)
RewriteCond %{HTTP_HOST} ^(.*)\.example\.com
RewriteRule ^((?!Subdomains/).*)$ Subdomains/%1/$1 [L]
However, this is arguably detrimental to your users. A custom 404 response might be preferable.

RewriteRule not working without R flag

I need this URL :
http://example.net/aroundtheshows/get?id=123
to be rewritten (not redirected) to :
http://example.net/ats/get?id=123
so I added the following RewriteRule in my htaccess :
RewriteCond %{REQUEST_URI} ^\/aroundtheshows
RewriteRule ^aroundtheshows(.*)?$ ats$1 [L]
But it does not work, I get a 404.
However if I had the R=301 flag, the redirection works properly (though that's not what I want, but it means the match is correct).
thanks !
If I understand you correctly you are looking to visit
http://example.net/ats/get?id=123 and have it masked as that URL while serving content from http://example.net/aroundtheshows/get?id=123?
In that case simply inverse your rule - no need for the RewriteCond:
RewriteRule ^ats(.*) aroundtheshows$1 [L]
Demo here: http://htaccess.mwl.be?share=1392f5a6-c631-5e90-9ef5-6622644ed517

When to use [L] flag in mod_rewrite

Can someone give me an example when to use [L] flag? I'm learning about mod_rewrite moudle in .htaccess file and can't find out when to this flag.
The L flag simply means to stop applying any rules that follow. Given the same URL, http://example.com/foo/bar?q=blah, and given the rules:
RewriteRule ^foo -
RewriteCond %{REQUEST_URI} !^/bar.php
RewriteRule ^(.*)$ /bar.php?z=$1
The first rule gets applied and the URI gets passed through unchanged (via the - target). The rewrite engine then processes the next rule, and the URI gets rewritten to /bar.php?z=foo/bar. What happens when you add an L to the end:
RewriteRule ^foo - [L]
RewriteCond %{REQUEST_URI} !^/bar.php
RewriteRule ^(.*)$ /bar.php?z=$1
The URL http://example.com/foo/bar gets passed through untouched from the first rule, then stops because of the L flag. If the URL is http://example.com/something/else then the first rule doesn't match and the second rule gets applied, rewriting the URI to: /bar.php?z=something/else
Note that since the rewrite engine loops through all the rules until the URI stops changing, the L flag will not prevent the looping, only any further rules from getting applied in the current iteration.

.htaccess rewrite rule handled correctly

I want to redirect rewrite /zp-core/admin.php to admin but somehow I can't get it to work.
I've added this rule to my htaccess:
RewriteEngine On
RewriteBase /
RewriteRule ^/admin$ /zp-core/admin.php [L]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^albums/?(.+/?)?$ $1 [R=301,L]
...
# Catch-all - everything else gets handled in PHP for compatibility.
RewriteRule ^(.*)/?$ index.php?album=$1 [L,QSA]
The third rule should do it, but somehow it doesn't. In the end it falls back on the catch all rule
When you say "rewrite A to B", usually, "A" is what the user types and "B" is where you want him to get.
If A='/admin' and B='/zp-core/admin.php' then the first rule is ok, if you remove other rules, it will work.
The problem is - apache looks into .htaccess on every request, including sub-requests, and your redirect does a sub-request... So it does not match the first rule anymore, but then comes the catch-all rule, and it is a match again (you'll see that $_GET["album"] will be /zp-core/admin.php when hitting index.php on such request.
What you need to do is to add RewriteCond either checking that the uri is not /zp-core/admin.php OR that you're not in sub-request...
Either:
RewriteCond %{REQUEST_URI} !^/zp-core/admin.php$
OR:
RewriteCond %{IS_SUBREQ} !=true

.htacces RewriteRule server error 500

I have this
RewriteRule ^(.*) public/$1 [NC,L]
in my .htacces file and i get Internal Server Error 500
Can someone help me?
And explain why do i get it.
Because you wrote your rules in such way that they create infinite rewrite loop which Apache has to break at some point, hence the 500 Internal Server Error. If you check your error log you will see exact error message.
The [L] flag does not necessary mean "rewrite done" -- it just means "rewrite done on this iteration -- lets go again from start".
Very useful to read: RewriteRule Last [L] flag not working?
To solve your problem -- you need to add some condition so that already rewritten rules are not get rewritten again and again. These rules should do the job for you (one of the possible solutions -- it all depends on how your actual project is set up):
RewriteEngine on
RewriteBase /
RewriteCond %{REQUEST_URI} !^/public/
RewriteRule ^(.*)$ public/$1 [L]
With this rule if URL is already rewritten or starts with /public/ straight away then no additional rewrite will occur.

Resources