socket.io can't handle errors - ios

I'm trying to make real time application with node.js and socket.io. As I can see the server can see when new user connects but can't return information to client side or something. This is what I've on client side:
<script src="<?= base_url('assets/js/socket.io.js') ?>"></script>
<script>
var socket;
socket = io('http://***.***.***.***:3030', {query: "key=key"});
socket.on('connect', function (data) {
console.log('Client side successfully connected with APP.');
});
socket.on('error', function (err) {
console.log('Error: ' + err);
});
</script>
and this is the server side:
var app = require("express")();
var http = require("http").createServer(app);
var io = require("socket.io")(http);
http.listen(3030, function () {
globals.debug('Server is running on port: 3030', 'success');
});
io.set('authorization', function (handshakeData, accept) {
var domain = handshakeData.headers.referer.replace('http://', '').replace('https://', '').split(/[/?#]/)[0];
if ('www.****.com' == domain) {
globals.debug('New user connected', 'warning');
} else {
globals.debug('Bad site authentication data, chat will be disabled.', 'danger');
return accept('Bad site authentication data, chat will be disabled.', false);
}
});
io.use(function (sock, next) {
var handshakeData = sock.request;
var userToken = handshakeData._query.key;
console.log('The user ' + sock.id + ' has connected');
next(null, true);
});
and when someone comes to website I'm expecting to see in console output "New user connected" and I see it: screen shot and the user should see on the browser console output: "Client side successfully connected with APP." but I doesn't show. Also I tried to emit data to user but it doesn't work too. I can't see any errors or something. This is not the first time I'm working with sockets but the first time facing such as problem. Maybe there is any error reporting methods to handle errors or something? Also I can't see output on io.use(....) method

The solution is to pass "OK" sign just after authenticating to do the next method:
io.set('authorization', function (handshakeData, accept) {
var domain = handshakeData.headers.referer.replace('http://', '').replace('https://', '').split(/[/?#]/)[0];
if ('www.****.com' == domain) {
globals.debug('New user connected', 'warning');
accept(null, true);
} else {
globals.debug('Bad site authentication data, chat will be disabled.', 'danger');
return accept('Bad site authentication data, chat will be disabled.', false);
}
});

Related

How to store a list of querys and send them to mySQL when online?

I'm trying to build a webapp that will work offline.
I found JS Service worker and i have now implemented it in my app to store some static pages.
Now i'd like to build a HTML FORM where the user fills in stuff that will be saved to the cache if the user is offline.. but directly sends to mysql when the user is online.
It will be like a list with querys that will execute when user comes online.
How can i save a query string to the cache, and then check if online and send it with Ajax? to php and mySQL.
First off, how do i save a query string to the cache?
Second.. how do i find out when online and then fetch the query string from the cache?
This is what i got to cache my pages:
importScripts('cache-polyfill.js');
self.addEventListener('install', function(e) {
e.waitUntil(
caches.open('offlineList').then(function(cache) {
return cache.addAll([
'/app/offline_content/'
]);
})
);
});
self.addEventListener('fetch', function(event) {
console.log(event.request.url);
event.respondWith(
caches.match(event.request).then(function(response) {
return response || fetch(event.request);
})
);
});
EDIT
I'm now reading up on HTML/JS "localStorage"..
Well i solved this by adding data to localStorage:
//ADD DATA
localStorage.setItem(key, JSON.stringify(value));
Then i check for internet connection:
//CHECK INTERNET CONNECTION
const checkOnlineStatus = async () => { //console.log('CHECKING INTERNET..');
try {
const online = await fetch("/img.gif");
return online.status >= 200 && online.status < 300; // either true or false
} catch (err) {
return false; // definitely offline
}
};
const result = await checkOnlineStatus();
result ? updateMysql() : console.log('NO INTERNET..');
In the updateMysql() function i load all the localStorage and send it with ajax to php and mySQL.
var query = JSON.parse(localStorage.getItem(key));

Ajax request fail over https on iOS browser but not through http

Hi thanks in advance for the help.
We're running a mobile web app that has been working fine on all browsers when it originally went live earlier this year.
About the app:
Running on IIS 8.5.
Certificate is from LetsEnctrypt.org
REST web service is running on .NET Web API 2.
Front end is AngularJS
Sample Ajax Call:
$http.post('/api/User/Validate', loginData)
.then(function (response) {
alert("_login.Success: " + JSON.stringify(response, null, 4));
if (response.data.StatusCode == 200) {
//console.log("Successfult Validate" + response);
var token = response.data.Data[0].Token;
var authData = {
token: token.TokenStr,
expiryDate: token.ExpiryDate,
companyId: response.data.Data[0].CompanyId,
userId: response.data.Data[0].UserId
};
_setAuthData(authData);
deferred.resolve(response.data);
}
else {
console.log("Error while validating ", response);
deferred.resolve(response.data);
}
}, function (err, status) {
alert("_login.Error: " + JSON.stringify(err, null, 4) + " " + status);
_logOut();
deferred.reject(err);
});
I've added debug logging to troubleshoot this and i see the request hit that backend without any errors that i can see but when the browser gets the request the error callback function gets executed instead of the success one. If i try the same code through http it works perfectly.
Thoughts?
Thanks!

A signalr function is not working in firefox

I want to redirect on a specific page after file download in MVC. And in my application signalr is already configured. So I used following code in controller
var hubContext = GlobalHost.ConnectionManager.GetHubContext<ChatHub>();
hubContext.Clients.All.RedirectToBatch(BatchID, Convert.ToInt32(Session["AgencyUserID"]));
return File(stream, "text/plain", (BatchName + "." + ediExtension));
And in view I used following code
var chat = $.connection.chatHub;
chat.client.redirectToBatch = function (BatchID, AgencyUserID) {
if (currentUserID == AgencyUserID) {
var claimlist = $('#ClaimListGrid');
if (claimlist.length > 0) {
window.location = "/Billing/ClaimSummary/" + BatchID;
}
}
};
$.connection.hub.start().done();
$.connection.hub.disconnected(function () {
setTimeout(function () {
$.connection.hub.start();
}, 5000); // Restart connection after 5 seconds.
});
I think this code will work for redirect to a page after file download. And this works in chrome proper but In firefox this is not working fine.
In firefox following error is occurring
no element found
AND
Firefox can't establish a connection to the server at ws://localhost:2804/signalr/connect?transport=webSockets&clientProtocol=1.5&connectionToken=4p2zZ%2B%2F0ok4B9uAxcslDlTv4kpT%2BGbW2nav6S%2Fe5RlSqQgS2gaFr7%2BlQiIrHZu5cPapvjoeZNB8bXM6AeF%2B1b1RS0P6y%2FETaNeAC5hDQkGrwH5xgDfjDHWt%2B%2B52K7yaD&connectionData=%5B%7B%22name%22%3A%22chathub%22%7D%5D&tid=10.
What should I do for this problem?

how to secure or set a rails style before_filter for all angular controllers?

I'm using angularjs for the front end and rails + devise for authentication on the backend.
On the front end I have added a responseInterceptor to redirect to the /#/sign_in page upon any 401 response from any xhr request and display a growl style pop-up message using toastr.
App.config(['$httpProvider', function ($httpProvider) {
$httpProvider.responseInterceptors.push('securityInterceptor');
}]);
App.factory('securityInterceptor', ['$injector', '$location', '$cookieStore', function ($injector,$location,$cookieStore) {
return function(promise) {
var $http = $injector.get('$http');
return promise.then(null, function(response){
if (response.status === 401) {
$cookieStore.remove('_angular_devise_user');
toastr.warning('You are logged out');
$location.path('/#/sign_in');
}
});
};
});
My problem is, when I click on a page that loads several xhr requests during the controllers initialization, for example:
var products = Product.query();
var categories = Category.query();
var variations = Variation.query();
These are needed for various navigation components and they all fire off in parallel, resulting in several duplicate growl-style messages.
Is there a way to make angular quit on the first 401 and stop execution of the rest of the controller from within the interceptor? In a traditional rails app, there would be a "before_filter" that stops regular execution, preventing the page and queries from loading... what's the best way to do this in angular?
I've been pondering about this problem for my own apps too. A sketch of my thoughts (NOT REAL IMPLEMENTATION, SO BEWARE):
A userData service keeps track of whether the user is logged in + other information (e.g. user name, real user name etc):
App.service("userData", function() {
var currentData = {
loggedIn: false
};
function getCurrent() {
return currentData;
}
// called when the user logs in with the user data
function loggedIn(userData) {
// the object is REPLACED to avoid race conditions, see explanation below
currentData = angular.extend({loggedIn: true}, userData);
}
return {
getCurrent: getCurrent,
loggedIn: loggedIn
};
});
The interceptors keep track of the currentData. If an interceptor receives HTTP 401 and the loggedIn flag is true, it changes the flag to false and redirects to the login view. If an interceptor receives HTTP 401 and the loggedIn flag is false, it does nothing besides rejecting the request, because another interceptor has done the view redirection.
When the user logs in, the currentData is replaced, so as to avoid situations with delayed responses (e.g. call1 and call2 are initiated, call1 responds 401; call2 also results in 401, but the delivery of the actual response is delayed; then the user logs in again; then call2 receives its 401; the second 401 should not overwrite the current state)
App.config(["$provide", "$httpProvider", function($provide, $httpProvider) {
$provide.factory("myHttpInterceptor", ["$q", "userData", "$cookieStore", "toastr", "$location",
function($q, userData, $cookieStore, toastr, $location) {
return {
request: function(config) {
config.currentUserData = userData.getCurrent();
return config;
},
responseError: function(rejection) {
if( rejection && rejection.status === 401 && rejection.config && rejection.config.currentUserData && rejection.config.currentUserData.loggedIn ) {
rejection.config.currentUserData.loggedIn = false;
$cookieStore.remove('_angular_devise_user');
toastr.warning('You are logged out');
$location.path('/#/sign_in');
}
return $q.reject(rejection);
}
};
}
]);
$httpProvider.interceptors.push("myHttpInterceptor");
});
Also note I am using the newer way to register interceptors, as $httpProvider.responseInterceptors seems to be deprecated.

two way communication between extension and content javascript files

i am trying to accomplish a two way communication request response in my firefox sidebar extension, i have a file named event.js this resides on the content side, i have another file called sidebar.js file which is residing in the xul. I am able to communicate from event.js to sidebar.js file using the dispatchEvent method. my event in turn raises a XMLHttpRequest in sidebar.js file which hits the server and sends back the response. Now, here i am unable to pass the response to the event.js file. I want the response to be accessed in the event.js file. Till now i have achieved only one way communication. Please help me in getting the two way communication.
Code is as follows:
// event.js file
// This event occurs on blur of the text box where i need to save the text into the server
function saveEvent() {
var element = document.getElementById("fetchData");
element.setAttribute("urlPath", "http://localhost:8080/event?Id=12");
element.setAttribute("jsonObj", convertToList);
element.setAttribute("methodType", "POST");
document.documentElement.appendChild(element);
var evt = document.createEvent("Events");
evt.initEvent("saveEvent", true, true);
element.dispatchEvent(evt);
//Fetching the response over here by adding the listener
document.addEventListener("dispatchedResponse", function (e) { MyExtension.responseListener(e); }, false, true);
}
var MyExtension = {
responseListener: function (evt) {
receivedResponse(evt.target.getAttribute("responseObject"));
}
}
function receivedResponse(event) {
alert('response: ' + event);
}
// sidebar.js file
window.addEventListener("load", function (event) {
var saveAjaxRequest = function (urlPath, jsonObj, methodType, evtTarget) {
var url = urlPath;
var request = Components.classes["#mozilla.org/xmlextras/xmlhttprequest;1"].createInstance(Components.interfaces.nsIXMLHttpRequest);
request.onload = function (aEvent) {
window.alert("Response Text: " + aEvent.target.responseText);
saveResponse = aEvent.target.responseText;
//here i am again trying to dispatch the response i got from the server back to the origin, but unable to pass it...
evtTarget.setAttribute("responseObject", saveResponse);
document.documentElement.appendChild(evtTarget);
var evt = document.createEvent("dispatchedRes"); // Error line "Operation is not supported" code: "9"
evt.initEvent("dispatchedResponse", true, false);
evtTarget.dispatchEvent(evt);
};
request.onerror = function (aEvent) {
window.alert("Error Status: " + aEvent.target.status);
};
//window.alert(methodType + " " + url);
request.open(methodType, url, true);
request.send(jsonObj);
};
this.onLoad = function () {
document.addEventListener("saveEvent", function (e) { MyExtension.saveListener(e); }, false, true);
}
var MyExtension =
{
saveListener: function (evt) {
saveAjaxRequest(evt.target.getAttribute("urlPath"), evt.target.getAttribute("jsonObj"), evt.target.getAttribute("methodType"), evt.originalTarget);
}
};
});
Why are you moving your fetchData element into the sidebar document? You should leave it where it is, otherwise your content code won't be able to receive the event. Also, use the content document to create the event. Finally, document.createEvent() parameter for custom events should be "Events". So the code after your //here i am again trying comment should look like:
evtTarget.setAttribute("responseObject", saveResponse);
var evt = evtTarget.ownerDocument.createEvent("Events");
evt.initEvent("dispatchedResponse", true, false);
evtTarget.dispatchEvent(evt);
Please note however that your code as you show it here is a huge security vulnerability - it allows any website to make any HTTP requests and get the result back, so it essentially disables same-origin policy. At the very least you need to check that the website talking to you is allowed to do it (e.g. it belongs to your server). But even then it stays a security risk because server response could be altered (e.g. by an attacker on a public WLAN) or your server could be hacked - and you would be giving an attacker access to sensitive data (for example he could trigger a request to mail.google.com and if the victim happens to be logged in he will be able to read all email data). So please make this less generic, only allow requests to some websites.

Resources