Hotlink protection excluding a particular URL - .htaccess

We have tried adding the below hotlink protection inorder to save the bandwidth.
RewriteEngine on
RewriteCond %{HTTP_REFERER} !^https://(www\.)?domain [NC]
RewriteCond %{HTTP_REFERER} !^https://(www\.)?domain.*$ [NC]
RewriteRule \.(gif|GIF|jpg|JPG|PNG|png|jpeg|JPEG|mp4|MP4|mkv|MKV|webm|WEBM|ico|ICO)$ - [F]
This is working perfectly. Now, we want to exclude hotlink protection for the URL admin/thumbs (domain.tld/admin/thumbs/image.jpg) should be excluded from the hotlink protection.
We tried adding the below code however its not working. We searched on stackoverflow and multiple forums however none were helped us.
RewriteEngine on
RewriteCond %{HTTP_REFERER} !^https://(www\.)?domain [NC]
RewriteCond %{HTTP_REFERER} !^https://(www\.)?domain.*$ [NC]
RewriteCond %{REQUEST_URI} !/admin/thumbs$
RewriteRule \.(gif|GIF|jpg|JPG|PNG|png|jpeg|JPEG|mp4|MP4|mkv|MKV|webm|WEBM|ico|ICO)$ - [F]
Any help would be appreciated.

