Rewrite rules ignoring my dist folder - regex

So I have a bunch of .htaccess rules for my angular application and I'm looking for the behavior:
If dist/frontend.html exists, route everything to that. If not route to frontend.html.
This is what I currently have. The rules work as long as I'm requesting a sub route (e.g. http://www.domain.com/404/) but if I'm requesting the root, with no path it's like these rules are never executed and it just relies on the DirectoryIndex.
DirectoryIndex index.html index.html frontend.html index.php
# Rewrite everything which looks like it should be handled by angular here, 404 if a specific resource
RewriteCond %{REQUEST_URI} !\.(jpg|png|jpeg|gif|css|js|html)$ [NC]
RewriteCond %{DOCUMENT_ROOT}/dist/frontend.html -f
RewriteRule ^ dist/frontend.html [L]
RewriteCond %{REQUEST_URI} !\.(jpg|png|jpeg|gif|css|js|html)$ [NC]
RewriteCond %{DOCUMENT_ROOT}/frontend.html -f
RewriteRule ^ frontend.html [L]

Problem is this condition:
RewriteCond %{REQUEST_URI} !\.(jpg|png|jpeg|gif|css|js|html)$ [NC]
Since you're ignoring .html extension and also using index.html as default handler using DirectoryIndex causing both of your rules to be skipped.
If you're going to use one of the frontend.html using one of the 2 rules then you don't really need DirectoryIndex directive, just comment it out and it should work.

Related

Redirect non-www to www giving me hundreds of 404's

Thanks to anyone who can take a moment to look at this.
Recently I created a new section "subdomain" in my website and in this new folder I have includes a Joomla CMS installation the url looks like this: http://www.example.com/subdomain/
In this folder I have a htaccess file to which I have added.
## No directory listings
# Redirect non-www to www:
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule ^(.*)$ http://www.%{HTTP_HOST}/$1 [R=301,L]
When I try to access say http://example.com/subdomain/anytrailingstring then it's NOT redirecting me to http://www.example.com/subdomain/anytrailingstring as I expected, it is redirecting to http://www.example.com/anytrailingstring leaving out the /subdomain/ and this is of course a page that doesnt exist and therefore a 404.
This is a problem.
I do not have any directive in the root .htacces file except for this :
DirectoryIndex index.php
Options +FollowSymLinks
RewriteEngine on
RewriteBase /
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
Can someone perhaps see why the subdomain htaccess isnt redirecting to correctly? Did I miss something?
I am not good with htaccess at all, if anybody can help me I would really appreciate it.
Thanks!
RewriteCond %{HTTP_HOST} !^www\. [NC]
RewriteRule ^(.*)$ http://www.%{HTTP_HOST}/$1 [R=301,L]
You need to use the REQUEST_URI server variable instead of the backreference ($1). The URL-path matched by the RewriteRule pattern (first argument) is relative to the current directory, so excludes the parent subdirectory (ie. /subdomain in your example).
Do it like this instead:
RewriteCond %{HTTP_HOST} !^www\.
RewriteRule ^ http://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
You will need to clear your browser cache since the erroneous (301 - permanent) redirect will have been cached by the browser. Test with 302 (temporary) redirects to avoid potential caching issues.
However, a couple of questions:
Why are you not using HTTPS? (You are redirecting to HTTPS in the parent .htaccess file - but this is now being overridden by the mod_rewrite directives in the subdirectory.)
Why not include this in the parent .htaccess file?
UPDATE: So, taking the above points into consideration... if you want to move this rule to the parent .htaccess file in the root then have it like this:
DirectoryIndex index.php
Options +FollowSymLinks
RewriteEngine on
# Redirect non-www to www (and HTTPS)
RewriteCond %{HTTP_HOST} !^www\.
RewriteRule ^ https://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
# Redirect HTTP to HTTPS
RewriteCond %{HTTPS} off
RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
The order of the directives is to ensure there is only ever at most 1 redirect (assuming you are not implementing HSTS).
You were unnecessarily duplicating the RewriteEngine directive (so I removed the second instance).
The RewriteBase directive was not being used.
The capturing subgroup in your HTTP to HTTPS rule was not required. ie. ^ is better than ^(.*)$ in this instance.
Aside:.
...a new section "subdomain" in my website and in this new folder I have includes a Joomla CMS installation the url looks like this: http://www.example.com/subdomain/
This is a subdirectory, not a "subdomain".
This is a "subdomain":
http://subdomain.example.com/

How can I load content from two different folders (based on the subdomain) and keep the old URLs?

