socketio / engine.io-client

The engine used in the Socket.IO JavaScript client, which manages the low-level transports such as HTTP long-polling, WebSocket and WebTransport.
https://socket.io
742 stars 356 forks source link

Add negotiate #710

Closed zackliu closed 3 months ago

zackliu commented 1 year ago

Note: the engine.io.js file is the generated output of make engine.io.js, and should not be manually modified.

The kind of change this PR does introduce

Current behaviour

The engine.io connection directly connects to the hostname, path.

New behaviour

If negotiatePath is set, engine.io will make a fetch to the <hostname>/<negotiatePath> to get a JSON encoded response first.

{
  "url", "http://hostname/path",
  "token": "<token>"
}

if succeeded, the engine.io will parse the url got in negotiation and replace it with the previous hostname, path, port and protocol in opts. As the opts has changed, everything is unchanged then (e.g when constructing a transport, it still read from opts).

Another change is adding a token in opts. If token is set, it will be used in Authorization for long polling, and access_token query for websocket. This token can be set in opts directly but it can also be override in negotiation.

Other information (e.g. related issues)

This is the implementation of issue https://github.com/socketio/socket.io/issues/4825

zackliu commented 1 year ago

@darrachequesne We can discuss whether the design is acceptable, and I will write some more test.

zackliu commented 12 months ago

@darrachequesne Do you have any comments on the design?

darrachequesne commented 11 months ago

Hi @zackliu,

Thanks for your work on this.

However, I still don't think the use case is common enough for this to be included here in the package.

zackliu commented 11 months ago

@darrachequesne I think there're two parts in it.

  1. Added a token in opts, which can be used in Authorization in long polling and access_token query in websocket
  2. Add a negotiate opts and replace the correlating fields in opts.

I admit we can use a separate library for the second purpose but what about the first one? Do you think it's acceptable to have such a property as it's hard to achieve outside this package?

darrachequesne commented 11 months ago

For 1, the transportOptions option should be sufficient I think:

import { io } from "socket.io-client";

const socket = io({
  transportOptions: {
    polling: {
      extraHeaders: {
        Authorization: myToken
      }
    },
    websocket: {
      query: {
        access_token: myToken
      }
    }
  }
});

Reference: https://socket.io/docs/v4/client-options/#transportoptions

darrachequesne commented 3 months ago

I think this can be closed now. Please reopen if needed!