寒武

寒武

Nginx Reverse Proxy and CORS Cross-Origin Issue Resolution

1. Introduction#

In the previous article, it was mentioned that due to the slow loading speed of the website, a CDN was added to the website.

https://www.xiaozhengyang.com/notes/5

I have also gradually moved some referenced external resources to Upyun OSS, such as font files, and the json and png files that the blogger is working on. When I checked the traffic statistics on the Upyun console a few days later, the daily traffic for font files accounted for 99.9% of the total traffic, which was about 220M. It is important to note that this traffic is only used for updating articles and testing website speed. If the number of visitors increases in the future, or if there is malicious traffic, I can't imagine what can be done with only 15G of traffic in a month! I must find a solution!

2. Backend Nginx Reverse Proxy#

There are 3 solutions:

  1. Pay money
    ==Just pass==|| (It's impossible for me to pay, impossible in this lifetime~) ||
  2. Change to a free CDN address for font files on the internet
    ==Just pass==|| (Let's not talk about the fact that most addresses on the internet are from GitHub and Jsdeliver, and it's difficult to discover if they delete the files and run away) ||
  3. Directly request the backend local files
    ==bingo!== (Because my backend is directly connected to home broadband, why not make use of the 100M upload bandwidth?)

Let's get to work.

I encountered a problem when setting up reverse proxy with Nginx.

If I set it up so that when the front end accesses example.com/files, it proxies to the backend's 127.0.0.1/index address. The rule is written like this:

location ^~ /files/ {
    proxy_pass http://127.0.0.1/index; 
    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 REMOTE-HOST $remote_addr; 
    proxy_set_header Upgrade $http_upgrade; 
    proxy_set_header Connection "upgrade"; 
    proxy_set_header X-Forwarded-Proto $scheme; 
    proxy_http_version 1.1; 
    add_header X-Cache $upstream_cache_status; 
    add_header Strict-Transport-Security "max-age=31536000"; 
    add_header Cache-Control no-cache; 
}

At first glance, there doesn't seem to be a problem, but when we access this address, it will return a 404 Not Found error. Checking the console information, it shows that Nginx routed to the address example.com/files/index. The backend received the address with the front end address added, which is why it returns a 404 error.

The solution to this problem is simple. We need to exclude the suffix files from the address received by the backend. We just need to add a / at the end of the request address in the proxy_pass line. ^~/files/ means that it matches requests with the prefix files, and since proxy_pass ends with a /, it will directly append the path after /files/ to the end, effectively removing files.

location ^~ /files/ {
    proxy_pass http://127.0.0.1/index/; 
    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 REMOTE-HOST $remote_addr; 
    proxy_set_header Upgrade $http_upgrade; 
    proxy_set_header Connection "upgrade"; 
    proxy_set_header X-Forwarded-Proto $scheme; 
    proxy_http_version 1.1; 
    add_header X-Cache $upstream_cache_status; 
    add_header Strict-Transport-Security "max-age=31536000"; 
    add_header Cache-Control no-cache; 
}

Now we can successfully access the backend address.

3. CORS Cross-Origin Resource Sharing Problem#

After solving the problem, when we access the front-end address of the blog, we find that our font files still cannot be loaded correctly. Checking the console using F12, we find the following error message:

::: banner {error}
has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
:::

Reason#

Note

The requested resource did not set 'Access-Control-Allow-Origin', which means that the Nginx response header does not have Access-Control-Allow-Origin.

Solution#

Just add the following code to the position of the request header:

    add_header Access-Control-Allow-Origin *;
    add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS';
    add_header Access-Control-Allow-Headers 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization';
 
    if ($request_method = 'OPTIONS') {
        return 204;
    }

Statement Explanation#

Access-Control-Allow-Origin
By default, servers are not allowed to make cross-origin requests. By configuring Access-Control-Allow-Origin * on the Nginx server, it means that the server can accept requests from any origin, allowing all cross-origin requests.
Access-Control-Allow-Headers
This is to prevent the following error:
Request header field Content-Type is not allowed by Access-Control-Allow-Headers in preflight response.
This error means that the current request's Content-Type value is not supported. It is caused by making a request with the "application/json" type. This involves a concept called preflight request, please see the description of "preflight request" below.
Access-Control-Allow-Methods
This is to prevent the following error:
Content-Type is not allowed by Access-Control-Allow-Headers in preflight response.
Adding 204 response to OPTIONS
This is to handle the error of Nginx still refusing access when sending a POST request.
When sending a "preflight request", the OPTIONS method is used, so the server needs to allow this method.

4. Complete Code#

location ^~ /files/ {
   proxy_pass http://127.0.0.1/index/; 
   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 REMOTE-HOST $remote_addr; 
   proxy_set_header Upgrade $http_upgrade; 
   proxy_set_header Connection "upgrade"; 
   proxy_set_header X-Forwarded-Proto $scheme; 
   proxy_http_version 1.1; 
   add_header X-Cache $upstream_cache_status; 
   add_header Strict-Transport-Security "max-age=31536000"; 
   add_header Cache-Control no-cache; 
   add_header Access-Control-Allow-Origin *; 
   add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS'; 
   add_header Access-Control-Allow-Headers 'DNT,X-Mx-ReqToken,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization'; 

   if ($request_method = 'OPTIONS') {
       return 204;
   }
}




🎉🎉🎉The End🎉🎉🎉

This article is synchronized to xLog by Mix Space
The original link is https://www.xiaozhengyang.com/posts/life/nginx.html


Loading...
Ownership of this post data is guaranteed by blockchain and smart contracts to the creator alone.