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.
Related
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.
I am trying to make a dynamic CORS proxy using Nginx, so I can use multiple API's from my front-end code without any CORS errors. My current way is using multiple location blocks, one for each domain, which works, but I would rather have a dynamic solution. My idea is to use x-proxy-target to specify the upstream hostname, and pass on the pathname. Nginx is running in Docker containers on Kubernetes, hence 10.245.0.10 being the resolver.
This works perfectly, and sends the CORS headers that are set at the bottom using add_header
location / {
default_type application/json;
if ($http_x_proxy_target = "") {
return 400 '{"message": "No x-proxy-target header", "code": "PROXY_TARGET_NOT_SET"}';
}
resolver 10.245.0.10 [::1];
set $cors '*';
if ($http_origin != "") {
set $cors $http_origin;
}
if ($request_method = "OPTIONS") {
add_header Access-Control-Allow-Origin $cors always;
add_header Access-Control-Allow-Methods "GET, POST, OPTIONS" always;
add_header Access-Control-Allow-Headers * always;
return 204;
}
proxy_hide_header Access-Control-Allow-Headers;
proxy_hide_header Access-Control-Expose-Headers;
proxy_hide_header Access-Control-Allow-Credentials;
proxy_hide_header Access-Control-Allow-Origin;
proxy_set_header x-proxy-target '';
proxy_set_header User-Agent $http_user_agent;
proxy_set_header Connection $http_connection;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Origin https://$http_x_proxy_target;
proxy_set_header Host $http_x_proxy_target;
proxy_set_header Referer https://$http_x_proxy_target/;
proxy_pass https://google.com/;
add_header Access-Control-Allow-Headers * always;
add_header Access-Control-Expose-Headers * always;
add_header Access-Control-Allow-Credentials true always;
add_header Access-Control-Allow-Origin $cors always;
}
But when I change the proxy_pass to use the supplied upstream:
location / {
default_type application/json;
if ($http_x_proxy_target = "") {
return 400 '{"message": "No x-proxy-target header", "code": "PROXY_TARGET_NOT_SET"}';
}
resolver 10.245.0.10 [::1];
set $cors '*';
if ($http_origin != "") {
set $cors $http_origin;
}
if ($request_method = "OPTIONS") {
add_header Access-Control-Allow-Origin $cors always;
add_header Access-Control-Allow-Methods "GET, POST, OPTIONS" always;
add_header Access-Control-Allow-Headers * always;
return 204;
}
proxy_hide_header Access-Control-Allow-Headers;
proxy_hide_header Access-Control-Expose-Headers;
proxy_hide_header Access-Control-Allow-Credentials;
proxy_hide_header Access-Control-Allow-Origin;
proxy_set_header x-proxy-target '';
proxy_set_header User-Agent $http_user_agent;
proxy_set_header Connection $http_connection;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Origin https://$http_x_proxy_target;
proxy_set_header Host $http_x_proxy_target;
proxy_set_header Referer https://$http_x_proxy_target/;
proxy_pass $scheme://$http_x_proxy_target$uri$is_args$args;
add_header Access-Control-Allow-Headers * always;
add_header Access-Control-Expose-Headers * always;
add_header Access-Control-Allow-Credentials true always;
add_header Access-Control-Allow-Origin $cors always;
}
I get the correct response using Postman, but the CORS headers are not set. I have tried moving the add_header lines to above the proxy_pass, to no avail. To me, this seems like a possible bug in Nginx, although I might just be making an obvious mistake. I can't find any mention of this problem anywhere, although it is a very specific usecase.
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';
}
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';
}
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;
}