I have created a small Angular application that runs perfectly on localhost, but I can't make it work correctly on my server. Anytime I try to load any other url than the homepage/base url, I get either an error 403 or 404 depending on the solutions I tried.
This is an apache server running on Centos7, with the following VHosts (sensitive data (domain url, app name) redacted) :
VHost to redirect http to https :
<VirtualHost *:80>
ServerName domain_url
ServerAlias domain_url (without www.)
DocumentRoot /var/www/MyApp/html
ErrorLog /var/www/MyApp/log/error.log
CustomLog /var/www/MyApp/log/requests.log combined
RewriteEngine on
RewriteCond %{SERVER_NAME} = domain_url [OR]
RewriteCond %{SERVER_NAME} = domain_url (without www.)
RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
</VirtualHost>
HTTPS VHost :
<IfModule mod_ssl.c>
<VirtualHost *:443>
ServerName domain_url
ServerAlias domain_url (without www.)
DocumentRoot /var/www/MyApp/html
ErrorLog /var/www/MyApp/log/error.log
CustomLog /var/www/MyApp/log/requests.log combined
<Directory /var/www/MyApp/>
AllowOverride All
</Directory>
Include /etc/letsencrypt/options-ssl-apache.conf
SSLCertificateFile /etc/letsencrypt/live/domain_url/cert.pem
SSLCertificateKeyFile /etc/letsencrypt/live/domain_url/privkey.pem
SSLCertificateChainFile /etc/letsencrypt/live/domain_url/chain.pem
</VirtualHost>
</IfModule>
Some of the relevant parts of the httpd.conf file :
<Directory />
AllowOverride none
Require all denied
</Directory>
DocumentRoot "/var/www/html"
<Directory "/var/www">
Options Indexes FollowSymLinks
AllowOverride All
Require all granted
</Directory>
<Directory "/var/www/html">
Options Indexes FollowSymLinks
AllowOverride All
Require all granted
</Directory>
<Directory "/var/www/MyApp">
Options Indexes FollowSymLinks
AllowOverride All
Require all granted
</Directory>
When I run my website with only these files, the Homepage runs perfectly, and navigation within my angular app works, but trying to load any url other than "www.domain.com/" (for exemple : "www.domain.com/about") returns an Error 404 Not Found.
I then added the following .htaccess file in 'var/www/MyApp/html' (mostly generated from an online htaccess generator, I only added a Require all granted and I don't even know if it's useful, I'm very new to apache configuration) :
Require all granted
<IfModule mod_rewrite.c>
RewriteEngine On
# Redirection of requests to index.html
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -f [OR]
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -d
RewriteRule ^.*$ - [NC,L]
# Redirect all non-file routes to index.html
RewriteRule ^(?!.*\.).*$ index.html [NC,L]
</IfModule>
# Disable browser caching for all files that don't get a hash string by Angular.
<FilesMatch "^(?!.*\.([0-9a-z]{20})\.).*$">
<IfModule mod_headers.c>
FileETag None
Header unset ETag
Header unset Pragma
Header unset Cache-Control
Header unset Last-Modified
Header set Pragma "no-cache"
Header set Cache-Control "max-age=0, no-cache, no-store, must-revalidate"
Header set Expires "Mon, 1 Jan 1900 00:00:00 GMT"
</IfModule>
</FilesMatch>
After adding this .htaccess, I now get an error 403 Forbidden whenever I try to load anything including my homepage.
I'm completely lost on what I did wrong and can't seem to find any solution on the web so any help would be appreciated.
CodePudding user response:
Ok I finally found a solution that works for me :
I replaced the first half of my htaccess file to the following (and got rid of the Require all granted) :
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.html$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.html [L]
</IfModule>
And it finally seems to work, Apache doesn't fire 403 or 404 errors anymore !
CodePudding user response:
You need to configure rewrite rules with fallback to the index file
Angular's official docs have examples on how to do it for mainstream web servers.
tl;dr;
In your .htaccess
you need rules that implement fallback to the index file:
RewriteEngine On
# If an existing asset or directory is requested go to it as it is
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -f [OR]
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -d
RewriteRule ^ - [L]
# If the requested resource doesn't exist, use index.html
RewriteRule ^ /index.html