Websocket handshake error in React after yarn upgrade - reactjs

In my react app, I connect to some websockets using the websocket package (not socket.io)
componentDidMount(): void {
this.settingsSubscription = subscribeToWebsocket("Settings", urls.SETTINGS_WS, handleSettingsMessage);
this.statusSubscription = subscribeToWebsocket("Status", urls.STATUS_WS, handleStatusMessage);
this.studyDataSubscription = subscribeToWebsocket("Study Data", urls.STUDY_WS, handleStudyDataMessage);
}
subscribeToWebsocket(name, url, messageHandler): W3CWebSocket {
let subscription = new W3CWebSocket(url);
subscription.onopen = () => console.log(`WebSocket Client Connected (${name})`);
subscription.onclose = () => console.log(`WebSocket Client Disconnected (${name})`);
subscription.onmessage = messageHandler;
return subscription;
}
This had been working fine, and in fact does still work fine except I also get this error in the console:
WebSocket connection to 'ws://localhost:3000/sockjs-node' failed:
Error during WebSocket handshake: Unexpected response code: 200
./node_modules/react-dev-utils/webpackHotDevClient.js # webpackHotDevClient.js:51
__webpack_require__ # bootstrap:785
fn # bootstrap:150
1 # helpers.ts:1
__webpack_require__ # bootstrap:785
checkDeferredModules # bootstrap:45
webpackJsonpCallback # bootstrap:32
(anonymous) # index.chunk.js:1
The error points to these lines in node-modules/react-dev-utils/webpackHotDevClient.js which appear to be the culprit:
// Connect to WebpackDevServer via a socket.
var connection = new WebSocket(
url.format({
protocol: 'ws',
hostname: window.location.hostname,
port: window.location.port,
// Hardcoded in WebpackDevServer
pathname: '/sockjs-node',
})
);
I had just run yarn upgrade --latest --exact so I'm guessing that has something or other to do with it.
Especially since we use the console to demo to the client, I'd really love to get rid of this error message. Thanks!

we had same issue with ejected CRA project.
Solution of mine is manual update of the config/webpackDevServer.config.js config file.
Imho this changes are the reason our livereload works again:
hot: true,
+ // Use 'ws' instead of 'sockjs-node' on server since we're using native
+ // websockets in `webpackHotDevClient`.
+ transportMode: "ws",
+ // Prevent a WS client from getting injected as we're already including
+ // `webpackHotDevClient`.
+ injectClient: false,
// It is important to tell WebpackDevServer to use the same "root" path

I had the same issue when developing an azure portal extension on my localhost. I changed 'ws' to 'wss' and it worked.

Related

Unble to open multiple simultaneous websockets to the same endpoint in case where the consumer is busy for the first websocket

