htaccess: act as if files were in another directory, but RewriteRules seem to be mutually exclusive - .htaccess

For files in several subdirectories of /data/, I would like to treat them (and the files inside them) as if they were in the root directory.
So,
1) a request to
/data/foobar/file.png
should redirect the browser to
/foobar/file.png
2) any requests to
/foobar/file.png
should respectively deliver the file /data/foobar/file.png, but without redirection.
For 1) I got the following rule working
:
RewriteCond %{REQUEST_URI} ^(.*)?data/((foobar|and|some|other|subdirs)/.*)$
RewriteRule .* %1%2 [R=301,L,qsappend]
(I took this approach usind a RewriteCond with %x references in order to be subdirectory-agnostic, as in my dev environment the page is located in a subdirectory as opposed to the live system where it's in the root of the domain.)
And for 2) the following rule does the trick:
RewriteRule ^((foobar|and|some|other|subdirs)/.*)$ data/$1 [L,qsappend]
However, these rules only work if I enable one at a time. If I enable both of them at the same time, the browser will abort the request with a "too many redirects" error. The redirect from /data/* to /* will work, but then end in the aborted request just the same as calling the URL without /data/*.
I'm having a hard time understanding why this is happening. It would be totally logical if both rules actually triggered a redirect. But as far as my understanding of htacccess goes (and the Network tab of the dev console seems to confirm that conception), the client shouldn't even know for case 2) that the file is not actually there. So why does this apparently still count towards the redirection limit?
Is there something fundamental I'm missing? And how can I achieve what I'm trying to achieve?

This is because you first redirect and then rewrite the same Uri . Your second rule is conflicting with with the first one.
You need to match against %{THE_REQUEST} instead of %{REQUEST_URI} to avoid the redirect loop
RewriteCond %{THE_REQUEST} \s(.*)?data/((foobar|and|some|other|subdirs)/.*)\s
RewriteRule .* %1%2 [R=301,L,qsappend]
RewriteRule ^((foobar|and|some|other|subdirs)/.*)$ data/$1 [L,qsappend]

Related

Why htaccess not working for mobile browser?

I have website (mzadkm.com) try to RewriteRule short url to app.php page .
So if user browse "mzadkm.com/app" will show "mzadkm.com/app.php" page
RewriteRule ^/app /app.php [L,R=301]
It's work on Computer , but on mobile browser give me 404 page
Any ideas
That probably is what you are looking for:
RewriteRule ^/?app /app.php [L]
The documentation clearly says, that the pattern in a RewriteRule get's applied to the relative path of the request if the rule is implemented inside a distributed configuration file. That means you actually want to match the path app and not /app here. Which is why your rule did not get applied. The ^/?app is a variant to accept both path notations, relative and absolut, which means the same rule can get implemented in the central configuration or likewise in a distributed configuration file (".htaccess").
I took the liberty to also remove the external redirection you showed ("R=301") since that most likely is not what you want, according to the phrasing of your question. Instead you want an internal rewrite .
You need to take care however that you do not implement a rewriting loop. Which would result in failing requests and an "internal server error" (http status 500).
One approach would be that:
RewriteEngine on
RewriteRule ^/?app$ /app.php [L]
Here another one:
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^/?app /app.php [L]
Why things looked fine on your computer, but not on a mobile browser is unclear. Since the same rules get applied and the requests look the same there has to be another reason for that. I suspect you looked at a cached result of a previous attempt somewhere. Remember to always use a fresh anonymous browser window when testing. And to check the response you receive back inside your browsers network console.

Subdomain in .htaccess file only works with index

I have a subdomain setup in my .htaccess, which only seems to work with the default index.html page. I'd LIKE it to work for ANY page in the folder corresponding to the subdomain. Edited for privacy, assume my domain is example.org. The pertinent parts of the file look like this...
#subdomain
RewriteCond %{HTTP_HOST} ^subname\.example\.org$ [OR]
RewriteCond %{HTTP_HOST} ^www\.subname\.example\.org$
# (a few lines added by my hosting company deleted -- see below)
RewriteRule ^/?$ "http\:\/\/example\.org\/subname\/" [R=301,L]
So the result of the above is that if I have an index.html page in my 'public-html' (root?), http://example.org and a different index.html stored in a sub-folder (having the same name as the subdomain), I will get this expected result, which works...
browse to: http://example.org results in viewing http:// example.org/index.html
browse to: http://subname.example.org results in viewing http:// example.org/subname/index.html
Great so far. This is what I expected when I created the domain name. However, given a specific file myfile.html stored in the subname folder, I would expect this to work also, and it doesn't...
browse to: http://subname.example.org/myfile.html results in a 404 error.
This despite the fact that browsing to http://example.org/subname/myfile.html works fine. In that case myfile.html is displayed. So is there anything I can do to modify the subdomain code to get the result I'm looking for? Namely, browsing to http://subname.example.org/ANYFILE should work as well as browsing to http://example.org/subname/ANYFILE, regardless of what 'ANYFILE' is. This, after all, is one of the main reasons I set up the subdomain to begin with!
Note: I confess that I relied on my hosting company's cPanel utility to create the subdomain code, so I asked for their tech support for help first. Long story short they didn't. Maybe what I hoped for is not actually possible?
Also, the lines I deleted' from the code had to do with something called "well-known/acme-challenge", added by my hosting company at some point. Since removing them had no effect on the behavior I've described, I left it out to avoid clouding the issue.
RewriteRule ^/?$ "http\:\/\/example\.org\/subname\/" [R=301,L]
This only "redirects" the document root. To redirect all URLs you need to change the above to read something like:
RewriteRule (.*) http://example.org/subname/$1 [R=301,L]
The $1 backreference refers to the URL-path captured in the RewriteRule pattern, ie. (.*).
No need to backslash-escape the colons, slashes and dots in the substitution string (that's typical of cPanel).
Also, the lines I deleted' from the code had to do with something called "well-known/acme-challenge", added by my hosting company at some point.
Those lines will likely be required when the (Let's Encrypt?) SSL cert auto-renews. (Although the above redirects to "http" - are you not using HTTPS?)
UPDATE:
RewriteCond %{HTTP_HOST} ^subname\.example\.org$ [OR]
RewriteCond %{HTTP_HOST} ^www\.subname\.example\.org$
Just as an aside, these two conditions could be reduced to a single condition if you wanted. For example, the above is equivalent to:
RewriteCond %{HTTP_HOST} ^(www\.)?subname\.example\.org$

Redirects not working as expected

I have an .htaccess file with several lines. It does not work as expected. Mod_rewrite is enabled. RewriteLogLevel is set to 9.
The first two rules are there to forbid uris with a length more then 80 characters:
RewriteCond %{REQUEST_URI} ^.{80}
RewriteRule .* - [F]
It does not seem to get evaluated as every test url passes through and it does not generate an error either.
I also tried:
RewriteRule .{80} - [F]
But that did not do the trick either. The process ends with a 404, not a 403.
This next rule is not working either. It used to work.
RewriteRule ^(\/)?([\w]+)$ /index.php [L]
The URI /Contact was always handled by this index.php.
Whatever URL I type I get a 404. I should get a 403 or a 200. Not a 404. What am I missing?
Apache has on all directories the permission to read, write and execute and on all files the permission to read and write.
The two urls for testing are:
127.0.0.4/asssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssddddddddddddddddddddd?p=s&s=psv
and
127.0.0.4/Contact
The alias for 127.0.0.4 used is considerate.lb.
Try this rule instead:
RewriteCond %{THE_REQUEST} ^[A-Z]{3,}\s/+\S{80}
RewriteRule ^ - [F]
Using THE_REQUEST instead of REQUEST_URI as that variable might get overwritten due to presence of other rules in your .htaccess
Finally I have found a solution. The problem was not in the coding of the .htaccess. I replaced the file with a previous version, added the new lines to test the request and it worked all fine.
It is not a satisfactory solution, because it can happen again and I do not have any clue what caused the error. If someone knows the error, I would love to hear what might have been the exact cause and how to solve that properly. I would like to change the tags of the question as the current tags might be misleading (although other people might experience the same problem how apache handles a .htaccess file), but I do not know which tags I should use.

.htaccess Redirect in case of 404

I have this line of .htaccess
This line is used to get images from another server.
RewriteRule ^resources/fabricantes(.*)$ http://mysecondserver.com/arq/pictures/fab$1
than, if I have the url: http://myserver.com/resources/fabricantes/fab_1.jpg
this image will be get from: http://mysecondserver.com/arq/pictures/fab/fab_1.jpg
The Problem:
In some cases, the image doesn't exists on mysecondserver.com, how can I redirect to a "image unavailable" image in this cases?
First think you need to understand that this rule can only work from mysecondserver.com host not from server.com.
On mysecondserver.com place this .htaccess in /arq/pictures/.htaccess:
RewriteEngine On
RewriteBase /arq/pictures/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ no-image.jpg [L]
On mysecondserver.com, you would have .htaccess checking for -f status of the REQUEST_FILENAME. It could send the user back to the first server, if necessary. The alternative is to explicitly list all known failures back on your first server, which is a lot of work for you (even if you have a complete list). There's no way for the first server to know if a file actually exists on the second server.

htaccess reditect if server returns 404

For example I have a page http://www.f1u.org/en/its-interesting/166-cricri.
How to write rule: if that page exists - open it.
If it returns 404, then redirect to http://www.f1u.org/its-interesting/166-cricri
use this line in .htaccess file
ErrorDocument 404$ http://www.f1u.org/its-interesting/166-cricri
It sounds like you want the apache server to look ahead to see if the current URL exists, if not, redirect them. I think you might be able to use mod_rewrite to accomplish this.
My first stab at it would be something like:
RewriteEngine On
RewriteCond %{IS_SUBREQ} false
RewriteCond %{REQUEST_URI} !-U
RewriteRule /en(/.*) $1 [R,L]
I'll note that I haven't tried it so the syntax and effects could be slightly off, and you'd need to be careful that you don't put yourself into an infinite loop, or wind up with too many subrequests (as that could impact the performance of your server). But hopefully it'll give you a starting point to play with. Alternatively mod-rewrite could (depending on server permissions) let you invoke scripts to determine rewrites as well, which could be an option as well.

Resources