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

Exception: The underlying connection was closed before the hub handshake could complete. #5

Closed
laimonas opened this issue Feb 13, 2020 · 24 comments
Labels
bug Something isn't working

Comments

@laimonas
Copy link

Hi, tnx for package!

I'm getting this error while trying to connect to hub that's deployed to azure running emulator.
`final connection = HubConnectionBuilder()
.withUrl(
'https://fortestpurpose.azurewebsites.net/hub',
HttpConnectionOptions(
transport: HttpTransportType.webSockets,
logging: (level, message) => print(message),
))
.withAutomaticReconnect()
.build();

await connection.start();`

Using localhost service there is no such error for example with url:
http://10.0.2.2:5000/hub

Any clues why this can happen?

@jamiewest jamiewest added the bug Something isn't working label Feb 13, 2020
@jamiewest
Copy link
Owner

Thank you for your issue, would it be possible for you to share the logs when you connect? I did some basic testing with Azure and will probably need to focus some attention here. Thanks!

@laimonas
Copy link
Author

Hi there is my logs:

I/flutter (17280): Starting HubConnection.
I/flutter (17280): Starting connection with transfer format 'TransferFormat.text'.
I/flutter (17280): Sending negotiation request: https://scrumpokertest.azurewebsites.net/scrum-poker/negotiate.
D/EGL_emulation(17280): eglMakeCurrent: 0x7992b9ef9dc0: ver 3 0 (tinfo 0x7992b9e32f20)
I/flutter (17280): Selecting transport 'HttpTransportType.webSockets'.
I/flutter (17280): (WebSockets transport) Connecting.
I/flutter (17280): WebSocket connected to wss://scrumpokertest.azurewebsites.net/scrum-poker?id=D0riT29u-hAprZq3ss2DdA.
I/flutter (17280): The HttpConnection connected successfully.
I/flutter (17280): Sending handshake request.
I/flutter (17280): (WebSockets transport) sending data. String data of length '32'.
I/flutter (17280): Using HubProtocol 'json'.
I/flutter (17280): WebSocketChannelException: WebSocketChannelException: WebSocketException: Connection to 'https://scrumpokertest.azurewebsites.net:0/scrum-poker?id=D0riT29u-hAprZq3ss2DdA#' was not upgraded to websocket
I/flutter (17280): (WebSockets transport) socket closed.
I/flutter (17280): HttpConnection.stopConnection(null) called while in state ConnectionState.connected.
I/flutter (17280): Connection disconnected.
I/flutter (17280): HubConnection.connectionClosed(null) called while in state HubConnectionState.disconnected.
I/flutter (17280): Hub handshake failed with error 'Exception: The underlying connection was closed before the hub handshake could complete.' during start(). Stopping HubConnection.
I/flutter (17280): Call to HttpConnection.stop(Exception: The underlying connection was closed before the hub handshake could complete.) ignored because the connection is already in the disconnected state.
I/flutter (17280): HubConnection failed to start successfully because of error '{Exception: The underlying connection was closed before the hub handshake could complete..toString}'.

You can try with this url:
https://scrumpokertest.azurewebsites.net/scrum-poker

@jamiewest
Copy link
Owner

Just a quick update, I haven't had a chance to start coding a fix yet. The underlying socket is not getting upgraded when connecting. I will need to modify the underlying web_socket_channel library to accept an upgraded socket when not running on the web. I tried testing the web version with your site but failed due to the cors policy. Long polling and server sent events seem to work okay.

@laimonas
Copy link
Author

Hi @jamiewest tnx for info. I have tried with long polling and it's working for me also (didn't know about this). If you need my azure signalr site to test from web i can try to configure CORS for you if you need, just ping me here and i will look when i have time.

@jamiewest
Copy link
Owner

I made some progress but I am not receiving at 503 (service unavailable) error from your backend. Any ideas?

@laimonas
Copy link
Author

laimonas commented Feb 23, 2020

@jamiewest 503 error is probably because of site is running in free plan only 60 min execution per day. I have upgraded the service plan and it should be online for all day.
Also if you want to test some hub actions there is:

