htaccess password protected directory and mod_rewrite RerwriteCond - apache

I have a site that i want to redirect all requests accept for 1 directory path.
http://mysite.com/application
http://mysite.com/application/templates
http://mysite.com/application/admin (password protected)
RewriteCond %{REQUEST_URI} !^\/application
RewriteRule ^.*$ http://mynewsite.com [R=307]
My rewrite engine on the .htaccess is working fine, except when accessing the /admin directory which is password protected. When i try to request it, i am redirected. If i rename the .htaccess in the /admin folder. it works fine. My suspicion is that the browser (FF) is requesting another url which matches the redirect. How can i keep the directory password protected, but not redirect?

by adding:
RewriteCond %{REQUEST_URI} !401
Now it works. I believe this is due to the shared webhost configuration which has pre-assigned 4XX and 5XX page redirects. So, that that is what was happening. The !401 isn't perfect, but for my simple app it works. I think something like this would be better to capture 401 as the beginning of the uri (pattern is untested):
RewriteCond %{REQUEST_URI} !^\/401

Related

How add path to url if the url does not contain substring

I need to redirect all requests from
https://example.com/* to https://example.com/test/* if the URL does not contain the test substring.
So far I have these rewrite rules
RewriteBase /
RewriteCond %{THE_REQUEST} !^/test
RewriteRule ^/?$ /test/$1 [R=301,L] # if the url does not contain test, redirect to url with test
RewriteCond %{THE_REQUEST}% test
RewriteRule ^test?(.*)$ /$1 [L] # mask the fact that the url is not https://example.com/ and instead is https://example.com/test but apache serve the website like if it was on root
If I access https://example.com it redirects to https://example.com/test but gives infinite loop because of the second rule.
How can I combine it, so request to https://example.com/test* do not get redirected but those request at https://example.com/* do without having to change www root directory and so it will work for all URLs.
UPDATE:
The test should be in url (for user experience), but the apache should route like if it was not in url and instead the request came to root url, so application routing is preserved internally without having to change the app itself.
Ah, Ok. However, you should be linking to the /test URLs within your app (so you do still need to "change the app", despite your last comment), otherwise /test isn't actually in the URLs that users and search engines see on the page (they will be redirected) and your users will experience an external redirect every time they click one of your links (bad for SEO and user experience).
The "redirect" implemented in .htaccess to prefix "old" URLs with /test is just for SEO - as with any "old" to "new" URL change. (It should not be required for your app to function - with /test in the URL-path - since your internal URLs should already include /test.)
Try it like this instead:
RewriteEngine On
# Insert "/test" at the start of the URL-path if absent in "direct" requests
RewriteRule %{ENV:REDIRECT_STATUS} ^$
RewriteRule !^test/ /test/$1 [R=301,L]
# Rewrite "/test" URLs back to root
RewriteRule ^test(?:$|/(.*)) /$1 [L]
The REDIRECT_STATUS environment variable is used to prevent a redirect loop. This is empty on the initial request from the client and set to the HTTP response status after the rewrite (below).
Test first with 302 (temporary) redirects and only change to 301 (permanent) when you are sure this is working as intended.
You will need to clear your browser cache before testing.

How to setup request proxy using URL rewriting

