I have a javascript API that it's included in some websites. For some reasons there is a need for communicate that browser side with a desktop application written in Java. As you can see, all is local to the host.
My first solution was to use plugins/extensions for each known browser, but the lack of good support and the bunch of dependencies stop me to opt for that option. Then my second approach was to use websockets in both sides, with the server in the Java app, and the client being the browser, everything will going to be perfect, but then a big problem come to the surface: HTTPS websites can't establish connection with a insecure websocket server, not matter of Java, and not matter of if the server is on the localhost.
The java_websocket API that I've been using was not good enough to resolve this problem, and in google Jetty is a good name that sound for my purposes. I get involve with Jetty in few hours, and after some examples I got two classes, a server endpoint (EchoSocket) and the server (EventServer):
EventServer.java
import java.util.logging.Level;
import java.util.logging.Logger;
import org.eclipse.jetty.server.HttpConfiguration;
import org.eclipse.jetty.server.HttpConnectionFactory;
import org.eclipse.jetty.server.SecureRequestCustomizer;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.SslConnectionFactory;
import org.eclipse.jetty.server.handler.DefaultHandler;
import org.eclipse.jetty.server.handler.HandlerList;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.eclipse.jetty.websocket.jsr356.server.ServerContainer;
import org.eclipse.jetty.websocket.jsr356.server.deploy.WebSocketServerContainerInitializer;
public class EventServer {
public static void main(String[] args) {
try {
Server server = new Server();
int httpsPort = 8771;
SslContextFactory scf = new SslContextFactory("mykeystore.jks");
scf.setKeyStorePassword("blaStore");
scf.setKeyManagerPassword("blablaKey");
SslConnectionFactory sslConnectionFactory = new SslConnectionFactory(scf, "http/1.1");
HttpConfiguration https = new HttpConfiguration();
https.setSecurePort(httpsPort);
https.setSecureScheme("https");
https.addCustomizer(new SecureRequestCustomizer());
ServerConnector sslConnector = new ServerConnector(server,
sslConnectionFactory,
new HttpConnectionFactory(https)
);
sslConnector.setPort(httpsPort);
server.addConnector(sslConnector);
HandlerList baseHandler = new HandlerList();
server.setHandler(baseHandler);
ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS); //ServletContextHandler.SESSIONS
context.setContextPath("/");
baseHandler.addHandler(context);
ServerContainer jsrContainer = WebSocketServerContainerInitializer.configureContext(context);
jsrContainer.addEndpoint(EchoSocket.class);
baseHandler.addHandler(new DefaultHandler());
server.start();
server.dump(System.err);
server.join();
} catch (Throwable ex) {
ex.printStackTrace(System.err);
}
}
}
EchoSocket.java
import javax.websocket.OnError;
import javax.websocket.OnMessage;
import javax.websocket.server.ServerEndpoint;
@ServerEndpoint(value="/echo")
public class EchoSocket
{
@OnMessage
public void onMessage(javax.websocket.Session session, String message){
session.getAsyncRemote().sendText("welcomeeee");
}
@OnError
public void onError(Throwable cause)
{
cause.printStackTrace(System.err);
}
}
Using a Websocket online test I can communicate from Mozilla Firefox and Opera, but the connection it's disconnected after some minutes, and in some times there is an undefined error that close the connection.
In case of Microsoft Edge and IE nothing works, when I wrote the URI as wss://localhost:8771/echo the error is:
SCRIPT12017: WebSocket Error: SECURITY_ERR, Cross zone connection not allowed
And when I try with wss://127.0.0.1:8771/echo the error is:
SCRIPT12038: WebSocket Error: Network Error 12038, The host name in the certificate is invalid or does not match
In Google Chrome neither way of URI seems work, there is not connection, the error is:
WebSocket connection to 'wss://127.0.0.1:8771/echo' failed: Error in connection establishment: net::ERR_NETWORK_CHANGED
and in the other case:
WebSocket connection to 'wss://localhost:8771/echo' failed: Error in connection establishment: net::ERR_CONNECTION_CLOSED
So, I need some help, but may be you can answer me some of the next questions:
- Is correct my example of Jetty?, if not, How can I correct it?
- Should I try another libraries, or older versions of Jetty to make this work in most of the browsers?
- Should I see other implementations of a websocket server in another languages like C#?
- What hostname or SubjectAltName do I have to set in my SSL certificate to allow connections from IE and Edge? Maybe "localhost", or "127.0.0.1" .
Please, thanks in advance, and sorry by my english.