connection.invoke('CreateGroup', args: ['Group name, 'User name']);
connection.on('GroupCreated', (response) async {
});

@jamiewest
Copy link
Owner

I am waiting to see if a pull request is accepted regarding #387 in package:http/http.dart. If this is accepted then I will be able to provide a mechanism to handle bad certificate callbacks and other security context concerns along with allowing the socket to be upgraded. This should in part resolve the issue your having.

I did end up pushing my own SignalR app in an Azure App Service plan, the free one, to see if I could recreate the problems you are having. During the process it asked specifically if I wanted to enable websockets, which I did. I think yours might me missing this piece, you can check this by going into the app service/configuration/general settings area and make sure the radio button is enabled for web sockets.

@laimonas
Copy link
Author

laimonas commented Mar 2, 2020

@jamiewest websockets are enabled. I just made another test. I have two apps on azure one is based on windows and other on linux service plan. And yes it is working with windows but not the linux one. So i don't know if this is a bug with library or azure it self. Maybe you can try with linux service plan (it is much cheaper then windows based).

@laimonas
Copy link
Author

laimonas commented Mar 30, 2020

@jamiewest somehow i cannot reproduce this anymore on linux instance of azure it is even started to work with " transport: HttpTransportType.webSockets". I have also tested with flutter web and it is also working with one thing that i need to disable skipNegotiation. So you can close this one!

@jamiewest
Copy link
Owner

Okay, thanks. Once the http package is published with my changes I will publish this library with a handful of bug fixes. Hopefully soon...

@sawproduction
Copy link

have you solved this I'm getting this error after 2 years of yours

@MathiasTP
Copy link

I am getting this error as well..

@aminesnip
Copy link

I am getting this error as well.
When I test locally on windows it works very well, but the error appears when I publish on the linux server.
Any solution to fix this problem ?.

@frkn2076
Copy link

I was facing the same issue and stopping hubConnection before super.dispose solved my issue.

@override
  void dispose() {
    hubConnection.stop();  // I've added that line.
    super.dispose();
  }

@sinanhaci
Copy link

I am getting this error as well. When I test locally on windows it works very well, but the error appears when I publish on the linux server. Any solution to fix this problem ?.

Were you able to solve the problem?

@andres-aranda
Copy link

Me enfrentaba al mismo problema y detuve hubConnection antes de que super.dispose resolviera mi problema.

@override
  void dispose() {
    hubConnection.stop();  // I've added that line.
    super.dispose();
  }

eso en que archivo lo agregaste?

@sinanhaci
Copy link

This issue usually occurs on Linux servers, in my experience, it's not related to the package itself, but rather to the server configurations.

@mamaly12
Copy link

mamaly12 commented Sep 19, 2023

I still have the same issue. I use IdentityServer 4, and the following setup is recommended for signal authentication using the access token(according to https://learn.microsoft.com/en-us/aspnet/core/signalr/authn-and-authz?view=aspnetcore-7.0#identity-server-jwt-authentication).

It's not related to the OS, and I am suspicious it's related to the library that cannot update the connection.

  var originalOnMessageReceived = options.Events.OnMessageReceived;
            options.Events.OnMessageReceived = async context =>
            {
                await originalOnMessageReceived(context);

                if (string.IsNullOrEmpty(context.Token))
                {
                    var accessToken = context.Request.Query["access_token"];
                    var path = context.HttpContext.Request.Path;

                    if (!string.IsNullOrEmpty(accessToken) &&
                        path.StartsWithSegments("/hubs"))
                    {
                        context.Token = accessToken;
                    }
                }
            };

When I start a socket connection request, everything seems fine, and the " context.Token" will be set according to the token. Still, suddenly, I received the error "The underlying connection was closed before the hub handshake could complete." from Flutter and my connection will be closed

@madagaskarr
Copy link

I think the issue is on the server, try changing the connection protocol to long pooling

@kivocsa99
Copy link

@madagaskarr
iam having the same issue what do you mean by changing it to long pooling and how to do that ?

@kivocsa99
Copy link

@jamiewest
any updates on this ?

@madagaskarr
Copy link

I fixed this on the nginx server by adding support to upgrade the connection. The library work as expected!

@kivocsa99
Copy link

@madagaskarr iam using IIS any suggestions ?

@DmitryGaimaldinov
Copy link

In my case the problem happened only when I was using [Authrize] attribute in hub.
I added JwtBearerEvents handler, and everything started working.

builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, options =>
        {
            options.TokenValidationParameters = new TokenValidationParameters
            {
                ...
            };
            options.MapInboundClaims = false;
            options.Events = new JwtBearerEvents
            {
                OnMessageReceived = context =>
                {
                    var path = context.Request.Path;
                    var accessToken = context.Request.Query["access_token"];
                   // Here also was a check "path.StartsWithSegments("/hubs")" like the documentations suggests, but it caused websocket error so I removed it
                    if (!string.IsNullOrEmpty(accessToken))
                    {

                        context.Request.Headers.Add("Authorization", new[] { $"Bearer {accessToken}" });
                    }
                    return Task.CompletedTask;
                }
            };
        });

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests