CORS错误在访问Docker容器中的NodeJS Express API时发生。

huangapple go评论90阅读模式
英文:

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 });

CORS错误在访问Docker容器中的NodeJS Express API时发生。

CORS错误在访问Docker容器中的NodeJS Express API时发生。

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 &#39;axios&#39;;
    axios.defaults.withCredentials = true;

    export default async function handler(req, res){
       try {
         const response = axios.post(&#39;http://localhost:4000/&lt;your_login_api_URL&gt;&#39;, 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: [
&#39;X-ACCESS_TOKEN&#39;,
&#39;Access-Control-Allow-Origin&#39;,
&#39;Authorization&#39;,
&#39;Origin&#39;,
&#39;x-requested-with&#39;,
&#39;Content-Type&#39;,
&#39;Content-Range&#39;,
&#39;Content-Disposition&#39;,
&#39;Content-Description&#39;,
],
credentials: true,
methods: &#39;GET,HEAD,OPTIONS,PUT,PATCH,POST,DELETE&#39;,
origin: [
&#39;http://localhost:5001&#39;,
&#39;http://localhost:50000&#39;,
],
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 [ &quot;nginx&quot; ]
CMD [ &quot;-g&quot;, &quot;daemon off;&quot; ]

Build it as cors

docker build -t cors .

Finally make sure that nginx.conf allowing origins from request

add_header &#39;Access-Control-Allow-Origin&#39; &#39;*&#39;;

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 = &#39;OPTIONS&#39;) {
add_header &#39;Access-Control-Max-Age&#39; 1728000;
add_header &#39;Access-Control-Allow-Origin&#39; &#39;*&#39;;
add_header &#39;Access-Control-Allow-Headers&#39; &#39;Authorization,Accept,Origin,DNT,X-CustomHeader,Keep-Alive,User-Agent,
X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range&#39;;
add_header &#39;Access-Control-Allow-Methods&#39; &#39;GET,POST,OPTIONS,PUT,DELETE,PATCH&#39;;
add_header &#39;Content-Type&#39; &#39;application/json&#39;;
add_header &#39;Content-Length&#39; 0;
return 204;
}
add_header &#39;Access-Control-Allow-Origin&#39; &#39;*&#39;;
add_header &#39;Access-Control-Allow-Headers&#39; &#39;Authorization,Accept,Origin,DNT,X-CustomHeader,Keep-Alive,User-Agent,
X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Content-Range,Range&#39;;
add_header &#39;Access-Control-Allow-Methods&#39; &#39;GET,POST,OPTIONS,PUT,DELETE,PATCH&#39;;
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.

&quot;proxy&quot;: &quot;http://localhost:4000&quot;,

huangapple
  • 本文由 发表于 2023年1月5日 13:18:51
  • 转载请务必保留本文链接:https://go.coder-hub.com/75014128.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定