RewriteCond %{REQUEST_URI} !/admin/thumbs$
This creates an exception for any URL that ends with /admin/thumbs, whereas it would seem you want to create an exception for any file in the /admin/thumbs subirectory, ie. any URL that starts /admin/thumbs.
The suggestion !^admin/thumbs/? in comments is incorrect, since the REQUEST_URI server variable always starts with a slash so the condition will always be successful and the request is potentially blocked.
You should use the CondPattern !^/admin/thumbs($|/) instead to exclude requests for /admin/thumbs, /admin/thumbs/ and /admin/thumbs/<anything>, but not /admin/thumbsomething. For example:
RewriteCond %{REQUEST_URI} !^/admin/thumbs($|/)
Your existing rule can be further simplified/refined since the existing conditions that check the HTTP_REFERER are "the same", but also match too much. And the mixed case RewriteRule pattern can be flattened by using the NC (nocase) flag instead.
For example, the complete rule would become:
# Hotlink protection for images, except those in "/admin/thumbs/..."
RewriteCond %{HTTP_REFERER} !^https://(www\.)?example\.com($|/) [NC]
RewriteCond %{REQUEST_URI} !^/admin/thumbs($|/)
RewriteRule \.(gif|jpg|png|jpeg|mp4|mkv|webm|ico)$ - [NC,F]
Note that this also blocks an empty Referer header. This includes direct requests (anyone typing the URL directly into the browser's address bar) and any user that has suppressed the Referer in their browser (which some users do for increased privacy).
Alternative solution with additional .htaccess file
Alternatively, you could create an additional .htaccess in the /admin/thumbs/ subdirectory and simply disable the rewrite engine. For example:
RewriteEngine Off
This overrides and prevents the hotlink-protection directives in the parent config from being processed when anything within this subdirectory is requested.

Related

A .htaccess redirect while editing the query string

I am trying to redirect to a new domain, while keeping the query string but in a modified way.
For example, I want to redirect:
http://guides.freshstoreinstant.com/fresh-store-instant/how-to-find-your-amazon-affiliate-key-secret-key
to
https://guides.freshlabs.group/search?query=how+to+find+your+amazon+affiliate+key+secret+key
So I am wanting to:
Take the last "folder" from the original URL (how-to-find-your-amazon-affiliate-key-secret-key)
Replace - with +
Append the result to https://guides.freshlabs.group/search?query= and redirect with 301
I tried a few things and know a little bit about .htaccess but this one has me stumped
UPDATE
This could be easier using a combination of .htaccess and PHP. Can I use .htaccess to rewrite all URLs to index.php, then use PHP to replace the characters and redirect?
You can do this using mod_rewrite in .htaccess. Try the following at the top of your .htaccess file:
RewriteEngine On
RewriteRule ^(fresh-store-instant)/([^/]*)-([^/]*)$ $1/$2+$3 [N]
RewriteRule ^fresh-store-instant/([^/]+)$ https://guides.freshlabs.group/search?query=$1 [R=302,L]
The first rule repeatedly rewrites the request (internally) replacing all - (hyphens) with + in the second path segment. The N (next) flag explicitly triggers the rewriting loop. This should be used with caution; as with any recursive-like behaviour, it needs to fail at some point. (NB: A + in the URL-path is simply a literal +.)
Once all the hyphens have been replaced, the second rule triggers an external redirect to the other domain, copying the second path segment (now containing +) to the query string in the target URL. (NB: A + in the query string part of the URL is seen as an encoded space by the receiving server.)
Note that this is a temporary (302) redirect. Only change to a 301 (permanent) once you have confirmed it works OK - to avoid caching issues.
Clear your browser cache before testing.
...while keeping the query string but in a modified way
There is no query string on your example source URL to "keep"? Note that the above redirect overwrites any query string that might be present on the source URL. Include the QSA on the second RewriteRule if you want to "append" the query string from the request.
UPDATE:
the first "folder" can vary (e.g. http://guides.freshstoreinstant.com/fresh-store-builder/...)
If there is a limited subset of folders then it will probably be better to explicitly name each one, in order to avoid potential conflicts with other URLs on your site. For example:
RewriteRule ^(fresh-store-(?:instant|builder))/([^/]*)-([^/]*)$ $1/$2+$3 [N]
RewriteRule ^fresh-store-(?:instant|builder)/([^/]+)$ https://guides.freshlabs.group/search?query=$1 [R=302,L]
If you make the initial directory entirely variable (such as below) then I can imagine this conflicting with existing URLs:
RewriteRule ^([\w-]+)/([^/]*)-([^/]*)$ $1/$2+$3 [N]
RewriteRule ^([\w-]+)/([^/]+)$ https://guides.freshlabs.group/search?query=$1 [R=302,L]
This is not possible using apache's rewrite module it does not support such search&replace actions. It only rewrites. If you really cannot live with the unaltered string which you probably could still split in your processing logic, then you have these options:
either introduce another rewriting layer, based on some scripting engine which accepts the unaltered string, converts it by means of normal string operations and output redirection headers
or you may be able to do something with apache's substitute module, but youneed to install and load that and it's usage is not exactly easy (did that, grumbled a lot...)
or use a strange looking but working workaround:
RewriteEngine on
RewriteCond %{HTTP_HOST} ^guides\.freshstoreinstant\.com$
RewriteRule ^/?fresh-store-instant/([^/-]*)-([^/-]*)-([^/-]*)-([^/-]*)-([^/-]*)-([^/-]*)-([^/-]*)-([^/-]*)-([^/-]*)/?$ https://guides.freshlabs.group/search?query=$1+$2+$3+$4+$5+$6+$7+$8+$9 [R=301,QSA]
RewriteCond %{HTTP_HOST} ^guides\.freshstoreinstant\.com$
RewriteRule ^/?fresh-store-instant/([^/-]*)-([^/-]*)-([^/-]*)-([^/-]*)-([^/-]*)-([^/-]*)-([^/-]*)-([^/-]*)/?$ https://guides.freshlabs.group/search?query=$1+$2+$3+$4+$5+$6+$7+$8 [R=301,QSA]
RewriteCond %{HTTP_HOST} ^guides\.freshstoreinstant\.com$
RewriteRule ^/?fresh-store-instant/([^/-]*)-([^/-]*)-([^/-]*)-([^/-]*)-([^/-]*)-([^/-]*)-([^/-]*)/?$ https://guides.freshlabs.group/search?query=$1+$2+$3+$4+$5+$6+$7 [R=301,QSA]
RewriteCond %{HTTP_HOST} ^guides\.freshstoreinstant\.com$
RewriteRule ^/?fresh-store-instant/([^/-]*)-([^/-]*)-([^/-]*)-([^/-]*)-([^/-]*)-([^/-]*)/?$ https://guides.freshlabs.group/search?query=$1+$2+$3+$4+$5+$6 [R=301,QSA]
RewriteCond %{HTTP_HOST} ^guides\.freshstoreinstant\.com$
RewriteRule ^/?fresh-store-instant/([^/-]*)-([^/-]*)-([^/-]*)-([^/-]*)-([^/-]*)/?$ https://guides.freshlabs.group/search?query=$1+$2+$3+$4+$5 [R=301,QSA]
RewriteCond %{HTTP_HOST} ^guides\.freshstoreinstant\.com$
RewriteRule ^/?fresh-store-instant/([^/-]*)-([^/-]*)-([^/-]*)-([^/-]*)/?$ https://guides.freshlabs.group/search?query=$1+$2+$3+$4 [R=301,QSA]
RewriteCond %{HTTP_HOST} ^guides\.freshstoreinstant\.com$
RewriteRule ^/?fresh-store-instant/([^/-]*)-([^/-]*)-([^/-]*)/?$ https://guides.freshlabs.group/search?query=$1+$2+$3 [R=301,QSA]
RewriteCond %{HTTP_HOST} ^guides\.freshstoreinstant\.com$
RewriteRule ^/?fresh-store-instant/([^/-]*)-([^/-]*)/?$ https://guides.freshlabs.group/search?query=$1+$2 [R=301,QSA]
RewriteCond %{HTTP_HOST} ^guides\.freshstoreinstant\.com$
RewriteRule ^/?fresh-store-instant/([^/-]*)/?$ https://guides.freshlabs.group/search?query=$1 [R=301,QSA]
This rule set will work likewise in the http servers host configuration or in a dynamic configuration file (".htaccess" style file).
UPDATE:
I realized that your example string to be converted contains more than 9 tokens which is the more or less hard coded limit of back references supported by an apache http server. You could change that if you can recompile the sources, in that case the above solution is fine and can be extended up to a number of tokens you feel safe with.
If that is not an option (as typical), you need to try something like this instead:
RewriteEngine on
RewriteCond %{HTTP_HOST} ^guides\.freshstoreinstant\.com$
RewriteCond %{QUERY_STRING} (^|&)query=(.+)&|$
RewriteRule ^/?fresh-store-instant/?$ https://guides.freshlabs.group/search [R=301,QSA]
RewriteCond %{HTTP_HOST} ^guides\.freshstoreinstant\.com$
RewriteCond %{QUERY_STRING} (^|&)query=(.+)(&|$)
RewriteRule ^/?fresh-store-instant/([^/-]*)[-]?(.*)/?$ /fresh-store-instant/$2?query=%2+$1 [N,QSD]
RewriteCond %{HTTP_HOST} ^guides\.freshstoreinstant\.com$
RewriteCond %{QUERY_STRING} !(^|&)query=
RewriteRule ^/?fresh-store-instant/([^/-]*)/?$ https://guides.freshlabs.group/search?query=$1 [R=301,QSD]
RewriteCond %{HTTP_HOST} ^guides\.freshstoreinstant\.com$
RewriteCond %{QUERY_STRING} !(^|&)query=
RewriteRule ^/?fresh-store-instant/([^/-]*)[-](.*)/?$ /fresh-store-instant/$2?query=$1 [N,QSD]
Note: I did not test this, just wrote it down, so there might be some smaller glitch in there. It should work though. It implements a multiple rewriting strategy: it rewrites each token in a separate go, "storing" that token in a preliminary query argument. One by one the tokens are assembled until the final external redirection is performed because no more tokens to be converted are present in the request.
And a general remark: you should always prefer to place such rules in the http servers host configuration instead of using dynamic configuration files (".htaccess"). Those dynamic configuration files add complexity, are often a cause of unexpected behavior, hard to debug and they really slow down the http server. They are only provided as a last option for situations where you do not have access to the real http servers host configuration (read: really cheap service providers) or for applications insisting on writing their own rules (which is an obvious security nightmare).

mod-rewrite redirect but prevent direct access

I want to redirect all content to:
www.example.com/public/...
but prevent direct access to
www.example.com/public/file1/
www.example.com/public/file2/
etc
The final URL should be:
www.example.com/file1/
I've tried this for redirecting and it works - but I dont know how to prevent direct access:
ReWriteCond %{REQUEST_URI} !/public/
RewriteRule ^(.*) public/$1 [L]
After spending an inordinate amount of time trying to solve this problem, I found that the solution lies with the under-documented REDIRECT_STATUS environment variable.
Add this to the beginning of your top-level /.htaccess code, and also to any .htaccess files you have under it (e.g. /public/.htaccess):
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{ENV:REDIRECT_STATUS} !=200
RewriteRule ^ /public%{REQUEST_URI} [L]
</IfModule>
Now, if the user requests example.com/file1 then they are served the file at /public/file1. However, if they request example.com/public/file1 directly then the server will attempt to serve the file at /public/public/file1, which will fail (unless you happen to have a file at that location).
IMPORTANT:
You need to add those lines to all .htaccess files, not just the top-level one in the web root, because if you have any .htaccess files below the web root (e.g. /public/.htaccess) then these will override the top-level .htaccess and users will again be able to access files in /public directly.
Note about variables and redirects:
Performing a redirect (or a rewrite) causes the whole process to start again with the new URI, so any variables that you set before the redirect will no longer be set afterwards. This is done deliberately, because usually you do not want the final result to depend on how you got there (i.e. whether it was via a direct request or via a redirect).
However, for those special occasions where you do want to know how you got to a particular URI, you can use REDIRECT_STATUS. Also, any environment variables set before the redirect (e.g. with SetEnvIf) will still be available after the redirect, but with REDIRECT_ prefixed to the name of the variable (so MY_VAR becomes REDIRECT_MY_VAR).
Maybe you should clarify what's the expected behaviour when user tries to reach the real URL:
www.example.com/public/file1/
If by prevent you mean forbid, you could add a rule to respond with a 403
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_URI} !/public/
RewriteRule ^(.*)$ /public/$1 [L]
RewriteCond %{REQUEST_URI} /public/
RewriteRule ^(.*)$ / [R=403,L]
</IfModule>
Update: The solution above doesn't work!
I realized my previous solution always throws the 403 so it's worthless. Actually, this is kinda tricky because the redirection itself really contains /public/ in the URL.
The solution that really worked for me is to append a secret query string to the redirection and check for this value on URL's containing /public/:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_URI} !/public/
RewriteRule ^(.*)$ /public/$1?token=SECRET_TOKEN [L]
RewriteCond %{REQUEST_URI} /public/
RewriteCond %{QUERY_STRING} !token=SECRET_TOKEN
RewriteRule ^(.*)$ / [R=403,NC,L]
</IfModule>
This way www.example.com/file1/ will show file1, but www.example.com/public/file1/ will throw a 403 Forbidden error response.
Concerns about security of this SECRET_TOKEN are discussed here: How secure is to append a secret token as query string in a htaccess rewrite rule?
If your URL's are expected to have it's own query string, like www.example.com/file1/?param=value be sure to add the flag QSA.
RewriteRule ^(.*)$ /public/$1?token=SECRET_TOKEN [QSA,L]

htaccess codes did not work

This is EXACTLY the same case as: (htaccess) How to prevent a file from DIRECT URL ACCESS?
But, no one of codes provided by answers work for me. I tried 1 by 1, then tried to combine, but still not works. Here is my code:
# prevent direct image url access
# ----------
RewriteEngine On
RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} !^http(s)://(www\.)?example\.com [NC]
RewriteCond %{HTTP_REFERER} !^http(s)://(www\.)?example\.com.*$ [NC]
# this not works
RewriteRule \.(png|gif|jpe?g)$ - [F]
# and this
RewriteRule \.(png|gif|jpe?g)$ - [F,NC]
# and this
RewriteRule \.(png|gif|jpe?g)$ https://example.com/wp-login.php [NC,R,L]
# even by combining them
# ----------
# /prevent direct image url access
The case simulation:
index.php has <img src="test.png" alt=""> and should be normally accessible. The requirement is: http://example.com/test.png shouldn't be accessible.
I use WordPress in wp-engine, and i think WordPres's default rewrite doesn't cause the problem since the code from answers are placed above WordPress rewrite.
UPDATE
I use PHP Version 5.5.9-1ubuntu4.14 on Apache 2 on wp engine
Your rules basically work for me, except for one thing:
The (s) is not doing what you think it does.
RewriteCond %{HTTP_REFERER} !^http(s)://(www\.)?example\.com [NC]
With parentheses you define a group, which doesn't make any sense at this point. If you remove the (s), it works for http.
If you want to use https too you have to write it like this:
RewriteCond %{HTTP_REFERER} !^https?://(www\.)?example\.com [NC]
The ? will make the preceding character (or group, if in parentheses) optional.

