Several questions for the same topic on the net but nothing worked.
I have a serverXYZ running an Angular app, a backend tomcat webapp for authentication, a nginx server. Angular app on port 4200, tomcat app on 8080. Everything is on the same host.
The angular app has a environment.ts file (the commented string is one of my tests, see nginx conf below):
export const environment = {
production: false,
// apiUrl: 'http://serverXYZ:444/api'
apiUrl: 'http://localhost:8080/backend'
};
The nginx conf:
server {
listen 444;
server_name serverXYZ;
location / {
proxy_pass http://localhost:4200;
//websocket
proxy_set_header HOST $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass_request_headers on;
proxy_http_version 1.0;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_read_timeout 120s;
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
add_header 'Access-Control-Max-Age' 1728000;
add_header 'Content-Type' 'text/plain; charset=utf-8';
add_header 'Content-Length' 0;
return 204;
}
if ($request_method = 'POST') {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';
}
if ($request_method = 'GET') {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';
}
}
location /api {
proxy_pass http://localhost:8080/backend;
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
add_header 'Access-Control-Max-Age' 1728000;
add_header 'Content-Type' 'text/plain; charset=utf-8';
add_header 'Content-Length' 0;
return 204;
}
if ($request_method = 'POST') {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';
}
if ($request_method = 'GET') {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';
}
}
}
The backend tomcat app has this in its web.xml:
...
<!-- Tomcat built in CORS implementation -->
<!-- https://tomcat.apache.org/tomcat-7.0-doc/config/filter.html -->
<filter>
<filter-name>CorsFilter</filter-name>
<filter-class>org.apache.catalina.filters.CorsFilter</filter-class>
<init-param>
<param-name>cors.allowed.headers</param-name>
<param-value>Content-Type,X-Requested-With,accept,Origin,Access-Control-Request-Method,Access-Control-Request-Headers,Authorization</param-value>
</init-param>
<init-param>
<param-name>cors.allowed.methods</param-name>
<param-value>GET,POST,HEAD,OPTIONS,PUT,DELETE</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CorsFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- End of built in CORS implementation -->
...
I use my computer, open the browser, With the described conf if I connect to http://serverXYZ:444 the app shows up but I get CORS error on authentication (Failed CORS request). If instead I use the configuration with the commented string in environment.ts , the browser authentication doesn't say CORS, just 403. Of course the authentication api is tested and working.
I'm clueless, what's wrong? Also, solving this with nginx is my preferred way but not mandatory.
Edit: I add one more info, I'm launching the angular app with "ng serve --disableHostCheck=true" . I don't know if maybe the "--publicHost" option or "--host 0.0.0.0" should be used in this case?
Edit 2: Another thing I see just now, Firefox doesn't give me any error on OPTIONS request, just Cors on POST.
Have you already seen the famous If is Evil article? The article states that
For the most cases those clarifications are too strict, usually you can safely use any nginx directive from
ngx_http_rewrite_module
within theif
block. However using any other directive including theadd_header
one is really unsafe and can lead to the unpredictable results. Here is how I would write such a configuration: