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.

Home Page:https://socket.io

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

extra-headers still not supported in browser

gjuchault opened this issue · comments

It appears that those lines

var freeGlobal = typeof global === 'object' && global;
if (freeGlobal.global === freeGlobal) {
if (opts.extraHeaders && Object.keys(opts.extraHeaders).length > 0) {
this.extraHeaders = opts.extraHeaders;
}
still block headers from being sent in browser with the basic extraHeaders option.

The way to use extraHeaders in Node is:

{
  extraHeaders: { foo: 'bar' }
}

The way to use extraHeaders in Browser is (#536 (comment)):

{
    transportOptions: {
        polling: {
            extraHeaders: { 'foo': 'bar' }
        }
    }
}

The documentation could definitely be improved here 👍

And what about websocket protocol ?

Ah I see (for future reference, more testing and notes: https://trello.com/c/7oqnpaxT/88-verify-that-extraheaders-is-actually-still-100-fixed-for-browser-usage-in-socket-io-client-engine-io-client-and-if-so-1-update-t)

We have some code that looks for a "nosession" header in order to determine whether to log warnings or not when the cookie can't be used.

please see http://stackoverflow.com/a/4361358

@darrachequesne So I'm guessing maybe if we named it "Authorization" we'd have better luck? (I'll take that for a spin and post back-- just making sure that's the intended behavior.)

@gjuchault re what's documented now: https://github.com/socketio/engine.io-client/tree/be4c9067b548f3e27dd1889e4094aff5b6d9eecb#nodejs-with-extraheaders

Well, just for reference, in the browser and in React Native, looks like 'sec-websocket-protocol': 'foobar' doesn't make it through:

  transports: ['websocket'], // you need to explicitly tell it to use websockets
  extraHeaders: {
  // nosession: true,
  // 'Sec-WebSocket-Protocol': 'foobar'
  'sec-websocket-protocol': 'foobar'
  }

From a node.js client, doing the same thing results in an error from the client:

TypeError: Cannot create property 'type' on string 'server sent a subprotocol even though none requested'
    at WebSocket.onError (/Users/mike/code/react-native-socket-io-example/node_modules/engine.io-client/node_modules/ws/lib/WebSocket.js:450:16)
    at emitOne (events.js:96:13)
    at WebSocket.emit (events.js:188:7)
    at ClientRequest.upgrade (/Users/mike/code/react-native-socket-io-example/node_modules/engine.io-client/node_modules/ws/lib/WebSocket.js:757:12)
    at ClientRequest.g (events.js:291:16)
    at emitThree (events.js:116:13)
    at ClientRequest.emit (events.js:194:7)
    at Socket.socketOnData (_http_client.js:394:11)
    at emitOne (events.js:96:13)
    at Socket.emit (events.js:188:7)

this is w/ socket.io@1.7.3 (engine.io@1.8.3)

I had the same results when embedding basic auth in the url (e.g. http:/foo:bar@localhost:1337) and when including either of the two special headers as transport-specific websocket options:
image

Aside: for other folks finding this looking for an immediate answer, note that query works just fine, as far as I can tell. In either case, be aware that you'll want to send a string -- because if you send false, null, or 0, you'll get an ugly and (truthy) surprise (e.g. 'false', 'null', '0')

Update: extraHeaders is supported in browsers as of v2.0.0, but only for the polling transport, because the browser Websocket API doesn't support adding extra headers to the handshake. As @mikermcneil mentions above, the best workaround for the websocket transport is to use the query option to pass whatever info you need in the handshake.

{ 
        transports: ['polling'], 
        path: '/websocket',
        transportOptions: {
            polling: {
                extraHeaders: {
                    'x-clientid': 'abc',
                }
              }
        }
    }

it works, you can print socket.handshake.headers['x-clientid'] on server.

you can send credentials like this

const socket = io({
  auth: {
    token: "abc"
  }
});