htaccess subdomain script redirection

I'm having problems understanding how htaccess redirects work:
Can I do a background redirect, so that the user sees [subdomain].mydomain.com/?p1=v1..., but the server delivers mydomain.com/?sid=[subdomain]&p1=v1... without actual redirection, only server side.
This is what I have so far, it doesn't work:
RewriteEngine On
RewriteBase /
RewriteCond %{HTTP_HOST} ^([^./]+)\.localhost\.com/(.+) [NC]
RewriteRule (.+) localhost.com/index.php?supplier=$1&$2 [L]
I doesn't change anything.
Edit
I got this halfway working:
Options +FollowSymLinks
RewriteEngine On
RewriteBase /
RewriteCond %{HTTP_HOST} ^([^./]+)\.localhost\.com$ [NC]
RewriteRule /(.+)$ http://localhost\.com/eshop/?supplier=%1 [QSA,P]
Now I get a nice forbidden warning, if I remove the P flag it'll redirect, so the URL shows http://localhost.com/eshop/?supplier=[subdomain]&p1=v1... like it should, but the user must still see http://[subdomain].localhost.com/eshop/?p1=v1..., now how the remove that forbidden part...
(Notice my website is actually in a folder under www, but the eshop part will go away).
EDIT 2
IT WORKS, so as clmarquart said I needed mod_proxy. On WAMP you have to enable it by clicking on the tray icon->Apache->Apache modules and I enabled proxy_module and proxy_http_module, whatever they are.
Use the "P" flag to force use of the internal proxy. The RewriteURL target must be a full URL when using the proxy module. Use "%1" to "%9" as the captured data from the RewriteCond expression, and "$1" to "$9" for the captured data from the RewriteRule expression.
The following should work better (not tested though)
RewriteEngine On
RewriteBase /
RewriteCond %{HTTP_HOST} ^([^./]+)\.localhost\.com$ [NC]
RewriteRule (.+) http://localhost.com/index.php?supplier=%1&$1 [L,P]

