How to handle invalid URL / IP's in websockets? - javascript

I'm using HTML / Javascript web sockets to communicate with a python server program. Now I have the option to change the server's IP via clean UI and I have a .onerror function that handles with connection errors, however this doesn't handle initial errors. What I mean by this is if I were to enter a completely invalid address, it wont even attempt to connect with it (which is fine) and spit out and error like: [Error] WebSocket network error: The operation couldn’t be completed. (kCFErrorDomainCFNetwork error 2.). How can I handle this error so I can say, popup a message for example?
Here's a brief overview of my JS script.
function updateDevice(id, ipUI){
if ("WebSocket" in window){
var ws = new WebSocket(serverIP);
// Here is where I need to handle the bad address right?
ws.onopen = function(){
ws.send(id);
};
ws.onmessage = function (evt){
var received_msg = evt.data;
};
// This function ws.onerror doesnt handle bad addresses.
ws.onerror = function(){
document.getElementById("error_msg").style.display='block';
};
}else{
alert("This site doesnt support your browser...");
};
};

You could wrap the new WebSocket in a try/catch:
try {
new WebSocket(serverIP);
} catch (e) {
if (e instanceof DOMException) {
alert('Invalid address!');
} else {
throw e;
}
}

Related

Javascript Websocket fails to receive TCP data

I'm trying to receive json data from an ESP32 via TCP to a website hosted thru WAMP (localhost -> ESP32 IP address on local network is 10.11.125:23). Below is my javascript function. My browser (Firefox Developer) generates a "SecurityError: The operation is insecure" when executing the line var connection = new webSocket('ws://10.11.13.125:23'). What am I missing??
function openWebsocket() {
console.log("open Websocket.....");
var connection = new WebSocket('ws://10.11.13.125:23');
connection.onerror = function(error) {
$("#Connection").html("Connection Error");
console.log("Websocket Error: " + error);
}
connection.onopen = function(evt) {
$("#Connection").html("Connected");
}
connection.binaryType = 'arraybuffer';
connection.onmessage = function(evt) {
console.log("Server: " + evt.data.byteLength);
}
console.log("ReadyState: "+connection.readyState);
}
I found the problem. The Chromium browser yields a more descriptive error message. Port 23 is not available. Switched over to
var connection = new WebSocket('ws://10.11.13.125:80');
and voila, everything works as expected.
Sorry for posting about an issue that in the end I found the solution for myself.

Javascript websocket wont connect to php websocket

So I've been trying to get this whole connection between PHP socket server and Javascript websockets working, but I cant get them to connect. I have looked everywhere to figure out what I'm doing wrong. My guess is it's the protocol but I have no idea. Everything helps, comment if you have questions.
Client-Side Example
<script>
var connection = new WebSocket('ws://127.0.0.1:4446');
connection.onopen = function () {
connection.send('Ping'); // Send the message 'Ping' to the server
};
// Log errors
connection.onerror = function (error){
console.log('WebSocket Error ' + error);
};
// Log messages from the server
connection.onmessage = function (e) {
console.log('Server: ' + e.data);
};
</script>
Server-Side Example -PHP
<?php
$conn = stream_socket_server('tcp://127.0.0.1:4446');
while ($socket = stream_socket_accept($conn)) {
$pkt = stream_socket_recvfrom($socket, 1500, 0, $peer);
if (false === empty($pkt)) {
stream_socket_sendto($socket, $pkt, 0, $peer);
}
fclose($socket);
usleep(10000); //100ms delay
}
stream_socket_shutdown($conn, \STREAM_SHUT_RDWR);
?>
Console Log Error
VM4666:35 WebSocket connection to 'ws://127.0.0.1:4446/' failed: Error during WebSocket handshake: net::ERR_INVALID_HTTP_RESPONSE
I understand that there are many questions on here similar but I cant seem to find a solution, I appreciate any help!

cannot handle net::ERR_CONNECTION_REFUSED in pure js