I am using Django channels with React websockets. I am unable to open multiple simulataneous websockets if the consumer of the first websocket channel is busy with some activity. I want to open multiple simultaneous websockets where consumers is doing something for each individual websocket.
The module versions are:
asgiref 3.6.0
daphne 3.0.2
django-cors-headers 3.13.0
djangorestframework 3.14.0
djangorestframework-simplejwt 5.2.2
From the snippet below, once one websocket completes the task the second websocket can be connected (in a separate tab) but while 1st websocket is busy (sleeping), the other websockets in the new browser tabs fails after handshake with the following error:
**
WebSocket HANDSHAKING /ws/socket-server/monitor-rack-kpis/ushoeuhrti/ [127.0.0.1:49228]
django.channels.server INFO WebSocket HANDSHAKING /ws/socket-server/monitor-rack-kpis/ushoeuhrti/ [127.0.0.1:49228]
daphne.http_protocol DEBUG Upgraded connection ['127.0.0.1', 49228] to WebSocket
daphne.ws_protocol DEBUG WebSocket closed for ['127.0.0.1', 49228]
WebSocket DISCONNECT /ws/socket-server/monitor-rack-kpis/ushoeuhrti/ [127.0.0.1:49228]
django.channels.server INFO WebSocket DISCONNECT /ws/socket-server/monitor-rack-kpis/ushoeuhrti/ [127.0.0.1:49228]
daphne.server WARNING Application instance <Task pending name='Task-56' coro=<StaticFilesWrapper.__call__() running at /Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/site-packages/channels/staticfiles.py:44> wait_for=<Future pending cb=[_chain_future.<locals>._call_check_cancel() at /Library/Frameworks/Python.framework/Versions/3.11/lib/python3.11/asyncio/futures.py:387, Task.task_wakeup()]>> for connection <WebSocketProtocol client=['127.0.0.1', 49216] path=b'/ws/socket-server/monitor-rack-kpis/vhofoefwmr/'> took too long to shut down and was killed.
**
I tried using url in routing instead of re_path but that didn't help either
settings.py
`
ASGI_APPLICATION = 'backend.asgi.application'
CHANNEL_LAYERS={'default':{'BACKEND':'channels.layers.InMemoryChannelLayer'}}
`
asgi.py
application = ProtocolTypeRouter({
'http':get_asgi_application(),
'websocket':AuthMiddlewareStack(
URLRouter(logstatus.routing.websocket_urlpatterns)
)
})
routing.py
websocket_urlpatterns=[
re_path(r'^ws/socket-server/monitor-rack-kpis/(?P<username>[A-Za-z]+)/', consumers.InfluxWritePromesthusConsumer.as_asgi())
]
consumer.py
class InfluxWritePromesthusConsumer(WebsocketConsumer):
def ws_connect(message):
message.reply_channel.send({"accept": True})
def receive(self, text_data):
print(f"\nReceiving from: {self.channel_name}\n")
t = 0
while t<=100:
self.send(text_data=json.dumps({
'type':"LearnSocket",
'message': "Received Messages"
}))
t += 10
time.sleep(10)
Frontend- React.JS
const randN = generate()
console.log(randN)
const socket = new WebSocket('ws://127.0.0.1:8000/ws/socket-server/monitor-rack-kpis/'+ randN+ '/');
console.log(socket)
socket.onopen=function(e){
console.log(socket.readyState)
if (user && user.access) {
socket.send("Hi");
//Receiving response from WebSocket
socket.onmessage=function(e){
//let data1=JSON.parse(e.data);
console.log(e.data, new Date());
//setOutputResponse(data1['message']);
}
}
}

Salesforce, lwc local development server crashing