My website is example.com.
In my public_html folder, I have two folders. One is called main, and the other is called report.
When somebody navigates to example.com, I want to serve content from the main folder, but I want their URL to remain the same.
So, if they navigate to example.com/file.html, I want them to see the file.html file that's in the main folder, but I don't want their URL to change to example.com/main/file.html.
Similarly, if they navigate to report.example.com/report1.pdf, I want them to see the report1.pdf file that's in the report folder, but I don't want their URL to change to report.example.com/report/report1.pdf.
The closest thing I've been able to achieve is this:
DirectoryIndex index.php index.html index.htm
RewriteEngine on
RewriteBase /
RewriteCond %{HTTP_HOST} ^example.com$ [NC]
RewriteRule ^((?!main).*)$ /main/$1
RewriteCond %{HTTP_HOST} ^report.example.com$ [NC]
RewriteRule ^((?!report).*)$ /report/$1 [L]
That seems to work to some extent, but:
If somebody navigates to http://example.com/report/index.html, the server incorrectly loads the index.html file from the public_html/report folder rather than the public_html/main/report folder. Normally that path would make sense, but in this case I'm trying to change that behavior.
If somebody navigates to http://report.example.com/test, the server correctly displays the public_html/test/index.html file, but redirects them to http://report.example.com/report/test/.
How can I load the correct files and keep the URLs correct?
This should do:
RewriteCond %{HTTP_HOST} ^example.com$ [NC]
RewriteCond %{ENV:REDIRECT_STATUS} !200
RewriteRule ^ /main%{REQUEST_URI} [L]
RewriteCond %{HTTP_HOST} ^reports.example.com$ [NC]
RewriteCond %{ENV:REDIRECT_STATUS} !200
RewriteRule ^ /reports%{REQUEST_URI} [L]

.htaccess rewrite everything except images, scripts, and stylesheets

I have a web project with two directories: "core" and "public".
"Core" contains all of the controllers, views, and files required for the Model-View-Controller.
"Public" contains all public files, like js, css, and less, that can be accessed directly.
I have the following .htaccess in the main directory:
<IfModule mod_rewrite.c>
RewriteEngine on
RewriteCond %{REQUEST_URI} !(\.png|\.jpg|\.gif|\.jpeg|\.bmp|\.css|\.js|\.less|\.coffee)$
RewriteRule ^$ core/ [L]
RewriteRule (.*) core/$1 [L]
</IfModule>
However, it still rewrites those files to the 'core' directory.
What am I doing wrong?
I recommend you use this instead:
RewriteEngine on
# First, check if a specific type is being requested
RewriteCond %{REQUEST_URI} !\.(png|jpg|gif|jpeg|bmp|css|js|less|coffee)$ [NC]
# Second, check if the request is for an existing file
RewriteCond %{REQUEST_FILENAME} -f
# If both conditions are true, then skip rewriting
RewriteRule ^ - [L]
# Otherwise, continue:
RewriteRule ^$ core/ [L]
RewriteRule (.+) core/$1 [L]
The reason your assets were being sent to core is because the conditions only work for the first rule, which was for your application index. Using this method tells mod_rewrite to skip rewriting if an asset is being requested. Once it does that, it can continue with all other rules.

Apache multiple rewrite conditions for a single rule

