rest api direct vs nginx proxy - nginx

I am a newbie in nginx and CORS and finding it challenging getting this right.
I have rest services hosted on a server which blocks CORS so installed nginx to proxy for rest call. What works:
rest api call (from angular code) to backend server after enabling CORS
rest api call (from chrome) to frontend nginx server which has cors enables
What doesn't work: rest api call (from angular code) to frontend nginx
I think the CORS part work as I do not see that error anymore but angular is getting a null response.
For above scenarios, I have tried using GET and POST methods. Response code is 200 OK even for failed scenario.
Here is the nginx conf:
upstream myserver {
server myserver.com:8443;
}
server {
listen 443 ssl;
listen [::]:443 ssl;
server_name myserver.com;
ssl_certificate /some.crt;
ssl_certificate_key /some.key;
location /rest-service/ {
# Simple requests
if ($request_method ~* "(GET|POST)") {
add_header "Access-Control-Allow-Origin" *;
}
# Preflighted requests
if ($request_method = OPTIONS ) {
add_header "Access-Control-Allow-Origin" *;
add_header "Access-Control-Allow-Methods" "GET, POST, OPTIONS, HEAD";
add_header "Access-Control-Allow-Headers" "Authorization, Origin, X-Requested-With, Content-Type, Accept";
return 200;
}
proxy_pass_header Server;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Scheme $scheme;
proxy_set_header X-NginX-Proxy true;
proxy_connect_timeout 5;
proxy_read_timeout 240;
proxy_intercept_errors on;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass https://myserver/rest-service/;
proxy_ssl_trusted_certificate /some.pem;
proxy_ssl_verify off;
proxy_ssl_session_reuse on;
}
}
Here is the angular/typescript code (running from loaclhost):
ngOnInit() {
let url='https://myserver.com/rest-service/login?login=admin&password=password';
this.http.get(this.url).subscribe((response) => {console.log(response); });
}

I think I figured out the issue and posting it here; hope it helps someone.
Following worked:
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' 'http://localhost:4200' always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always;
add_header 'Access-Control-Allow-Headers' 'Origin,Keep-Alive,User-Agent,Cache-Control,Content-Type,Accept' always;
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 = 'GET' ) {
add_header 'Access-Control-Allow-Origin' 'http://localhost:4200' always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always;
add_header 'Access-Control-Allow-Headers' 'Origin,Keep-Alive,User-Agent,Cache-Control,Content-Type,Accept' always;
add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';
}
if ( $request_method = 'POST' ) {
add_header 'Access-Control-Allow-Origin' 'http://localhost:4200' always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always;
add_header 'Access-Control-Allow-Headers' 'Origin,Keep-Alive,User-Agent,Cache-Control,Content-Type,Accept' always;
add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';
}

Related

Allowing CORS for api.glossgenius.com

I need assistance, i am unsure how to make the API response from "api.glossgenius.com" work properly to get elements of the site working.
https://studio21md.com/portfolio
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://api.glossgenius.com/v3/web/portfolio_images?slug=meganhammett. (Reason: CORS header ‘Access-Control-Allow-Origin’ missing).
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://api.glossgenius.com/v3/web/portfolio_images?slug=meganhammett. (Reason: CORS request did not succeed).
Can anyone assist on Nginx how i would solve this specific issue?
Here is my config, Thank you for your assistance.
server {
listen 80;
server_name www.studio21md.com studio21md.com;
#charset koi8-r;
#access_log logs/host.access.log main;
location / {
proxy_pass https://meganhammett.glossgenius.com;
}
Please use this config in nginx.
server {
listen 80;
server_name www.studio21md.com studio21md.com;
#charset koi8-r;
#access_log logs/host.access.log main;
location / {
add_header 'Access-Control-Allow-Origin' 'https://api.glossgenius.com';
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Headers' 'Authorization,Accept,Origin,DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range';
add_header 'Access-Control-Allow-Methods' 'GET,POST,OPTIONS,PUT,DELETE,PATCH';
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' 'https://api.glossgenius.com';
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Headers' 'Authorization,Accept,Origin,DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range';
add_header 'Access-Control-Allow-Methods' 'GET,POST,OPTIONS,PUT,DELETE,PATCH';
add_header 'Access-Control-Max-Age' 1728000;
add_header 'Content-Type' 'text/plain charset=UTF-8';
add_header 'Content-Length' 0;
return 204;
}
proxy_pass https://meganhammett.glossgenius.com;
proxy_redirect off;
proxy_set_header host $host;
proxy_set_header X-real-ip $remote_addr;
proxy_set_header X-forward-for $proxy_add_x_forwarded_for;
}
}
As I understand you do not have access to the backend of api.glossgenius and you are calling it from the javascript.
I would try calling that glossgenius api from your backend. And make endpoint so that your frontend calls your backend. You do not have cors problems from your frontend calling your backend as I understand.

