问题
I'm slowly losing my mind over a very stupid issue I'm having.
I have a socket.io/express app uploaded to Digital Ocean as a Docker setup.
To allow https, I am using caddy as part of my Docker setup to allow for automatic https.
I've been trying to connect to this setup via my domain and from my local React app that lives on localhost:3000. But I am constantly getting the following error:
Access to XMLHttpRequest at 'https://mediaserver.domain.dev/socket.io/?EIO=3&transport=polling&t=N5BXNK2' from origin 'http://localhost:3000' has been blocked by CORS policy: The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'. The credentials mode of requests initiated by the XMLHttpRequest is controlled by the withCredentials attribute.
I know there have been a lot of SO questions about this before and believe me when I say I tried almost all of them.
- I tried changing the options of the cors middleware
- I tried adding my own middleware and setting headers specifically
- I tried using localhost:3000 as origin
- ...
But nothing seems to work. I have currently no idea what I can still do to fix this.
So any help would be welcome.
My docker-compose file looks as follows:
version: '3.6'
services:
media-server:
build:
dockerfile: Dockerfile
context: ./
ports:
- "8080:5000"
expose:
- "5000"
caddy:
image: abiosoft/caddy:0.11.0
depends_on:
- "media-server"
restart: always
ports:
- "80:80"
- "443:443"
volumes:
- /root/Caddyfile:/etc/Caddyfile
- /root/.caddy:/root/.caddy
My Caddyfile is as follows:
https://mediaserver.domain.dev {
proxy / http://media-server:8080 {
websocket
transparent
}
cors
}
And my server setup looks as follows:
import cors from 'cors';
import express from 'express';
import socket from 'socket.io';
import { intialiseWebSocketConnection } from './socketio';
const app = express();
app.use(cors());
const server = app.listen(5000, function () {
console.log('Server is connectedd on *:5000');
});
const io = socket.listen(server);
intialiseWebSocketConnection(io);
回答1:
You are attempting to make a cross-origin request with the credentials flag set and the Access-Control-Allow-Origin
set to any (*). This is not allowed for security reasons. There are two ways to solve the problem. If you don't need to send credentials make sure the credentials flag is false. That is, if you are using an XMLHttpRequest
make sure withCredentials
is not true (it is false by default). If you are using the Fetch API
make sure Request.credentials
is set to "omit"
.
If you do need to send credentials for some reason, you have to set the Access-Control-Allow-Origin
in your server's response to the origin from where you are sending requests to the server and not to any (*).
To figure out what your origin is just check to what the Origin
header is set to in the requests you send to the server.
By default cors()
sets the Access-Control-Allow-Origin
to *. Try changing it to:
cors({
origin: "http://localhost:3000",
credentials: true
});
Also note Chrome does not support localhost
as an origin. To get around that you can start Chrome with the --disable-web-security
flag during development.
回答2:
There's a simple way to bypass CORS errors for socket.io connections. By default socket.io starts each connection with several regular http calls. If things go well, it converts to a webSocket transport (and runs socket.io over the webSocket transport). Those initial http calls are subject to CORs restrictions.
But, if you tell socket.io to just start out with the webSocket transport right away, then you are not subject to CORs restrictions. You can do that in the client by doing this:
const socket = io({transports: ['websocket']});
Even though a webSocket connection always starts with one http request, that particular http request (with the appropriate upgrade
header set is not subject to CORs restrictions.
The only downside to this (that I'm aware of) is that your code would not run in a browser that does not support webSockets. That would be a really, really old browser. Even IE10 (released in 2012) supports webSockets and all modern browsers have supported them since at least 2013. I'm actually not quite sure why socket.io still has their http polling as the default as it's far less efficient on the network to start out every connection. Anyway, you can easily bypass it with io({transports: ['websocket']});
.
来源:https://stackoverflow.com/questions/61047220/socket-io-and-express-app-not-connecting-due-to-cors-error-the-value-of-the-a