Starting LWC Local Development.
Username: test-lgcvzacysqx3#example.com
Api Version: 49.0
[HPM] Proxy created: / -> https://ability-customization-2906-dev-ed.my.salesforce.com
[HPM] Subscribed to http-proxy events: [ 'proxyReq', 'error', 'close' ]
cp: no such file or directory: /Users/admin/Desktop/suman/force-app/main/default/staticresources/*
cp: no such file or directory: /Users/admin/Desktop/suman/force-app/main/default/contentassets/*
LWR6003: Listening on :3333
Server up on http://localhost:3333
LWR6000: Created version hash "f5aff7264b"
LWR6001: Writing /Users/admin/Desktop/suman/.localdevserver/webruntime/custom-component/f617504cf1/dev/en-GB/c/myfirstLwc.js...
LWR6001: Writing /Users/admin/Desktop/suman/.localdevserver/webruntime/custom-component/f617504cf1/dev/en-GB/c/myfirstLwc.js...
CLIError: timed out
at Object.error (/Users/admin/.local/share/sfdx/client/7.163.0-ea5a9c6/node_modules/#oclif/core/lib/errors/index.js:28:15)
at /Users/admin/.local/share/sfdx/client/7.163.0-ea5a9c6/node_modules/#oclif/core/lib/cli-ux/index.js:25:66
at async flush (/Users/admin/.local/share/sfdx/client/7.163.0-ea5a9c6/node_modules/#oclif/core/lib/cli-ux/index.js:121:9) {
oclif: { exit: 2 },
code: undefined
}
CLIError: timed out
at Object.error (/Users/admin/.local/share/sfdx/client/7.163.0-ea5a9c6/node_modules/#oclif/core/lib/errors/index.js:28:15)
at /Users/admin/.local/share/sfdx/client/7.163.0-ea5a9c6/node_modules/#oclif/core/lib/cli-ux/index.js:25:66
at async flush (/Users/admin/.local/share/sfdx/client/7.163.0-ea5a9c6/node_modules/#oclif/core/lib/cli-ux/index.js:121:9) {
oclif: { exit: 2 },
code: undefined
}
LWR6004: Server is shutdown
Error: timed out
at Object.error (/Users/admin/.local/share/sfdx/client/7.163.0-ea5a9c6/node_modules/#oclif/core/lib/errors/index.js:28:15)
at /Users/admin/.local/share/sfdx/client/7.163.0-ea5a9c6/node_modules/#oclif/core/lib/cli-ux/index.js:25:66
at async flush (/Users/admin/.local/share/sfdx/client/7.163.0-ea5a9c6/node_modules/#oclif/core/lib/cli-ux/index.js:121:9)
10:01:49.554 sfdx force:lightning:lwc:start
ended with exit code 1
Error: The local development server exited unexpectedly with code 1.
I faced the similar error today
But somehow made it running using the below solution
Open the below path
C:/Users/UserName/AppData/Local/sfdx/client/7.163.0-ea5a9c6/node_modules/#oclif/core/lib/cli-ux
And edit the async flush() method in the index.js file
from 10000 to 600000
await timeout(flush(), 600000);
Hope this helps.
found some articles here for help

CORS error - Error: Cross origin http://localhost forbidden - in ReactJS/Jest test only

I'm running into a problem where the request I am making to an outside API is working fine in execution, but when runing a Jest/Enzyme test it gives me a CORS error. The function in question is using a JsonRpc implementation from an API, and using fetch from node-fetch. Not sure if there are settings for CORS I can apply somewhere?
I tried many variations of async waits in Jest/Enzyme testing framework but am still running into issues.
test("it should do something", done => {
const component = shallow(<CustomComponent />)
component.instance().customAsyncFunction( result => {
expect(result.length).toEqual(5)
done()
})
// return component.instance().customAsyncFunction().then(data => {
// expect(data.length).toEqual(5)
// })
})
I tried the above and a few other methods (like setTimeout and awaiting it) and get the CORS error.
The results I'm getting are:
console.error
node_modules/jest-environment-jsdom/node_modules/jsdom/lib/jsdom/virtual-console.js:29
Error: Cross origin http://localhost forbidden
at dispatchError (...\node_modules\jest-environment-jsdom\node_modules\jsdom\lib\jsdom\living\xhr-utils.js:65:19)
at Request.client.on.res (...\node_modules\jest-environment-jsdom\node_modules\jsdom\lib\jsdom\living\xmlhttprequest.js:679:38)
at Request.emit (events.js:198:13)
at Request.onRequestResponse (...\node_modules\request\request.js:1066:10)
at ClientRequest.emit (events.js:203:15)
at HTTPParser.parserOnIncomingClient [as onIncoming] (_http_client.js:556:21)
at HTTPParser.parserOnHeadersComplete (_http_common.js:109:17)
at TLSSocket.socketOnData (_http_client.js:442:20) undefined
Any ideas?
Jest allows you to set a setup script file. This file will be required before everything else and gives you a chance to modify the environment in which the tests will run. This way you can unset XMLHttpRequest before axios is loaded and the adapter type evaluated since imports are hoisted.
Link:https://facebook.github.io/jest/docs/configuration.html#setuptestframeworkscriptfile-string
In package.json
{
...,
"jest": {
...,
"setupTestFrameworkScriptFile": "./__tests__/setup.js",
...
},
...
}
__tests__/setup.js
global.XMLHttpRequest = undefined;
The error happens because the external API you call during the tests has a CORS restriction different than Jest's default jsdom one has (http://localhost).
To fix this for Jest v24 - v27 you have to set the appropriate testURL (see the docs) in your Jest config (e.g. jest.config.js):
{
// Other config values here ...
"testURL": "http://localhost:8080"
}
In testURL you have to put the actual URL allowed by CORS at your remote API side.
NB: since v28 the option is organized differentlty that requires different update in Jest config.
Assuming you actually want to call the real API during your tests rather than just mock it, you'll need to make sure the server sends an appropriate "access-control-allow-origin" header (obviously the exact mechanism for doing this depends on your server platform)
1) what you're probably looking for is to instead mock the promise or whatever function is being ran using jest.mock(), then assert that that mock was called (with the correct params)
Jest tests are unit tests that shouldn't really talk to your API
2) most likely something with your env vars while in test mode, process.env.NODE_ENV is set to "test" during jest which might be changing something or maybe one of your own custom config env vars
By settting a testURL option which is a valid URL you want in jest config will resovle this problem.
https://jestjs.io/docs/configuration#testurl-string

ReactJS Error: only absolute urls are supported

I am trying to pull in the current URL to use in my fetch command, but I received an error when attempting to parse the URL via window.location. It appears that this URL use is not allowed, but I'm not sure of another alternative to achieve what I'm looking for. I'm avoiding setting a string so I can adapt my React setup to multiple environments.
Error:
Error: only absolute urls are supported
Line creating the error:
console.log(protocol + '//' + hostname + ':' + port + '/api' + window.location.search);
Variables:
var urlPath = window.location.pathname;
var hostname = window.location.hostname;
var protocol = window.location.protocol;
var port = window.location.port;
I prefer dotenv. Then all you need to do is to create a .env file. There are a couple ways of loading it into your app.
Webpack(not the npm package listed above, instead is webpack-dotenv-plugin)
import DotenvPlugin from 'webpack-dotenv-plugin';
plugins: [
new DotenvPlugin({
sample: './.env.default',
path: './.env',
}),
Not webpack
As early as possible:
require('dotenv').config()

Angular2 http.get(url) is returning 404 on a valid url - not a CORS issue

I have an Angular2 App running that is attempting to make a call to my Django server.
I have a function called getObjects That makes the external API call and should return a list of objects. As a bit of debugging I am currently making a XMLHttpRequest, which correctly grabs the data from my server.
However, whenever I attempt to make a request using Http.http.get(url) I see a 404 error. I've tried fiddling with a few of the HTTP headers, as well as playing around with some settings on my server, but I cannot figure out what is wrong.
I assume that the Http.http.get() method is doing something funky behind the scenes that I am unaware of. The odd thing is that my browser dev-network tab doesn't even show any attempt to reach my external browser.
Any help in the matter would be much appreciated, I can provide any additional debug information and could really use a point in the right direction.
ng --version
angular-cli: 1.0.0-beta.24
node: 6.9.1
os: win32 x64
#angular/common: 2.4.3
#angular/compiler: 2.4.3
#angular/core: 2.4.3
#angular/forms: 2.4.3
#angular/http: 2.4.3
#angular/platform-browser: 2.4.3
#angular/platform-browser-dynamic: 2.4.3
#angular/router: 3.4.3
#angular/compiler-cli: 2.4.3
import { Injectable } from '#angular/core';
import { Headers, Http } from '#angular/http';
import 'rxjs/add/operator/toPromise';
...
constructor(private http: Http) { }
getObjects(): Promise<Object[]> {
function httpGet(theUrl)
{
var xmlHttp = new XMLHttpRequest();
xmlHttp.open( "GET", theUrl, false ); // false for synchronous request
xmlHttp.send( null );
return xmlHttp.responseText;
}
var x = httpGet(this.myUrl);
console.log(x); // This works perfectly and I see an entry on my server log
this.http.get(this.myUrl)
.subscribe(res => console.log(res));// This throws a 404 and I see no entry on my server logs nor in my browser network tab
var headers = new Headers({'content-type': 'application/json'});
this.http.get(this.myUrl, {headers: headers})
.subscribe(res => console.log(res));// This throws a 404 and I see no entry on my server logs nor in my browser network tab
return this.http.get(this.myUrl)
.toPromise()
.then(response => response.json().data as Object[])
.catch(this.handleError); //The original code that worked on an internal in-memory-api
}
I was able to find a working fix in another stack overflow question:
Angular 2 HTTP GET returning URL null
The problem was with the InMemoryWebApiModule and the solution was to make the following config modification to my app.module.ts file:
- InMemoryWebApiModule.forRoot(InMemoryDataService),
+ InMemoryWebApiModule.forRoot(InMemoryDataService, {passThruUnknownUrl: true}),
Making this small config change caused the application to work.
In fact there is no 404, because you are not executing your requests. You need to subscribe() to them, to execute them. Few examples:
this.http.get(this.myUrl).subscribe(res => console.log(res));
this.http.get(this.myUrl).subscribe();
let response: Observable<Response> = this.http.get(this.myUrl);
response.subscribe();
response.subscribe(v => console.log(v);
You can read about observables here:
http://reactivex.io/rxjs/manual/index.html
This can be an issue with angular2-in-memory-web-api. I had the same issue, but when I removed the InMemoryWebApiModule from the AppModule, the API calls worked perfectly.

Resources