How do I get the [L] flag of RewriteRule (.htaccess) really working?

To newcomers: While trying to comprehensively describe my problem and phrase my questions I produced huge ammount of text. If you don't want to read the whole thing, my observations about (read "proof of") [L] flag not working the misconception, from which it all sprung, is located in Additional observations section. Why I misunderstood apparent behaviour is described in my Answer as well as solution to given problem.
Setup
I have following code in my .htaccess file:
# disallow directory indexing
Options -Indexes
# turn mod_rewrite on
Options +FollowSymlinks
RewriteEngine on
# allow access to robots file
RewriteRule ^robots.txt$ robots.txt [NC,L]
# mangle core request handler address
RewriteRule ^core/(\?.+)?$ core/handleCoreRequest.php$1 [NC,L]
# mangle web file adresses (move them to application root folder)
# application root folder serves as application GUI address
RewriteRule ^$ web/index.html [L]
# allow access to images
RewriteRule ^(images/.+\.(ico|png|bmp|jpg|gif))$ web/$1 [NC,L]
# allow access to stylesheets
RewriteRule ^(css/.+\.css)$ web/$1 [NC,L]
# allow access to javascript
RewriteRule ^(js/.+\.js)$ web/$1 [NC,L]
# allow access to library scripts, styles and images
RewriteRule ^(lib/js/.+\.js)$ web/$1 [NC,L]
RewriteRule ^(lib/css/.+\.css)$ web/$1 [NC,L]
RewriteRule ^(lib/(.+/)?images/.+\.(ico|png|bmp|jpg|gif))$ web/$1 [NC,L]
# redirect all other requests to application address
# RewriteRule ^(.*)$ /foo/ [R]
My web application (and its .htaccess file) is located in foo subfolder of DOCUMENT_ROOT (accessed from browser as http://localhost/foo/). It has PHP core part located in foo/core and JavaScript GUI part located in foo/web. As can be seen from the code above, I want to allow access only to single core script that handles all requests from GUI and to 'safe' web files and redirect all other requests to base application address (last commented directive).
Problem
Behaviour
It works until I try the last part by uncommenting the last redirecting directive. If I comment some more lines, the appropriate page parts stop working, etc.
However, when I uncomment last line, which should be performed only when matching of all previous rules fails (at least that's what I understand), page goes into redirection cycle (Firefox throws error page with something like "This page isn't redirecting properly"), because it's redirecting to http://localhost/foo/ again and again and again, forever.
Questions
What I don't understand is this processing of this rule:
RewriteRule ^$ web/index.html [L],
specifically the [L] flag. The flag apparently doesn't work for me. When the last line is commented, it correctly redirects, but when I uncomment it, it is always processed, even though rewriting should stop on [L] flag. Anyone got any ideas?
Also, on a sidenote, I'd be thrilled to know why my following attempt at fixing it doesn't work either:
RewriteEngine on
RewriteRule ^core/(\?.+)?$ core/handleCoreRequest.php$1 [NC,L]
RewriteRule ^(.*)$ web/$1 [L]
RewriteRule ^.*$ /foo/ [L]
This actually doesn't work at all. Even if I remove the last line, it still doesn't redirect anything correctly. How does the redirecting work in the first example, if it doesn't work in the second?
It would also be of great benefit to me, if anybody knew any way to actually debug these directives. I spend hours on this without even the slightest clue what could possibly be wrong.
Additional observations
After trying the advice given by bbadour (not that I haven't tried it before, but now that I had a second opinion, I gave it another shot) and it didn't work, I've come up with the following observation. By rewriting last line to this:
RewriteRule ^(.*)$ /foo/?uri=$1 [R,L]
or this
RewriteRule ^(.*)$ /foo/?uri=%{REQUEST_URI} [R,L]
and using Firebug's Net panel, I found out more evidence, that the [L] flag is clearly not working as expected in the previously mentioned RewriteRule ^$ web/index.html [L] rule (let's call it THE RULE from now on). In first case I get [...]uri=web/index.html, in second case [...]uri=/foo/web/index.html. That means that THE RULE gets executed (rewrites ^$ to web/index.html), but the rewriting doesn't stop there. Any more ideas, please?
After hours of searching and testing, I finally found the real problem and solution. Hopefully this will help somebody else too, when they come across the same problem.
Cause of observed behavior
.htaccess file is processed after every redirect (even without [R] flag),
which means that after the RewriteRule ^$ web/index.html [L] is processed, mod_rewrite correctly stops rewriting, goes to the end of the file, redirects correctly to /foo/web/index.html, and then the server starts processing .htaccess file for the new location, which is the same file. Now only the last rewrite rule matches and redirects back to /foo/ (this time with [R], so the redirect can be observed in browser) ... and the .htaccess file is processed again, and again, and again...
Once more for clarity: Because only the hard redirects can be observed, it seems like the [L] flag is ignored, but it is not so. Instead, the .htaccess is processed two times redirecting back and forth between /foo/ and /foo/web/index.html.
Solution
Disallow direct access to subfolder
To virtually move subdirectory to application root directory, additional complex conditional rewrites must be used. Variable THE_REQUEST is useful for distinguishing between hard and soft redirects:
RewriteCond %{THE_REQUEST} ^GET\ /foo/web/
RewriteRule ^web/(.*) /foo/$1 [L,R]
For this rewrite rule to be matched, two conditions must apply. First, on second line, the "local URI" must start with web/ (which corresponds with absolute web URI /foo/web/). Second, on first line, the real request URI must start with /foo/web/ too. Together this means, that the rule only matches when the file inside the web/ subfolder is requested directly from the browser, in which case we want to do a hard redirect.
Redirect to allowed content from root to subfolder (soft)
RewriteCond $1 !^web/
RewriteCond $1 ^(.+\.(html|css|js|ico|png|bmp|jpg|gif))?$
RewriteRule ^(.*)$ web/$1 [L,NC]
We want to redirect to allowed content only if we haven't done it already, hence the first condition. Second condition specifies mask for allowed content. Anything matching this mask will be softly redirected, possibly returning 404 error if the content doesn't exist.
Hide all content not in subfolder or not allowed
RewriteRule !^web/ /foo/ [L,R]
This will do a hard redirect to application root for all URIs not beginning with web/ (and remember, only requests that can begin with web/ at this point are internal redirects for allowed content.
Real example
My code shown in my "question" after using solution tips mentioned above gradually transformed into the following:
# disallow directory indexing
Options -Indexes
# turn mod_rewrite on
Options +FollowSymlinks
RewriteEngine on
# allow access to robots file
RewriteRule ^robots.txt$ - [NC,L]
# mangle core request handler address
# disallow direct access to core request handler
RewriteCond %{THE_REQUEST} !^(GET|POST)\ /asm/core/handleCoreRequest.php
RewriteRule ^core/handleCoreRequest.php$ - [L]
# allow access to request handler under alias
RewriteRule ^core/$ core/handleCoreRequest.php [NC,QSA,L]
# mangle GUI files adressing (move to application root folder)
# disallow direct access to GUI subfolder
RewriteCond %{THE_REQUEST} ^GET\ /foo/web/
RewriteRule ^web/(.*) /foo/$1 [L,R]
# allow access only to correct filetypes in appropriate locations
RewriteCond $1 ^$ [OR]
RewriteCond $1 ^(images/.+\.(ico|png|bmp|jpg|gif))$ [OR]
RewriteCond $1 ^(css/.+\.css)$ [OR]
RewriteCond $1 ^(js/.+\.js)$ [OR]
RewriteCond $1 ^(lib/js/.+\.js)$ [OR]
RewriteCond $1 ^(lib/css/.+\.css)$ [OR]
RewriteCond $1 ^(lib/(.+/)?images/.+\.(ico|png|bmp|jpg|gif))$
RewriteRule ^(.*)$ web/$1 [L,NC]
# hide all files not in GUI subfolder that are not whitelisted above
RewriteRule !^web/ /foo/ [L,R]
What I don't like about this approach is that the application root folder must be hardcoded in .htaccess file (as far as I know), so the file must be generated on application install, not simply copied.
To debug, try simplifying your regex, and the url you ask for (a part of the full url you wanna match), and see if it's working, now step by step, add more bits to the regex adn the testing url, till you find where things are stopping to work properly.
Try using:
RewriteRule ^(.*)$ /foo/ [R,L]
If it still loops, put a RewriteCond in front of it to skip the rule if it is already /foo/

Resources