nginx add_header called multiple times

I'm trying to enable CORS on nginx and I have the following server block.
server {
listen 443;
server_name myserver.earth;
ssl on;
ssl_certificate cert.crt;
ssl_certificate_key private.key;
ssl_protocols TLSv1.2;
ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA';
ssl_prefer_server_ciphers on;
ssl_dhparam dhparams.pem;
client_max_body_size 256M;
location / {
proxy_pass http://localhost:9000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
# CORS stuff only appears to be necessary in one block
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
#
# Custom headers and headers various browsers *should* be OK with but aren't
#
add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range,Authorization';
#
# Tell client that this pre-flight info is valid for 20 days
#
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,Authorization';
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,Authorization';
add_header 'Access-Control-Expose-Headers' 'Content-Length,Content-Range';
}
}
}
When I make an HTTP OPTIONS request to a method, I get the following error "'Access-Control-Allow-Origin' header contains multiple values '*, ', but only one is allowed.". It looks like the statement "add_header 'Access-Control-Allow-Origin' '';" has been called twice.
I don't understand how this has happened, and what I can do to prevent it?

NGINX Configs guidance needed for socket.io

The codes below are under my sites-enabled folder in nginx ..
however, the lines where i "add_header 'Access-Control-Allow-Origin' '*';" and add_header "'Access-Control-Allow-Credentials' 'true';" after the if statements are causing my socket to have multiple headers. can i seek suggestions to work around this ?
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name devapi.doctoroneworld.com;
location / {
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Methods' 'GET, POST, PUT, DELETE, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization';
add_header 'Access-Control-Max-Age' 1728000
add_header 'Content-Type' 'text/plain charset=UTF-8';
add_header 'Content-Length' 0;
return 204;
}
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Headers' 'Origin, X-Requested-With, Content-Type, Accept, If-Modified-Since, Authorization';
add_header 'Access-Control-Allow-Methods' 'POST, GET, PUT, DELETE, OPTIONS';
proxy_set_header Content-Type 'application/json';
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-NginX-Proxy true;
proxy_pass http://localhost:9000/;
proxy_ssl_session_reuse off;
proxy_set_header Host $http_host;
proxy_cache_bypass $http_upgrade;
proxy_redirect off;
}
}
this is what I've added in the above code : and i commented out the add_headers that were affecting the socket requests
set $cors '';
if ($request_uri !~ '^/socket.io-client') {
set $cors 'true';
}
if ($cors = 'true') {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Credentials' 'true';
}

enabe CORS form any site/localhost in nginx

