Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[help wanted] Manually proxy settings to open connection with websocket.org #2260

Closed
yuzhva opened this issue May 19, 2017 · 9 comments
Closed

Comments

@yuzhva
Copy link

yuzhva commented May 19, 2017

Hey hi.

Since react-scripts@1.0.0 and higher create-react-app support manual proxy settings.

After creating app like

creare-react-app proxy-test

I installed socket yarn add socket.io-client, added proxy settings to the package.json like:

  "proxy": {
    "/": {
      "target": "ws://echo.websocket.org",
      "ws": true
    }
  }

changed src/App.js:

import io from 'socket.io-client';

class App extends Component {
  constructor(props) {
    super(props);
   
    this.socket = io();
  }

  componentDidMount() {
    console.log('MOUNTED');
    this.socket.on('connect', () => console.log('Connected to the socket');
  }

But when I'm opening the console, I can see that request actually goes through HTTP and I'm getting 404 response, because there is no that page (this page exists only for web socket request)

Request URL: http://localhost:3000/socket.io/?EIO=3&transport=polling&t=LmXuie9
Request Method: GET
Status Code: 404 Not Found

Expected behavior:

Request URL: wss://localhost:3000/socket.io/?EIO=3&transport=polling&t=LmXuie9
Request Method: GET
Status Code: 101 Web Socket Protocol Handshake

When I'll resolve that, will open PR with an example in improved documentation.

@gaearon
Copy link
Contributor

gaearon commented May 19, 2017

@jamesblight Mind looking at this?

@yuzhva
Copy link
Author

yuzhva commented May 19, 2017

As I found out when I'm using web sockets, it is not necessary to turn on the proxy, because requests are going not through http/https, but through ws/wss (example: this.socket = new WebSocket('wss://echo.websocket.org/');), so there should not be issues with CORS.

But I'm still confused about: why after setting proxy to use sockets like:

  "target": "link",
  "ws": true

url for request generates like: Request URL: http://localhost:3000/ instead of Request URL: wss://localhost:3000/.

sockets.io-client propose to fix this issue, with next server and client configuration:
socketio/socket.io#1942 (comment)

Looks like that is not an issue of create-react-app, so will open the question at StackOverflow.

P.S: will keep that issue up to date after closing.

@yuzhva yuzhva closed this as completed May 19, 2017
@gaearon
Copy link
Contributor

gaearon commented May 19, 2017

Thanks. If you find an answer please don’t hesitate to send a PR to our docs 😉

@jamesblight
Copy link
Contributor

jamesblight commented May 20, 2017

@yuzhva @gaearon I spent a bit of time investigating this issue. The proxy is working, but ws://echo.websocket.org is not running a socket.io server. This is why you're seeing a 404 response. If you use socket.io, you need to use a socket.io server.

If you look at the network requests with and without the proxy defined in package.json, you can see that the behaviour is slightly different. With proxy, there's a 404. Without, there's a 200 GET and then a 404 POST. You'll also see different behaviour if you proxy to the secure websocket (You get a 500 error):

 "proxy": {
    "/": {
      "target": "wss://echo.websocket.org",
      "ws": true,
      "secure": true
    }
  }

TLDR; socket.io client will only work with a socket.io server, and websocket.org doesn't support this.
socketio/socket.io#533

If you want to proxy a websocket connection, you can use plain Websockets (without socket.io)
https://github.com/websockets/ws#echowebsocketorg-demo

If you want to use socket.io, you can run your own local socket.io server to connect to:

var app = require('http').createServer(handler)
var io = require('socket.io')(app);
var fs = require('fs');

app.listen(3001);

function handler (req, res) {
  res.writeHead(200);
  res.end('');
}

io.on('connection', function (socket) {
  socket.emit('news', { hello: 'world' });
  socket.on('other', function (data) {
    console.log(data);
  });
});

Then, setup your proxy:

"proxy": {
  "/socket.io": {
    "target": "ws://localhost:3001"
    "ws": true
  }
}

@gaearon
Copy link
Contributor

gaearon commented May 20, 2017

@jamesblight Anything we could add to the docs?

@yuzhva
Copy link
Author

yuzhva commented May 20, 2017

@gaearon Not sure if you need to add this to create-react-app documentation because that mostly touches to other libs.

Is note like would be helpful?

NOTE: WebSocket libraries like socket.io or ws requires to run a live server instead of making requests by ws://DOMAIN_URL. Their clients (socket.io-client, ws.clinet) reference to a back end with the role of a client in the websocket communication.

Server rendering also would not help you, so you need to write both server and client by using thair libraries, OR you need to use native (pure JS) WebSocket object in your create-react-app.

@jamesblight
Copy link
Contributor

@gaearon The docs cover a lot of areas not directly related to CRA, so it probably won't hurt to add some info on WebSockets. PR #2305

@yuzhva
Copy link
Author

yuzhva commented May 21, 2017

@jamesblight I added an extra note to your fork.

@yuzhva
Copy link
Author

yuzhva commented May 21, 2017

UPDATE: Final words.

If you would like to connect WebSocket server that already hosted at ws://DOMAIN_URL like ws://echo.websocket.org - you can't use any client libraries like socket.io-client or ws.
You need to use native WebSockets in the browser

Also, you don't need to configure a proxy for that purpose.

The solution will be: After creating app like creare-react-app proxy-test, connect to WebSocket server in src/App.js:

class App extends Component {
  constructor(props) {
    super(props);
   
    this.socket = new WebSocket('ws://echo.websocket.org');
  }

  componentDidMount() {
    this.socket.onmessage = (message) => {
      const messageData = JSON.stringify(message);

      console.log(messageData);
    }
    
    // Give some time for socket to establish connection
    setTimeout(() => {
      this.socket.send('create-react-app');
    }, 3000);
  }

@lock lock bot locked and limited conversation to collaborators Jan 21, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

3 participants