centrifuge-swift
centrifuge-swift copied to clipboard
Can we update headers for next reconnect state?
Hi
We're dealing with a scenario where we connect to a centrifuge via a middleware. This middleware verifies our authentication using a value in the headers. The authentication value in the headers has a limited lifetime, so we must update it in the client's headers for the next reconnect.
Is it currently impossible? Perhaps you could suggest a workaround?
Thank you
Let me describe in more detail.
When connecting to the centrifuge, we have an additional intermediate layer.
-
In the connection parameters, via headers, we pass a key - I understand that using this key, our intermediate layer confirms authorization, and this happens before the connection is upgraded to WebSocket state during the HTTP handshake phase.
-
After successful authorization, the connection establishment with the centrifuge begins, and the connection is upgraded to WebSocket state.
When an error occurs at stage 1, for example, if the passed key is invalid or expired, the client receives a response not as from WebSocket, but as from a regular "REST" request. In other words, during the connection establishment, we expect a response with a code 101, but we can receive anything.
The library is currently not designed to handle such types of errors, or rather, it's not fully prepared. Perhaps you can correct me if I'm wrong.
StarscreamWebSocket
It has access to all data being sent and received, so when the above error occurs, you determine the "Invalid HTTP upgrade" state, retrieve the received code from the server, and pass it.
As a result, StarscreamWebSocket passes the current response code from the server, but replaces the response with "Invalid HTTP upgrade". It would be beneficial to have an option to gain access to the server's message as well, providing the ability to retrieve both the response code and the server message.
NativeWebSocket
Here it's more complex, as it utilizes a system implementation and many details are hidden. We catch the error in the code below:
func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
assertIsOnQueue(queue)
guard let task = task as? URLSessionWebSocketTask, task === self.task else {
// Ignore callbacks from obsolete tasks
return
}
handleTaskClose(task: task, code: task.closeCode, reason: task.closeReason, error: error)
}
In this case error, task.closeCode, and task.closeReason are not entirely informative. closeReason is empty, possibly because the socket connection wasn't established. closeCode == CloseCode.invalid can also be interpreted in various ways.
In this scenario, the required states can only be obtained from the current response - task.response. It will contain the response code from the server and the text - everything that is handled manually in the implementation of StarscreamWebSocket.
The client embedding the SDK using NativeWebSocket only perceives that the connection is not established. Even if the server sends informative responses, they won't be accessible. The response code and content are concealed within the task.response field and are not passed through.
I've played around with the library code a bit, and technically, there's a possibility to update headers so that new ones are used upon the next connection.
I've tested this, and it works for both implementations.
Here my code for headers updating: https://github.com/centrifugal/centrifuge-swift/pull/100