CORS绝对是最糟糕的。我正在尝试查找POST请求在next.js
-> NGINX
-> docker-compose
-> clojure
中的何处失败,它是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是最高阶的反模式。
确定
我有一个next.js
的前端dockerfile(导入点是公开了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
(公开了port 4000
)的dockerfile:
FROM java:8-alpine
WORKDIR /
COPY ./target/uberjar/ .
EXPOSE 4000
CMD java -jar clojure_play-0.1.0-SNAPSHOT-standalone.jar
以下是docker-compose
文件,其中两个端口3000
和4000
均已适当映射,并且有一个webserver
服务将NGINX加载为反向代理:
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中网桥所提供的服务名称(每个服务名称都映射到适当的端口3000
或4000
)。我对请求标头也有些傻,但是我正尝试尽可能地将其打开:
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
服务器,然后返回200。相反,我收到上面的CORS错误。
有人对如何调试此方法有任何想法吗?
答案 0 :(得分:0)
删除所有位置标头上的重复设置。
添加以下代码。
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错误。