Comments (13)
@msandel6 @nathanl Looking into this a little deeper and I found an issue with how the Client is passing errors back through onError
. Reading the docs revealed this about didCompleteWithError
The only errors your delegate receives through the error parameter are client-side errors, such as being unable to resolve the hostname or connect to the host. To check for server-side errors, inspect the response property of the task parameter received by this callback.
In order to get the 401
from the server response, the client needs to return back the task.response
to the calling code as well which should inform you of any potential server-side errors. I'm going to work on getting this added today. Hopefully that will help with whatever solution you guys came to.
from swiftphoenixclient.
Are you looking for socket.onOpen()?
from swiftphoenixclient.
.onOpen()
is called from within that same URLSession delegate method, so unless I'm missing something that would be called under the same circumstances. 🤔
from swiftphoenixclient.
I'm sorry, i'm not 100% following what the problem exactly is that you're trying to solve for. Is there a different method that URLSession delegate provides that, if used, solves your usecase?
from swiftphoenixclient.
The problem is that the didOpenWithProtocol
delegate method gets called after a successful TCP handshake, rather than after the socket is actually opened.
In my case, this is the sequence of events:
- I send the open request with parameters
- The server receives it (after successful handshake)
- The
didOpenWithProtocol
delegate callback happens due to the successful handshake - The
SwiftPhoenixClient
framework setssocket.isConnected
to true and callssocket.onOpen()
. My app responds accordingly, entering a flow that assumes the socket is open. - The server rejects the request to upgrade the connection to a socket if the parameters/credentials I sent are incorrect
The app now thinks there is an open socket connection, even though the socket was never opened.
Unfortunately, it doesn't look like there are other URLSessionWebSocketDelegate methods we can use to determine when a socket has actually been opened. Maybe there is a possible workaround using pings where at least one pong has to be returned before the socket is declared as isConnected
, but I haven't had time to experiment with that.
from swiftphoenixclient.
Okay, i'm following now. Thank you for clarifying. I can't speak directly to the solution, but I would assume your server can allow the upgrade to the websocket but then proceed to close the connection with an error? I don't think there is anything client side to intercept a failed upgraded handshake
from swiftphoenixclient.
@dsrees From a Phoenix perspective, preventing the upgrade for failed authentication is a supported feature:
To deny connection, return :error or {:error, term}. To control the response the client receives in that case, define an error handler in the websocket configuration.
https://hexdocs.pm/phoenix/1.7.0-rc.2/Phoenix.Socket.html#c:connect/2-socket-params-and-assigns
Looks like we can do it at the channel layer too, but I think the normal use case there is like "you're allowed to connect to the chat server (Socket
) but you're not allowed to join this specific room (Channel
)." For dealing with an authentication error ("we don't know who you are"), the Socket
seems like a more correct place to deny the user.
We can work around this, I just wanted to give that perspective.
from swiftphoenixclient.
I don't think there is anything client side to intercept a failed upgraded handshake
This seems like a bug, doesn't it? If you don't get a 101 Swiching Protcols
response but assume that it worked, does that mean you wouldn't get an error if you tried to establish a connection to a REST endpoint?
from swiftphoenixclient.
@nathanl @msandel6 thanks for some additional context. I believe URLSession handles the 101 Switching Protocols
response internally and doesn't seem to expose that level of detail to the delegate.
Testing this against a local server, if I return :error
from Socket.connect/3
, then the client receives the error and attempts to reconnect, which is the same behavior I see the Phoenix JS client performing. This error will be passed to your app via socket.onError { error in ... }
callback where you can inspect it further if you'd like. Inside of this socket.onError
callback, socket.isConnected
is returning false
for me and URLSession:webSocketTask:didOpenWithProtocol:
is never being called.
That all being said, I am not able to reproduce the same behavior described earlier:
- The
didOpenWithProtocol
delegate callback happens due to the successful handshake- The
SwiftPhoenixClient
framework setssocket.isConnected
to true and callssocket.onOpen()
. My app responds accordingly, entering a flow that assumes the socket is open.
If you can create a small client/server repo that reproduces this error, then I'd be happy to look further into this. For reference, I am testing using the ChatRoomViewController found in the client's example project and this chat server locally.
from swiftphoenixclient.
@dsrees Thanks for the response! So when you return an error it never even enters the .onOpen
delegate functions?
In my case the client error delegate does get hit (and .isConnected
set to false
), but only after first going through .onOpen
and setting .isConnected
to true. So I still can't rely on the .isConnected
value unless I add an arbitrary wait time to ensure it isn't closely followed by an error.
from swiftphoenixclient.
@msandel6 that is correct. If you can reproduce it in a toy ios/phoenix project then I am happy to pull that and take a look.
from swiftphoenixclient.
Interesting. Makes sense to me, thanks so much for investigating @dsrees!
from swiftphoenixclient.
5.2.0 has been released with this fix. You can see it in action here
from swiftphoenixclient.
Related Issues (20)
- Move out additional Rx and Starscream solutions to separate Swift Packages HOT 9
- Question: Behaviour when remote kills connection. HOT 3
- How to configure heartbeat? HOT 4
- Problems with connections closing and not re-establishing HOT 4
- Access raw message data HOT 2
- Crash on channel connection HOT 1
- `Channel` `bindingsDel` array is not thread safe and appears to rarely cause a crash HOT 1
- Problems with connections on WatchOS 9 HOT 4
- Error: "Undefined symbol: _$s18SwiftPhoenixClient7ChannelCMn" HOT 11
- SSL Pinning support after StarScream removal HOT 3
- Crash in `Channel.swift` `off()` function HOT 2
- Crash in `Socket.append<T>(callback:to:)` function HOT 5
- Automatic success for `Channel.leave()` attempts when offline HOT 3
- Sending binary data in a message HOT 3
- Crash on Channel initialization HOT 4
- Version 5.3.1 is unavailable via cocoapods HOT 1
- Adding a certificate authentication request HOT 1
- Socket.sendHeartbeat() EXC_BAD_ACCESS (KERN_INVALID_ADDRESS) HOT 3
- What are the payload size limits? HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from swiftphoenixclient.