I have configure nginx for node, and successfully run simple express app,
var express = require('express')
var app = express()
app.get('/', function (req, res) {
res.json({
"name":"Rajesh"
})
})
app.listen(8010, function () {
console.log('Example app listening on port 8010!')
})
using postman I can see request on vpsip:8010 as json string successfuly.
But when I use html+jquery ajax code ::
$.ajax({
method: "GET",
url: "http://vpsip:8010/"
})
.done(function( msg ) {
alert( "Data Saved: " + msg );
});
I get error
No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://anything' is therefore not allowed.
my nginx default file is
location /exapi {
proxy_pass http://localhost:8010/exapi;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' '*';
#
# Om nom nom cookies
#
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
#
# Custom headers and headers various browsers *should* be OK with but aren't
#
add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
#
# Tell client that this pre-flight info is valid for 20 days
#
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-Credentials' 'true';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
}
if ($request_method = 'GET') {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
}
}
Can anyone please tell me how to enable CORS request on my nginx(in my vps), so that I can create my express apis.
Got same problem time ago, for this API service (http://vps264757.ovh.net/GameFactoryService/resources/maze?w=50&h=50 / http://vps264757.ovh.net/maze.html). Here my default sites-enabled that works properly, proxying to glassfish at localhost/18000. Hope it helps :
#Glassfish
location /GameFactoryService/ {
index index.html;
add_header Access-Control-Allow-Origin $http_origin;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-NginX-Proxy true;
proxy_ssl_session_reuse off;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://127.0.0.1:18000/GameFactoryService/;
}
#static content
location / {
root /usr/share/nginx_static_content;
}
error_page 500 501 502 503 504 505 506 507 508 509 510 511 /50x.html;
#error
location = /50x.html {
add_header Access-Control-Allow-Origin $http_origin;
internal;
}

Nginx proxy_pass missing error body

Below is a pretty standard nginx proxy_pass setup:
server {
listen 80;
server_name ireport.jungdigital.com;
access_log /var/log/nginx/ireport.access.log;
root /var/www/ireport.jungdigital.com/dist;
index index.html index.htm;
location / {
}
location /api/ {
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Methods' 'GET, PUT, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Reques
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-Credentials' 'true';
add_header 'Access-Control-Allow-Methods' 'GET, PUT, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Reques
}
if ($request_method = 'PUT') {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Methods' 'GET, PUT, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Reques
}
if ($request_method = 'GET') {
add_header 'Access-Control-Allow-Origin' '*';
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Allow-Methods' 'GET, PUT, POST, OPTIONS';
add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Reques
}
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-NginX-proxy true;
proxy_set_header Host ireport.somehost.org;
proxy_pass http://ireport_dyndns/api/;
proxy_ssl_session_reuse off;
proxy_redirect off;
}
}
The API that I'm proxying returns response body's that contain error information for 400, 404, and 500 error codes. For example, on a 404, my response body might look like:
{
"errorCode": "TOKEN_NOT_FOUND",
"errorMessages": [
"Could not find a matching authorization token."
]
}
If I perform the request without the proxy, I get the response bodies for the errors.
If I use the nginx proxy, for some reason the response bodies are swallowed by nginx and I can't even see a response at all in my web browser Network tab.
Is there a way to tell Nginx to return response bodies for error codes in a proxy_pass?
I run into same question recently.
And the last anwser is that: add proxy header Upgrade
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
My full config as following:
upstream cloud-api {
server 127.0.0.1:8089;
}
client_max_body_size 20M;
client_header_buffer_size 8k;
large_client_header_buffers 4 16k;
server {
listen 8001;
access_log /data/senseid-cloud-log/senseid-cloud-api-access.log;
error_log /data/senseid-cloud-log/senseid-cloud-api-error.log warn;
location / {
proxy_http_version 1.1;
proxy_set_header Host $http_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_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_read_timeout 300s;
proxy_pass http://cloud-api;
}
}
And you could catch 500/401 .etc error body
Details : http://nginx.org/en/docs/http/websocket.html
Hope to give you some help.
See How to add a response header on nginx when using proxy_pass?
Per Alexey's comment - "browsers need headers to allow access to response body. I guess, you need always flag for add_header"
Since nginx 1.7.5 you can use the keyword always to include headers even in error responses - so you can setup your nginx.conf as follow:
-
server {
server_name .myserver.com
location / {
proxy_pass http://mybackend;
add_header X-Upstream $upstream_addr always;
}
}
Today I move Laravel 5.2 from IIS 8.5 to Ubuntu 16.04 (Nginx 1.10.0 - PHP-FPM 7.0.10), I have same problem. The body response from server are always empty when request from Angular2. But the postman still get body on response.
So that must be problem with request headers.
This config help me solved problem above:
add_header 'Access-Control-Allow-Origin' '*' 'always';
add_header 'Access-Control-Allow-Credentials' 'true' 'always';
add_header 'Access-Control-Allow-Methods' 'GET, POST, DELETE, PUT, OPTIONS, HEAD' 'always';
add_header 'Access-Control-Allow-Headers' 'Authorization, Content-Type, X-Requested-With' 'always';
Third parameters for add_header only available in recent nginx version.

Resources