簡體   English   中英

CORS 在 Docker-Compose Stack w/NGINX 中某處失敗 - 找不到它

[英]CORS failing somewhere in Docker-Compose Stack w/NGINX - can't find it

CORS 絕對是最糟糕的。 我試圖在next.js -> next.js -> NGINX docker-compose -> clojure一個 POST 請求失敗的 CORS。 我有以下錯誤消息,但沒有說明它來自堆棧中的哪個位置(是的!):

Cross-Origin Request Blocked: 
The Same Origin Policy disallows reading the remote resource 
at http://example.com/back/email. 
(Reason: CORS header ‘Access-Control-Allow-Origin’ missing).

axios error from PostRequest at endpt  /email :  Error: "Network Error"

所以...我將寫出請求觸及的每個部分,並嘗試表明它應該通過。 如果有人能找到此管道中請求失敗或 CORS 未正確打開的位置,請告訴我。 CORS 是最高階的反模式。

好的

我有一個前端dockerfile next.js (進口的一點是, port 3000暴露):

FROM node:10
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
EXPOSE 3000
CMD [ "npm", "start" ]

后端有一個用於clojure的 dockerfile(暴露了port 4000 ):

FROM java:8-alpine
WORKDIR /
COPY ./target/uberjar/ .
EXPOSE 4000
CMD java -jar clojure_play-0.1.0-SNAPSHOT-standalone.jar

這是docker-compose文件,其中正確映射了端口30004000以及加載 NGINX 作為反向代理的webserver服務:

version: '3'

services:
  frontend:
    build:
      context: .
      dockerfile: Dockerfile
    container_name: frontend
    restart: unless-stopped
    ports: 
      - "3000:3000"
    networks:
      - app-network

  backend:
    build:
      context: ./backend/clojure_play
      dockerfile: Dockerfile
    container_name: backend
    restart: unless-stopped
    ports: 
      - "4000:4000"
    networks:
      - app-network


  webserver:
    image: nginx:mainline-alpine
    container_name: webserver
    restart: unless-stopped
    ports:
      - "80:80"
    volumes:
      - web-root:/var/www/html
      - ./nginx-conf:/etc/nginx/conf.d
    depends_on:
      - frontend
      - backend
    networks:
      - app-network

volumes:
  web-root:
    driver: local

networks:
  app-network:
    driver: bridge  

這是我的NGINX配置。 請注意,我代理傳遞到我的 docker compose 中的網橋提供的服務名稱(每個都映射到適當的端口, 30004000 )。 我對請求標頭也有點傻,但我正在嘗試盡可能多地打開它:

server {
        listen 80;
        listen [::]:80;

        root /var/www/html;
        index index.html index.htm index.nginx-debian.html;

        # server_name example.com www.example.com;
        # server_name localhost;


        server_name example.me www.example.com;

        location / { 
          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';
             #
             # 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';
             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';
          }
          proxy_pass http://frontend:3000;
          proxy_http_version 1.1;
          proxy_set_header Upgrade $http_upgrade;
          proxy_set_header Connection "upgrade";
        }
        location /back/ {
          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';
             #
             # 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';
             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';
          }
          proxy_pass http://backend:4000;
          proxy_http_version 1.1;
          proxy_set_header Upgrade $http_upgrade;
          proxy_set_header Connection "upgrade";
          proxy_set_header X-Forwarded-For $remote_addr;
          proxy_set_header Host $http_host;
        }


        location ~ /.well-known/acme-challenge {
                allow all;
                root /var/www/html;
        }
}

最后,我的后端clojure應用程序有一個名為wrap-cors的實用程序,它應該為我的站點提供 cors 支持:

(defn -main
  "this is main"
  [& args]

  (println "hello there main")

  (run-server
   (wrap-cors
     (wrap-json-body my-routes {:keywords? true :bigdecimals? true})
     :access-control-allow-origin [#"http://www.example.me"]
     :access-control-allow-methods [:get :put :post :delete] 
   )
  {:port 4000})

  #_(run-server my-routes {:port 8080})
)


就是這樣。

當我在next.js前端發出請求時,我希望客戶端的計算機會向www.example.com/back/email發出 http 請求,該請求將進入 NGINX 代理,點擊/back/位置,發送/email向我的clojure服務器/email ,然后將返回 200。相反,我收到了上面的 CORS 錯誤。

有沒有人知道如何調試這個?

刪除所有位置標題上的重復設置。

添加以下代碼。

location / {

            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' 'Accept,Content-Type';
}

在設置上述配置時,我能夠解決 CORS 錯誤。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM