英文:
CORS error when accessing NodeJS express api in Docker container
问题
在主机上运行时,我的NodeJS API和NextJS应用程序位于单独的Docker容器中,一切都正常工作,但在Docker容器内运行时,出现了CORS错误。
我的Express配置在API中如下:
app.use(cors({
credentials: true,
origin: 'http://localhost:3000/' // 允许前端运行在端口3000上
}));
app.use(cookieParser());
app.use(bodyParser.json());
app.use(urlencoded({ extended: true }));
app.use(json());
app.enable("trust proxy");
app.use(methodOverride());
在前端NextJS axios配置中如下:
const axiosInstance = axios.create({ baseURL: 'http://localhost:4000/', withCredentials: true });
当我从主机机器上运行API时,一切正常,但在Docker中使用相同的配置时出现CORS错误。
英文:
I have NodeJS api and NextJS application in Separate docker containers when I'm in host machine its working fine, but when I'm running inside docker containers its giving CORS error.
My express config in API
app.use(cors({
credentials: true,
origin: 'http://localhost:3000/' // Allowing front-end running port 3000
}));
app.use(cookieParser());
app.use(bodyParser.json());
app.use(urlencoded({ extended: true }));
app.use(json());
app.enable("trust proxy");
app.use(methodOverride());
In front-end APP NextJS axios config
const axiosInstance = axios.create({ baseURL: 'http://localhost:4000/', withCredentials: true });
Its woking fine when im running API from host machine, with same configuration its giving CORS error in Docker.
答案1
得分: 1
以下是翻译好的部分:
"我能看到你的API配置似乎是正确的,但在你的NextJS中创建pages/api/whatever.js
,然后从处理程序中调用你的API。
import axios from 'axios';
axios.defaults.withCredentials = true;
export default async function handler(req, res){
try {
const response = axios.post('http://localhost:4000/<your_login_api_URL>', req.body)
}catch(error) {
// 处理错误
}
}"
这将有效,并且是一种更安全的方式来隐藏你的后端API调用,不让前端直接访问。
<details>
<summary>英文:</summary>
As i can see your API configuration seems correct, but in your NextJS create pages/api/whatever.js and call your API from handler
import axios from 'axios';
axios.defaults.withCredentials = true;
export default async function handler(req, res){
try {
const response = axios.post('http://localhost:4000/<your_login_api_URL>', req.body)
}catch(error) {
// handle error here
}
}
this will work and its safer way to mask your back end API calls from front end.
</details>
# 答案2
**得分**: 0
将每个`localhost` + `port`添加到`cors`选项中(_我只是为了示例留下了一些其他选项,与您的问题无关_):
```javascript
// 跨域中间件选项
const options: cors.CorsOptions = {
allowedHeaders: [
'X-ACCESS_TOKEN',
'Access-Control-Allow-Origin',
'Authorization',
'Origin',
'x-requested-with',
'Content-Type',
'Content-Range',
'Content-Disposition',
'Content-Description',
],
credentials: true,
methods: 'GET,HEAD,OPTIONS,PUT,PATCH,POST,DELETE',
origin: [
'http://localhost:5001',
'http://localhost:50000',
],
preflightContinue: false,
};
const app = express();
const corsOpts = cors(options);
// 添加跨域中间件
app.use(corsOpts);
英文:
Add each localhost
+ port
to the cors
options (I left some other options just for example, not relevant to your question though):
//options for cors midddleware
const options: cors.CorsOptions = {
allowedHeaders: [
'X-ACCESS_TOKEN',
'Access-Control-Allow-Origin',
'Authorization',
'Origin',
'x-requested-with',
'Content-Type',
'Content-Range',
'Content-Disposition',
'Content-Description',
],
credentials: true,
methods: 'GET,HEAD,OPTIONS,PUT,PATCH,POST,DELETE',
origin: [
'http://localhost:5001',
'http://localhost:50000',
],
preflightContinue: false,
};
const app = express();
const corsOpts = cors(options);
//add cors middleware
app.use(corsOpts);
</details>
# 答案3
**得分**: 0
这是常见的问题,有许多解决方案。
正确的解决方案取决于您的需求。更简单的解决方案是在运行Docker容器时使用NGINX作为反向代理。
**NGINX Docker示例**
```dockerfile
FROM nginx:alpine
WORKDIR /etc/nginx
COPY ./nginx.conf ./conf.d/default.conf
EXPOSE 80
ENTRYPOINT ["nginx"]
CMD ["-g", "daemon off;"]
将其构建为cors
docker build -t cors .
最后确保nginx.conf允许来自请求的源
add_header 'Access-Control-Allow-Origin' '*';
NGINX配置示例
upstream api {
# 可以是host.docker.internal - 适用于Docker的Mac/Windows - 主机本身
# 可以是您的API在适当的域中
# 可以是同一网络中的其他容器,如container_name:port
server url:port;
}
server {
listen 80;
server_name localhost;
location / {
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Max-Age' 1728000;
add_header 'Access-Control-Allow-Origin' '*';
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 'Content-Type' 'application/json';
add_header 'Content-Length' 0;
return 204;
}
add_header 'Access-Control-Allow-Origin' '*';
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';
proxy_pass http://api/;
}
}
英文:
This is common issue many solutions.
The correct solution depends on your requirements.The simpler solution is to run the docker container with NGINX acting as reverse proxy.
Example of nginx docker
FROM nginx:alpine
WORKDIR /etc/nginx
COPY ./nginx.conf ./conf.d/default.conf
EXPOSE 80
ENTRYPOINT [ "nginx" ]
CMD [ "-g", "daemon off;" ]
Build it as cors
docker build -t cors .
Finally make sure that nginx.conf allowing origins from request
add_header 'Access-Control-Allow-Origin' '*';
Example of nginx.config
upstream api {
# Could be host.docker.internal - Docker for Mac/Windows - the host itself
# Could be your API in a appropriate domain
# Could be other container in the same network, like container_name:port
server url:port;
}
server {
listen 80;
server_name localhost;
location / {
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Max-Age' 1728000;
add_header 'Access-Control-Allow-Origin' '*';
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 'Content-Type' 'application/json';
add_header 'Content-Length' 0;
return 204;
}
add_header 'Access-Control-Allow-Origin' '*';
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';
proxy_pass http://api/;
}
}
答案4
得分: -1
Add this line to your package.json
file. then rebuild your container and start the app.
"proxy": "http://localhost:4000",
英文:
Add this line to your package.json
file. then rebuild your container and start the app.
"proxy": "http://localhost:4000",
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论