I have an e-commerce site that resides in:
http://dev.gworks.mobi/
When a customer clicks on the signin link, the browser gets redirected to another domain, in order for authentication:
http://frock.gworks.mobi:8080/openam/XUI/#login/&goto=http%3A%2F%2Fdev.gworks.mobi%3A80%2Fcustomer%2Faccount%2Flogin%2Freferer%2FaHR0cDovL2Rldi5nd29ya3MubW9iaS8%2C%2F
I'm trying to rewrite http://dev.gworks.mobi/* to http://frock.gworks.mobi:8080/openam/*, without redirection.
I've tried this in the .htaccess of the dev.gworks.mobi site:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_URI} ^/openam(.*)$ [NC]
RewriteRule ^(.*)$ http://frock.gworks.mobi:8080/$1 [P,L]
</IfModule>
But when I access http://dev.gworks.mobi/openam, it shows a 404 page not found page.
Can anyone help me to achieve my use case?
Try this:
RewriteEngine on
RewriteBase /
# Make sure it's not an actual file being accessed
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# Match the host
RewriteCond %{HTTP_HOST} ^dev\.gworks\.mobi
# Rewrite the request if it starts with "openam"
RewriteRule ^openam(.*)$ http://frock.gworks.mobi:8080/$1 [L,QSA]
This will rewrite all the requests to dev.gworks.mobi/openam to frock.gworks.mobi:8080.
If you want to mask the URI in a way that it's not visible to the visitor that she's visiting the authentication app, you need to add a P flag. Please note that it needs Apache's mod_proxy module in place:
RewriteRule ^openam(.*)$ http://frock.gworks.mobi:8080/$1 [P,L,QSA]
Feel free to drop the L flag, if it's not the last rewrite rule. See RewriteRule Flags for more information.
The 404
If it's all in place and you're still getting a 404 error, make sure that the target URL is not throwing 404 errors in the first place.
Second, check if you're still getting the error with the correct referrer URI set. It might be designed in a way to throw a 404, if the referrer is not correctly set. If that's the case, which I suspect, you need to use the R flag and redirect instead of proxying the request.
Last thing that comes to my mind, some webapps are not built in a way to figure out the URI address. The host, as well as the port number, might be hard-coded somewhere in the config files. Make sure that the authentication app is able to be run from another URL without the need to edit the configs.
Test
You can test the rewriterule online:

htaccess - rewrite rule not working when requested URL is a folder on my system

All requests to my site should be rewritten to index.php?page=blah, where blah is the page that's requested (except for css, js, jp(e)g, gif and png files).
This is how my .htaccess file looks like:
RewriteEngine On
RewriteCond %{REQUEST_URI} !\.(?:css|js|jpe?g|gif|png)$ [NC]
RewriteRule ^(.*)$ index.php?page=$1 [L,QSA]
The .htaccess is in this directory: localhost:8080/example/, so when I go to localhost:8080/example/abc, it is (internally) rewritten to localhost:8080/example/index.php?page=abc.
However when I go to localhost:8080/example/res, I get redirected to localhost:8080/example/res/?page=res. I found out that this only happens to directories; when I go to localhost:8080/example/core(also a folder on my file system), I get redirected to localhost:8080/example/core/?page=core while it should be internally rewritten to localhost:8080/example/index.php?page=core and the url visible to the user should stay localhost:8080/example/core/
EDIT:
Thanks to #w3dk, who solved the problem stated above. But I found another problem, which may be related to the problem above:
When I go to:
localhost:8080/example/index/a, it's internally rewritten to localhost:8080/example/index.php?page=index.php/a, while it should be rewritten to localhost:8080/example/index.php?page=index/a.
I found out that this happens when index is a file, cause when I go to localhost:8080/example/exampleFile/abc, it's redirected to localhost:8080/example/index.php?page=exampleFile.php/abc, which shouldn't be the case.
The 2 files in my directory are:
index.php (everything should be directed to this file)
example.php
Apache seems to ignore the php file extension, cause this also works for exampleFile.txt
This is probably happening because of a conflict with mod_dir. The default behaviour (DirectorySlash On) is for mod_dir to automatically "fix" the URL when you request a physical directory without a trailing slash. It does this with an external 301 redirect, before your rule is processed. Your rule then fires, which modifies the target URL, a Location header gets returned to the client and the browser redirects.
This won't happen if you include the trailing slash on the original request. eg. localhost:8080/example/core/. mod_dir then does not need to "fix" the URL and issue a redirect. Although this may not be desirable for you?
Since you are wanting to internally rewrite all directories then the simple fix is to disable this behaviour in .htaccess:
DirectorySlash Off
You will need to clear your browser cache before testing, as the earlier 301s by mod_dir will have been cached locally.
Reference (note the security warning):
https://httpd.apache.org/docs/current/mod/mod_dir.html#directoryslash
You can use this
.htaccess file
Note: The directory folder1 must be unique in the URL. It won't work for http://domain.com/folder1/folder1.html. The directory folder1 must exist and have content in it.
RewriteEngine On
RewriteCond %{HTTP_HOST} domain.com$ [NC]
RewriteCond %{HTTP_HOST} !folder1
RewriteRule ^(.*)$ http://domain.com/folder1/$1 [R=301,L]