I use pure js(without JQuery) to send an XMLHttpRequest request to server.
var _xhr = new XMLHttpRequest();
_xhr.open(type, url);
_xhr.setRequestHeader('Content-Type', 'application/json');
_xhr.responseType = 'json';
_xhr.onload = function () {
if (_xhr.status === 200) {
var _json = _xhr.response;
if (typeof _json == 'string')
_json = JSON.parse(_json);
success(_json);
} else {
error(_xhr);
}
};
_xhr.onerror = function(){
console.log('fail');
};
try {
_xhr.send(_to_send);
} catch (e){
options.error(_xhr);
}
when i send a request it's fails(this is ok) and i get an error but I CANNON HANDLE IT. xhr.onerror prints message to console but i get OPTIONS url net::ERR_CONNECTION_REFUSED too. How can I avoid this message in console?
Also i use window.onerror to handle all error but i can not handle this OPTIONS url net::ERR_CONNECTION_REFUSED
This worked for me:
// Watch for net::ERR_CONNECTION_REFUSED and other oddities.
_xhr.onreadystatechange = function() {
if (_xhr.readyState == 4 && _xhr.status == 0) {
console.log('OH NO!');
}
};
This is not limited to just net::ERR_CONNECTION_REFUSED because other network errors (e.g. net::ERR_NETWORK_CHANGED, net::ERR_ADDRESS_UNREACHABLE, net::ERR_TIMED_OUT) may be "caught" this way. I am unable to locate these error messages within the _xhr object anywhere, so making a programmatic decision about which network error has specifically occurred won't be reliable.
There is no way around that error showing in console. Just as if you request a file that does't exist you get a 404 in console, regardless of if you handle the error or not.

Issue Parsing JSON Response

I'm using AJAX/JQuery to call a WCF service. I have some .NET try/catch error-handling on the service-side that checks to see if the user has timed out, and if they have then I pass back a JSON-converted message which I then parse out on the client-end using parseJSON and use it to re-direct the user back a login page.
This is all working great, but I just got a different type of error returned from the service that WASN'T in JSON format (it was XML) so the error-handling function got a javascript error on the client side when it tried to parse the reply. The error was in the jquery.min.js file, and was an 'Invalid character' error.
My question (finally), is there a better way to handle that reply if I can't always rely on it being JSON? In .NET we have a tryParse method available that would work great here, but as far as I know JQuery/Javascript has no such feature. If it can't parse the reply, it throws a JS error.
Here is where the custom JSON exception is thrown:
private HttpSessionState GetUserSession()
{
HttpSessionState session = HttpContext.Current.Session;
try
{
// This is a method we created that checks if user has timed out and throws the exception if so.
SessionBuilder.Create(session, HttpContext.Current.Request, HttpContext.Current.Response);
}
catch (SessionTimeOutException e)
{
throw new WebFaultException<SessionTimeOutException>(new SessionTimeOutException(e.Message), System.Net.HttpStatusCode.BadRequest);
}
return session;
}
And here is the client-side code that handles errors in my AJAX request:
error: function (HttpRequest)
{
// This is the line that gets the exception because the responseText is a standard .NET XML error, not my custom JSON error.
var parsedReply = $.parseJSON(HttpRequest.responseText);
if (parsedReply.ClassName === "SessionTimeOutException")
{
var url = "../timeout.asp?" + parsedReply.Message;
window.location.href = url;
}
}
JavaScript has try { ... } catch(ex) { ... } also.
error: function (HttpRequest)
{
var parsedReply;
try {
parseReply = $.parseJSON(HttpRequest.responseText);
if (parsedReply.ClassName === "SessionTimeOutException")
{
var url = "../timeout.asp?" + parsedReply.Message;
window.location.href = url;
}
} catch(ex) {
parsedReply = HttpRequest.responseText;
//Do something else
}
}

Repeat failed XHR

Is there any common way, example or code template how to repeat a XHR that failed due to connection problems?
Preferably in jQuery but other ideas are welcome.
I need to send some application state data to a database server. This is initiated by the user clicking a button. If the XHR fails for some reason I need to make sure that the data is sent later (no interaction needed here) in the correct order (the user may press the button again).
Here's how I would do it:
function send(address, data) {
var retries = 5;
function makeReq() {
if(address == null)
throw "Error: File not defined."
var req = (window.XMLHttpRequest)?new XMLHttpRequest():new ActiveXObject("Microsoft.XMLHTTP");
if(req == null)
throw "Error: XMLHttpRequest failed to initiate.";
req.onload = function() {
//Everything's peachy
console.log("Success!");
}
req.onerror = function() {
retries--;
if(retries > 0) {
console.log("Retrying...");
setTimeout(function(){makeReq()}, 1000);
} else {
//I tried and I tried, but it just wouldn't work!
console.log("No go Joe");
}
}
try {
req.open("POST", address, true);
req.send(data); //Send whatever here
} catch(e) {
throw "Error retrieving data file. Some browsers only accept cross-domain request with HTTP.";
}
}
makeReq();
}
send("somefile.php", "data");
To make sure everything is sent in the right order, you could tack on some ID variables to the send function. This would all happen server-side though.
And of course, there doesn't need to be a limit on retries.
jQuery provides an error callback in .ajax for this:
$.ajax({
url: 'your/url/here.php',
error: function(xhr, status, error) {
// The status returns a string, and error is the server error response.
// You want to check if there was a timeout:
if(status == 'timeout') {
$.ajax();
}
}
});
See the jQuery docs for more info.

Categories

Resources