I've been working on browser extensions that interact with a local application running a WebSocket server.
Safari and Chrome Extensions were very easy to implement, and after some headache getting a feel for FF development, I thought I would be able to implement WebSockets as I had in the other browsers. However I have had some issues.
I understand that I can't directly create a WebSocket in the "main" js file, and so attempted to use workarounds I found on the internet:
https://github.com/canuckistani/Jetpack-Websocket-Example uses a page-worker as a sort of proxy between main and the WebSocket code. When I implement this code, my WebSocket connection immediately errors w/ {"isTrusted":true} as the only information.
I also tried to use a hiddenframe as it appears this is how 1Password deals with websocket communication in their FF Addon, but this also results in the same immediate error.
When I simply open a websocket connection to my server in my normal FF instance, it connects perfectly, but so far, I haven't gotten anything to work from addon.
making pageWorker with:
var pw = pageWorker.Page({
contentUrl: self.data.url('com.html'),
contentScriptFile: self.data.url('com.js')
})
com.html:
<!DOCTYPE HTML>
<html>
<body>
</body>
</html>
com.js:
document.onready = launchCom();
// Could this need to be on ready?
function launchCom() {
console.log("[com.js] launchCom Called");
var wsAvailable = false;
if ("WebSocket" in window) {
console.log("[com.js] Detected Websocket in Window, attempting to open...");
// WebSocket is supported.
ws = new WebSocket('ws://localhost:9001');
wsAvailable = true;
} else {
console.log("[com.js] Websocket is not supported, upgrade your browser!");
}
}
ws.onmessage = function(event) {
console.log(event.data);
}
ws.onopen = function(evt) {
console.log("[com.js] ws opened. evt: " + evt);
}
ws.onerror = function(evt) {
console.log("[com.js] ws error: " + JSON.stringify(evt));
}
Running this results in:
console.log: xxx: [com.js] launchCom Called
console.log: xxx: [com.js] Detected Websocket in Window, attempting to open...
console.log: xxx: [com.js] ws error: {"isTrusted":true}
console.log: xxx: [com.js] ws closed. evt: {"isTrusted":true}
Any help would be greatly appreciated!
I've solved the problem:
I'm using https://github.com/zwopple/PocketSocket in my OS X application as my server, and there appears to be an issue with PocketSocket and FF.
After changing PocketSocket's PSWebSocketDriver.m line 87 code from
[[headers[#"Connection"] lowercaseString] isEqualToString:#"upgrade"]
to
[[headers[#"Connection"] lowercaseString] containsString:#"upgrade"]
per https://github.com/zwopple/PocketSocket/issues/34,
I was able to open a WebSocket connection from FF addon using the original code, but the server errored on messages.
Setting network.websocket.extensions.permessage-deflate to false in about:config allowed messages to be sent so I added
require("sdk/preferences/service").set("network.websocket.extensions.permessage-deflate", false);
to my main.js and everthing is working!
The tiny change to PocketSocket's code hasn't had any effects on the server interacting with other WebSocket clients.
I also got stuck in similar situation as websocket can't be implemented directly in main.js. I also did the same as you did , may be server is refusing connection. Snippet from my code look like below :
main.js
var wsWorker = require('sdk/page-worker').Page({
contentURL: "./firefoxScript/webSocket.html",
contentScriptFile : ["./firefoxScript/webSocket.js"]
});
webSocket.html
<html>
<head>
<title></title>
</head>
<body>
</body>
</html>
webSocket.js
var ws = new WebSocket('ws://localhost:9451');
ws.onopen = function() {
console.log('Connection open...');
};
ws.onclose = function() {
console.log('Connection closed...');
};
ws.onmessage = function(event) {
console.log('Message recieved...');
};
ws.onerror = function(event) {
console.log('Connection Error...');
};
It's perfectly working fine for me.
Related
I have the following code on my static client side:
socket.io.js file calling:
<script src="https://rancher.mysite.com/mymodule/socket.io/socket.io.js"></script>
JS File content:
var socket = io.connect('https://rancher.mysite.com/', {
'path':'/mymodule/socket.io'
});
socket.on('mymodulefunction', function (msg) {
/// Do something (it doesn't call)
});
But socket.io tries to establish the connection with a different address. I can see this on browser developer tools and the address that he is trying to call in "Network" tab is: "https://rancher.mysite.com/socket.io" instead of "https://rancher.mysite.com/mymodule/socket.io".
Please, what am I doing wrong? I'm stuck in this problem for hours...
I am developing websocket server with netty frame work version 4.1.6.
I am using the sample code from netty example site
This is my server source code:
public class WebSocketServer
{
static final int PORT = 4466;
public static void main(String[] args)
{
final SslContext sslCtx;
EventLoopGroup bossGroup = new NioEventLoopGroup(1);
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
SelfSignedCertificate ssc = new SelfSignedCertificate();
sslCtx = SslContextBuilder.forServer(ssc.certificate(), ssc.privateKey()).build();
ServerBootstrap b = new ServerBootstrap();
b.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.handler(new LoggingHandler(LogLevel.INFO))
.childHandler(new WebSocketServerInitializer(sslCtx));
Channel ch = b.bind(PORT).sync().channel();
System.out.println("Open your web browser and navigate to " +
"http://127.0.0.1:" + PORT + '/');
ch.closeFuture().sync();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
}
An WebSocketServerInitializer source code:
public class WebSocketServerInitializer extends ChannelInitializer<SocketChannel>
{
private static final String WEBSOCKET_PATH = "/websocket";
private final SslContext sslCtx;
public WebSocketServerInitializer(SslContext sslCtx) {
this.sslCtx = sslCtx;
}
#Override
public void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast(sslCtx.newHandler(ch.alloc()));
pipeline.addLast(new HttpServerCodec());
pipeline.addLast(new HttpObjectAggregator(65536));
pipeline.addLast(new WebSocketServerCompressionHandler());
pipeline.addLast(new WebSocketServerProtocolHandler(WEBSOCKET_PATH, null, true));
// pipeline.addLast(new WebSocketIndexPageHandler(WEBSOCKET_PATH));
pipeline.addLast(new WebSocketFrameHandler());
}
}
This is my Html code:
<html>
<head>
<script type="text/javascript">
// Let us open a web socket
var ws = null;
function WebSocketTest()
{
if ("WebSocket" in window)
{
alert("WebSocket is supported by your Browser!");
// Let us open a web socket
ws = new WebSocket("wss://localhost:4466/websocket");
ws.onopen = function()
{
// Web Socket is connected, send data using send()
ws.send("Message to send");
alert("Message is sent...");
};
ws.onmessage = function (evt)
{
var received_msg = evt.data;
alert(received_msg);
//alert("Message is received...");
};
ws.onclose = function()
{
// websocket is closed.
alert("Connection is closed...");
};
window.onbeforeunload = function(event) {
socket.close();
};
}
else
{
// The browser doesn't support WebSocket
alert("WebSocket NOT supported by your Browser!");
}
}
</script>
</head>
<body>
<div id="sse">
Run WebSocket
</div>
</body>
</html>
I browse the page using Chrome browser and got the following message when I click on the link in the web page.
WebSocket connection to 'wss://localhost:4466/websocket' failed: Error in connection establishment: net::ERR_INSECURE_RESPONSE
According to some discussions here, and the netty websocket sample code, wss must be forwarded by HTTPS. However, when I change the following javascript statement in my web page:
ws = new WebSocket("wss://localhost:4466/websocket");
to
ws = new WebSocket("wss://echo.websocket.org");
It works fine. It make me confusing, Why the site echo.websocket.org can working without https? Why my server cannot? are there something missing in my server source code?
PS: the echo.websocket.org example found in the following url:
http://jsbin.com/muqamiqimu/edit?js,console
Your browser is failing to connect to your websocket server, because it detected it is insecure.
This happens because when the browser tries to connect to your server, it will check the SSL certificate. This certificate is basically a proof that says your server is claiming to be the authoritative server for localhost.
Your server claims this by its certificate, what in your case is signed by itself, that's basically the SelfSignedCertificate class, and it's claiming to be "example.com".
This creates 2 issues:
Your browser connects to localhost, but instead of getting a certificate for localhost, it gets 1 for example.com
Your browser does not trust the signer of the certificate to have the authority to make certificates, causing it to be rejected.
There are multiple ways to solve this:
Getting a valid certificate and hosting your application on a server
This would be the recommended solution for production, depending where you get your valid certificate, it may or may not cost money.
Bypass the certificate warning
By manually going to http://localhost:4466/ you can skip past the certificate warning, and basically this adds a 1 time exception for the certificate rule, till you restart your browser
Configuring google chrome to accept invalid certificates for localhost
While this can be insecure (but not as insecure as turning off all certificate validation), it can be a great way to test ssl on development machines.
You can turn ssl validation of for localhost by going to chrome://flags/#allow-insecure-localhost and turning that option on. Notice that you might be required to set the domain of your certificate to localhost when using this option by calling the new SelfSignedCertificate("localhost"); contructor.
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
function WebSocketTest()
{
var ws = $.gracefulWebSocket("ws://localhost/Node/");
ws.onopen=function(ev){
alert('Connected to server');
};
ws.send("Client is sending message");
ws.onmessage = function (event) {
var messageFromServer = event.data;
alert('Message' +messageFromServer);
};
ws.onerror=function(ev){
alert('Error' +ev.code);
};
}
<div >
Run WebSocket
</div>
Here I have also added gracefulWebSocket library but Stackoverflow just removed it .I am using chrome browser for this Please help me Thanks in advance
You include js file from there? https://github.com/ffdead/jquery-graceful-websocket
What console tells you? (Developer Tools - F12 key shortcut on Chrome).
I am trying to create a simple program to send a message to a socket in plain text. The sender is a webpage in javascript using websocket and the server is a C program. I don't have any control over the C code but I have been assured by the codes owners that I can use simple javascript to send the message. My code is as follows:
<!DOCTYPE HTML>
<html>
<head>
<script type="text/javascript">
//initialize the websocket ws
var ws;
//Open the socket connection
function openSock() {
//test for Websocket compatibility in the browser
if ("WebSocket" in window) {
// log socket attempt
console.log("Attempting to open socket!");
//open web socket ws
ws = new WebSocket("ws://192.168.6.222:11000/echo");
} else { // else the browser doesn't support WebSocket
//Websocket is not supported
alert("APS NOT supported by your Browser!");
}
}
//send the command to socket ws
function sendCommand() {
console.log("Attempting to Send Message");
ws.send("your message here");
}
//close the socket ws
function closeSock() {
console.log("Closing Socket");
// close socket ws
ws.close();
}
</script>
</head>
<body>
<div id="sse">
<input type=submit value="open">
<input type=submit value="send">
<input type=submit value="close">
</div>
</body>
</html>
When I click the connect button I get this error:
WebSocket connection to 'ws://192.168.6.222:11000/echo' failed: Error during WebSocket handshake: net::ERR_CONNECTION_RESET
I have checked the firewall and the port seems to be open. After spending a fair amount of time troubleshooting the server (making sure it is running and on the network, etc.) I am wondering if I did something wrong with this client side code.
From my limited knowledge and the reading I have done this looks correct but any help is welcome.
This is probably super late but I just ran into a similar problem while using Django channels. I fixed it by adding a slash (/) at the end of the URL.
ws = new WebSocket("ws://192.168.6.222:11000/echo/");
How does the server side of the connection look like?
Maybe you are using a faulty WebSocket Lib which does not provide a valid handshake.
Because when testing the client against ws://echo.websocket.org everything seems to work perfectly fine. This strongly suggests that the websocket client is not source of the problem.
Make sure that your queue is running properly, in my case that was the issue
In Firefox (at least), if you hit ESC, then it will close all open WebSockets connections.
I need to capture that disconnection and try to re-connect once it's available again.
Here's an example of the code I've tried to implement, but nothing I can figure out will catch the error and allow me to handle it gracefully.
Have a look at the code: http://jsfiddle.net/w5aAK/
var url = "ws://echo.websocket.org";
try {
socket = window['MozWebSocket'] ? new MozWebSocket(url) : new WebSocket(url);
socket.onopen = function(){
console.log('Socket is now open.');
};
socket.onerror = function (error) {
console.error('There was an un-identified Web Socket error');
};
socket.onmessage = function (message) {
console.info("Message: %o", message.data);
};
} catch (e) {
console.error('Sorry, the web socket at "%s" is un-available', url);
}
setTimeout(function(){
socket.send("Hello World");
}, 1000);
Turn on your console and watch the output.
Am I doing something wrong here, or is it just not possible because the connection is running outside of the scope of the JS script?
Any input would be helpful.
Thanks!
You can attach a handler to the socket.onclose event. It will be called when you hit ESC and the connection is interrupted.
See: http://jsfiddle.net/w5aAK/1/
One problem that you can't get around at the moment is the interrupted error being output to the console. There's no way of capturing that at the moment I'm afraid.
You can't catch it and it's not your fault. It's FireFox bug. Vote for it here:
https://bugzilla.mozilla.org/show_bug.cgi?id=712329
I personally tried all kind of solutions:
event handlers onunload onbeforeunload onclose try..catch some js error handling 3rd party services etc.
You can log to console your socket, it's closed before unload, but FF thinks different.. :(
Solution (not answer directly to the answer, but it works):
It's a bug, so you can't catch, but this info is not Solution. After all kind of crazy workarounds and tries to catch that bug, i finally found this working. If you use socket.io to work with WebScokets it can work with different transport technologies. xhr-polling works with Firefox.
if (/Firefox[\/\s](\d+\.\d+)/.test(navigator.userAgent)) { //test for Firefox/x.x or Firefox x.x (ignoring remaining digits);
socket = io.connect('//' + node_server + '/', {
transports: ['polling']
});
} else {
socket = io.connect('//' + node_server + '/');
}
What helped me - might help you too:
Web Socket support in Node.js/Socket.io for older browser
Define transport types on the client side
socket.io doens't work with transports: [ 'xhr-polling' ]