Basic protected folder redirecting to https 401 page and causing problems

So I am redirecting all requests to my site to the www and https version MINUS one folder. That one folder just happens to be password protected. I need to access that folder with regular http (the reason for excluding it from the redirects), but when I do that it gives a 401 error. If I access it with https then the browser prompts me for the user/pass as normal. Why is this happening and how can I fix it?
/public_html/ htaccess
# BEGIN non-www to www with https: (with exclusions)
RewriteCond %{REQUEST_URI} !^/protected/
RewriteCond %{HTTP_HOST} !^(www\.example\.com)?$ [OR]
RewriteCond %{HTTPS} !on
RewriteRule (.*) https://www.example.com/$1 [R=301,L]
/public_html/protected/ htaccess
AuthType Basic
AuthName "Protected Access"
require valid-user
AuthUserFile "/home/example/.htpasswds/public_html/protected/passwd"
Problem
As I am excluding this folder from the www and https redirects I 'should' be able to access any files in /protected/ by either http OR https. The problem is http://example.com/protected/somefile.htm redirects to the https 401 error page without even prompting me for a user/pass.
On the other hand https://example.com/protected/somefile.htm works fine - it prompts me for the user/pass and works great.
For one I don't understand why this is happening and two I must be able to access files in that folder with http and non-ssl.
I should add that the htaccess rules are 'correct' as if I comment out the lines for the user/pass on protected it works as it should and both http/https are able to be served. It is ONLY when the folder is pw'ed that this problem is happening.

Apache mod_rewrite - want a file system redirect not a 301 redirect

I have example1.com on a shared web host running Apache. It has a directory example1.com/foo. I now want example2.com to serve the same content from example1.com/foo, except at the example2.com root without the intervening directory in the URL. Like example2.com/bar.html should serve the same content as example1.com/foo/bar.html .
RewriteEngine on
RewriteCond %{HTTP_HOST} example2.com$ [NC]
RewriteRule ^(.*)$ foo/$1 [NC]
This simple rewrite rule takes any request intended for example2.com and inserts the foo/ to point to the content which is in that directory. Problem is this keeps doing an external 301 redirect. I don't want that, I want the browser to stay on example2.com without redirecting while Apache serves up the content from /foo in the filesystem.
Been over the Apache mod_rewrite docs several times, which say how to force a 301 redirect with the [R] flag but don't say how to force it NOT to happen. What am I missing here? It is behaving the same on both my Linux shared host and a local test with Apache on Windows.
Thanks!
I figured this out. The 301 was happening because I had the directory name wrong in the rule. So the result of the rule pointed to a path that didn't exist, which makes Apache try to fallback from the file system redirect to a 301 redirect.
Then I had to fix an infinite loop, since that above rule always adds "foo" to the URL even if it's already present so I'd get foo/foo/foo/foo/... . We need to add it only if it's not already there. Had to do it with this two-step rule, because you can't use wildcards in a capturing group of a negative rule. But this seems to work, adding "foo" when the host is example2.com and the URL does not already contain "foo".
RewriteEngine on
RewriteCond %{HTTP_HOST} example2.com$ [NC]
RewriteRule !^foo - [C]
RewriteRule ^(.*)$ foo/$1 [NC,PT]