SignalR in react/ Go stack practice the day before yesterday, steps and ideas are mostly the application of the peripheral framework, today strike while the iron is hot, give me a summary of SignalR to avoid the pit guide.

1.SignalR Default negotiation

For both.net and JavaScript clients, there is a default configuration when building a connection: SkipNegotiation=fasle. The full implication of this default configuration is that when establishing a SignalR connection, the client needs to negotiate the transport mode.

The following figure is generated:

Tip: If you are sure that your network is stable for webSocket traffic, skip the negotiation request (set SkipNegotiation= True) in order to quickly establish real-time communication. After all, the React group price will be reloaded every time the page is refreshed.

 const connection = new HubConnectionBuilder()
        .withUrl(process.env.REACT_APP_APIBASEURL+"realtime", {
          skipNegotiation: true,  
          transport: HttpTransportType.WebSockets
        })
        .withAutomaticReconnect()
        .withHubProtocol(new JsonHubProtocol())
        .configureLogging(LogLevel.Information)
        .build();
Copy the code

Note: SkipNegotiation=true, only the client transport mode is specified as websocket, other modes will report an error.

2.SignalR Transmission negotiation YesFetch request

Fetch requests, like Ajax, are a form of browser scripting, so they are obviously cross-domain, and the standard CORS scheme still works for them.

http://localhost:9598/realtime/negotiate?negotiateVersion=1 Post request a custom request header – Requested – With X, X – Signalr – the user-agent

Obviously, this is going to trigger againPrecheck Option requests

You also need to allow these custom headers when using CORS Middleware.

C := cers.new (cers.options {// AllowedOrigins: []string{"http://localhost:3000","http://rosenbridge.17usoft.com"}, AllowOriginFunc: func(origin string) bool { return true }, AllowedMethods: []string{"POST", "GET", "OPTIONS", "PUT", "DELETE"}, []string{"Content-Type", "x-requested-with", "x-signalr-user-agent"}, AllowCredentials: true, Debug: cfg.Log.Debug, })Copy the code

3. Websockets also have same-origin restrictions

ws://localhost:9598/realtime? id=aoSD_WZhqbRfPyXVTYsHig==

Websockets also have same-origin restrictions, but standard CORS does not apply to them because CORS addresses the cross-domain problem of HTTP script requests. Websockets are not HTTP protocol after all.

The browser will still carry Origin headers for us, so the server needs to validate these headers to ensure that only Websockets from the intended source are allowed.

Var webSocketOptions = new webSocketOptions () {KeepAliveInterval = TimeSpan.FromSeconds(120), }; webSocketOptions.AllowedOrigins.Add("https://client.com"); webSocketOptions.AllowedOrigins.Add("https://www.client.com"); app.UseWebSockets(webSocketOptions);Copy the code

BTW, the GO SignalR library I use does not support WebSocket cross domain, I proposed a PR, has been successfully merged, excited, this is the first time I proposed MR to open source project and passed the project.

4. After production is deployed, nginx support is required

According to the default configuration, the negotiation is performed first and then the WebSocket is used for transmission.

After deployment to production, WebSocket mode is preferentially used after negotiation. However, the transmission fails, and the server automatically degrades to SSE mode.

Browser developer tools didn’t see anything, but used Fiddler to grab the package and found the 400 status code

A web search shows that nginx does not recognize websocket headers. Add the following configuration to the nginx configuration

Location / {proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; }Copy the code

SignalR closure guide from development to deployment, because it is not convenient to re-edit the wechat public account content after release, there will be more closure skills, will be synchronized to here.