SOLVED: The problem was related to Symfony. See my answer below.
I recently changed the domain of my site, and I'd like to permanently redirect visitors to the new domain, excluding a few specific URLs that must remain accessible via the old domain. Here's what I tried. The issue is that redirection occurs, but the specified directories are not excluded.
RewriteCond %{HTTP_HOST} !^newdomain\.com$ [NC]
RewriteCond %{REQUEST_URI} !^/[^/]+/example1/.*$ [NC]
RewriteCond %{REQUEST_URI} !^/[^/]+/example2/.*$ [NC]
RewriteCond %{REQUEST_URI} !^/[^/]+/example3/.*$ [NC]
RewriteCond %{REQUEST_URI} !/examplepage.html [NC]
RewriteRule ^/(.*)$ https://newdomain.com%{REQUEST_URI} [R=301,L]
I also tried placing the following at the top of my configuration file, no luck.
RewriteRule ^(example1|example2|example3)($|/) - [L]
Edit: It's also worth noting that these directives seem to work for examplepage.html, it's just the "directories" that don't work. This is Apache 2.4.7
The following example URLs should all be left out of the rewriting process (so pretty much anything containing "/example1":
https://olddomain.com/example1
https://olddomain.com/example1/action1
https://olddomain.com/app.php/example1/action1
For the sake of completeness, the above directives are in my apache.conf file. In addition, Symfony2 provides a default .htaccess file with the following rewrite directives. Could there be some sort of contradiction here?
RewriteCond %{HTTP:Authorization} ^(.+)$
RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
# Determine the RewriteBase automatically and set it as environment variable.
# If you are using Apache aliases to do mass virtual hosting or installed the
# project in a subdirectory, the base path will be prepended to allow proper
# resolution of the app.php file and to redirect to the correct URI. It will
# work in environments without path prefix as well, providing a safe, one-size
# fits all solution. But as you do not need it in this case, you can comment
# the following 2 lines to eliminate the overhead.
RewriteCond %{REQUEST_URI}::$1 ^(/.+)/(.*)::\2$
RewriteRule ^(.*) - [E=BASE:%1]
# Redirect to URI without front controller to prevent duplicate content
# (with and without `/app.php`). Only do this redirect on the initial
# rewrite by Apache and not on subsequent cycles. Otherwise we would get an
# endless redirect loop (request -> rewrite to front controller ->
# redirect -> request -> ...).
# So in case you get a "too many redirects" error or you always get redirected
# to the start page because your Apache does not expose the REDIRECT_STATUS
# environment variable, you have 2 choices:
# - disable this feature by commenting the following 2 lines or
# - use Apache >= 2.3.9 and replace all L flags by END flags and remove the
# following RewriteCond (best solution)
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule ^app\.php(/(.*)|$) %{ENV:BASE}/$2 [R=301,L]
# If the requested filename exists, simply serve it.
# We only want to let Apache serve files and not directories.
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule .? - [L]
# Rewrite all other queries to the front controller.
RewriteRule .? %{ENV:BASE}/app.php [L]
Try this instead:
RewriteCond %{HTTP_HOST} !^newdomain\.com$ [NC]
RewriteCond %{REQUEST_URI} !^/example1 [NC]
RewriteCond %{REQUEST_URI} !^/example2 [NC]
RewriteCond %{REQUEST_URI} !^/example3 [NC]
RewriteCond %{REQUEST_URI} !/examplepage.html [NC]
RewriteRule ^/(.*)$ https://newdomain.com/$1 [R=301,L]
I think you are making the folder conditions overly complex. Also note that you can use $1 in the last line to just carry over the value caught in the () in the left side of the line. Makes no difference in this example, but would if you needed only part of the left hand side to be used in the destination URL on the right.
I figured it out. If anyone else runs into a similar issue, the problem is due to Symfony issuing an [INTERNAL REDIRECT] on all URLs to /app.php. /app.php is then passed through the gauntlet of rewrite conditions for a second round. Excluding app.php in your rewrite conditions will solve it.
RewriteCond %{HTTP_HOST} !^newdomain\.com$ [NC]
RewriteCond %{REQUEST_URI} !^/example1/.*$ [NC]
RewriteCond %{REQUEST_URI} !^/example2/.*$ [NC]
RewriteCond %{REQUEST_URI} !^/example3/.*$ [NC]
RewriteCond %{REQUEST_URI} !/app.php [NC]
RewriteCond %{REQUEST_URI} !/examplehtml.html [NC]
RewriteRule ^/(.*)$ https://newdomain.com/$1 [R=301,L]

Rewrite sometext/ to sometext/sometext.php, forbid direct acces to sometext.php

I'am struggling with this for a couple of days.
Folder structure is:
index/files/pages/
In main folder (index) there is index.php - this is the only index.php file in whole page.
In files folder there are php files that are actually pages of the website.
In files folder there are couple of more folders (pages) that hold different pages - I just grouped the php fiels into folders to keep it tidy.
I am trying to achivie this.
When I enter url like index/files/pages/somename.php - I want to get 404 or whatever
When I enter url like index/files/somename - this gets rewritten to index/files/pages/somename.php, but the address looks clean.
Now whatever I do I can't get both rules to work, either one overwrites another or nothing works, I get 500 all the time.
Here is my rule that actually works:
RewriteRule ^([-0-9a-z]+)$ pages/$1.php - this is the scenario 2 and its ok.
Now when I add rule that handles direct access to php files, the previous rule is also affected and gets overwritten and everything throws 404, 500 etc. Flags like [L] etc don't have any effect, changing the order also does nothing.
Also I want to forbid direct access to index.php and redirect to index folder (and show clean url)
Here are some additional rules i tried, but no result. As I said earlier setting flags give no results.
RewriteCond %{REQUEST_URI} ^.*\/pages\/.*\.php$
RewriteRule ^(.+)$ [R=404,L]
RewriteRule ^([-0-9a-z]+)$ pages/$1.php
RewriteCond %{REQUEST_URI} ^(.+)\/index\.php
RewriteRule ^(.*)$ index/ [R=301,L]
RewriteCond %{REQUEST_URI} ^\/(.*)\.php
RewriteRule ^(.*)$ [R=404,L]
Thankx and regards
Try these rules:
RewriteCond %{THE_REQUEST} /index\.php [NC]
RewriteRule ^(.*?)index\.php$ index/ [L,R=302,NC,NE]
RewriteCond %{THE_REQUEST} \.php[\s?/] [NC]
RewriteRule ^ [F]
RewriteRule ^index/?$ index.php [L]
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{DOCUMENT_ROOT}/$1.php -f
RewriteRule ^(.+?)/?$ /$1.php [L]