Skip to content

Instantly share code, notes, and snippets.

@caub
Last active November 2, 2015 16:16
Show Gist options
  • Save caub/33aa31b380af6b581cb3 to your computer and use it in GitHub Desktop.
Save caub/33aa31b380af6b581cb3 to your computer and use it in GitHub Desktop.
package ws;
import java.lang.reflect.Type;
import java.net.CookieManager;
import java.net.CookieStore;
import java.net.HttpCookie;
import java.net.URI;
import java.util.LinkedHashMap;
import java.util.concurrent.Future;
import org.eclipse.jetty.client.HttpClient;
import org.eclipse.jetty.client.api.ContentResponse;
import org.eclipse.jetty.util.Fields;
import org.eclipse.jetty.util.Fields.Field;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketClose;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketConnect;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketError;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage;
import org.eclipse.jetty.websocket.api.annotations.WebSocket;
import org.eclipse.jetty.websocket.client.ClientUpgradeRequest;
import org.eclipse.jetty.websocket.client.WebSocketClient;
import org.jsoup.Jsoup;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
@WebSocket
public class SEChat {
String email = System.getProperty("se.email");
String password = System.getProperty("se.password");
public static void main(String[] args) throws Exception {
SEChat m = new SEChat();
m.run();
}
Gson gson = new Gson();
Type mapType = new TypeToken<LinkedHashMap<String, Object>>() {}.getType();
public void run() throws Exception {
SslContextFactory sslContextFactory = new SslContextFactory();
sslContextFactory.setTrustAll(true);
HttpClient httpClient = new HttpClient(sslContextFactory);
CookieStore cookieStore = new CookieManager().getCookieStore();
httpClient.setCookieStore(cookieStore);
httpClient.start();
ContentResponse response = httpClient.GET("https://stackoverflow.com/users/login");
String fkey = Jsoup.parse(response.getContentAsString())
.select("input[name=fkey]").attr("value");
System.out.printf("login: %s, fkey: %s%n", response.getStatus(), fkey);
response = httpClient.FORM("https://stackoverflow.com/users/login",
fields("email", email, "password", password, "fkey", fkey));
System.out.printf("login submit: %s%n", response.getStatus());
response = httpClient.GET("http://chat.stackoverflow.com/rooms/1");
fkey = Jsoup.parse(response.getContentAsString())
.select("input[name=fkey]").attr("value");
System.out.printf("chat: %s, fkey: %s%n", response.getStatus(), fkey);
response = httpClient.FORM("http://chat.stackoverflow.com/ws-auth",
fields("roomid", "1", "fkey", fkey));
LinkedHashMap<String, Object> o = gson.fromJson(response.getContentAsString(), mapType);
String url = (String) o.get("url");
System.out.printf("ws-auth: %s, url: %s%n", response.getStatus(), url);
response = httpClient.FORM("http://chat.stackoverflow.com/chats/1/events", fields("fkey", fkey));
o = gson.fromJson(response.getContentAsString(), mapType);
Double time = (Double) o.get("time");
System.out.printf("chat-events: %s, time: %s%n", response.getStatus(), time);
//System.setProperty("org.eclipse.jetty.LEVEL", "DEBUG");
WebSocketClient wsClient = new WebSocketClient(sslContextFactory);
wsClient.setCookieStore(cookieStore);
for(HttpCookie c : cookieStore.getCookies())
System.out.printf(" - %s - %s%n",c,c.getDomain()+c.getPath());
try {
wsClient.start();
ClientUpgradeRequest request = new ClientUpgradeRequest();
//request.setCookiesFrom(cookieStore);
request.setHeader("Host","chat.sockets.stackexchange.com");
request.setHeader("Origin","http://chat.stackoverflow.com");
Future<Session> future = wsClient.connect(getClass().newInstance(), URI.create(url+"?l="+time),request);
Session session = future.get();
session.getRemote().sendString("hello");
} catch (Throwable t) {
t.printStackTrace(System.err);
}
}
@OnWebSocketConnect
public void onConnect(Session sess){
System.out.println("onConnect");
}
@OnWebSocketClose
public void onClose(int statusCode, String reason){
System.out.println("onClose "+ reason);
}
@OnWebSocketError
public void onError(Throwable cause){
System.out.println(cause);
}
@OnWebSocketMessage
public void onMessage(String msg){
System.out.println("onMessage "+ msg);
}
public Fields fields(String... a){
Fields fields = new Fields();
for(int i=0; i<a.length; i+=2)
fields.put(new Field(a[i], a[i+1]));
return fields;
}
}
@joakime
Copy link

joakime commented Apr 7, 2015

Alternative approach.

package jetty.websocket;

import java.io.IOException;
import java.lang.reflect.Type;
import java.net.HttpCookie;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.concurrent.Future;

import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.RequestBuilder;
import org.apache.http.cookie.Cookie;
import org.apache.http.cookie.CookieOrigin;
import org.apache.http.cookie.CookieSpec;
import org.apache.http.impl.client.BasicCookieStore;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.cookie.RFC6265LaxSpec;
import org.apache.http.util.EntityUtils;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.eclipse.jetty.websocket.api.Session;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketClose;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketConnect;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketError;
import org.eclipse.jetty.websocket.api.annotations.OnWebSocketMessage;
import org.eclipse.jetty.websocket.api.annotations.WebSocket;
import org.eclipse.jetty.websocket.client.ClientUpgradeRequest;
import org.eclipse.jetty.websocket.client.WebSocketClient;
import org.jsoup.Jsoup;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;

@WebSocket
public class SEChat
{
    private static final Logger LOG = Log.getLogger(SEChat.class);

    private static final String email = System.getProperty("se.email");
    private static final String password = System.getProperty("se.pass");

    public static void main(String[] args) throws ClientProtocolException, IOException, URISyntaxException
    {
        SEChat m = new SEChat();
        m.run();
    }

    static BasicCookieStore cookieStore = new BasicCookieStore();
    HttpClient httpclient = HttpClients.custom().setDefaultCookieStore(cookieStore).build();
    Gson gson = new Gson();
    Type mapType = new TypeToken<LinkedHashMap<String, Object>>()
    {
    }.getType();

    public void run() throws ClientProtocolException, IOException, URISyntaxException
    {
        HttpResponse r = httpclient.execute(new HttpGet("https://stackoverflow.com/users/login"));
        String fkey = Jsoup.parse(EntityUtils.toString(r.getEntity(),"UTF-8")).select("input[name=fkey]").attr("value");
        System.out.printf("login[%s]: %s%n",r.getStatusLine(),fkey);
        EntityUtils.consume(r.getEntity());

        r = httpclient.execute(RequestBuilder.post().setUri(new URI("https://stackoverflow.com/users/login")).addParameter("email",email)
                .addParameter("password",password).addParameter("fkey",fkey).build());
        System.out.printf("Login result: %s%n",r.getStatusLine());
        EntityUtils.consume(r.getEntity());

        r = httpclient.execute(new HttpGet("http://chat.stackoverflow.com/rooms/139"));
        fkey = Jsoup.parse(EntityUtils.toString(r.getEntity(),"UTF-8")).select("input[name=fkey]").attr("value");
        System.out.printf("room/139[%s] %s%n",fkey,r.getStatusLine());
        EntityUtils.consume(r.getEntity());

        r = httpclient.execute(RequestBuilder.post().setUri(new URI("http://chat.stackoverflow.com/ws-auth")).addParameter("roomid","139")
                .addParameter("fkey",fkey).build());
        System.out.printf("ws-auth: %s%n",r.getStatusLine());
        LinkedHashMap<String, Object> o = gson.fromJson(EntityUtils.toString(r.getEntity(),"UTF-8"),mapType);

        String url = (String)o.get("url");
        System.out.printf("ws-auth: url = %s%n",url);

        r = httpclient.execute(RequestBuilder.post().setUri(new URI("http://chat.stackoverflow.com/chats/139/events")).addParameter("fkey",fkey).build());

        System.out.printf("chats/139/events: %s%n",r.getStatusLine());
        String eventsJson = EntityUtils.toString(r.getEntity(),"UTF-8");
        System.out.printf("chats/139/events: %s%n",eventsJson);
        o = gson.fromJson(eventsJson,mapType);
        String time = Long.toString(((Double)o.get("time")).longValue());
        System.out.printf("chats/139/events: time=%s%n",time);

        SslContextFactory sslContextFactory = new SslContextFactory();
        sslContextFactory.setTrustAll(true);
        WebSocketClient client = new WebSocketClient(sslContextFactory);
        try
        {
            client.start();
            URI wsUri = URI.create(url + "?l=" + time);

            LOG.info("Connecting to {}",wsUri);
            ClientUpgradeRequest req = new ClientUpgradeRequest();
            req.setHeader("Origin","http://chat.stackoverflow.com");
            List<HttpCookie> javaCookies = getMatchedCookies(wsUri);
            req.setCookies(javaCookies);
            Future<Session> fut = client.connect(getClass().newInstance(),wsUri,req);
            Session sess = fut.get();
            LOG.info("Connected to {}",wsUri);
            LOG.info("     Session {}",sess);
        }
        catch (Throwable t)
        {
            t.printStackTrace(System.err);
        }
    }

    public List<HttpCookie> getMatchedCookies(URI wsUri)
    {
        // Cookies that match, in java format
        List<HttpCookie> matchedCookies = new ArrayList<>();

        String host = wsUri.getHost();
        int port = wsUri.getPort();
        String scheme = wsUri.getScheme();
        if (port == (-1))
        {
            switch (scheme)
            {
                case "ws":
                    port = 80;
                    break;
                case "wss":
                    port = 443;
                    break;
                default:
                    throw new RuntimeException("Not able to determine port from scheme " + scheme);
            }
        }
        String path = wsUri.getPath();
        boolean secure = wsUri.getScheme().equals("wss");
        CookieOrigin cookieOrigin = new CookieOrigin(host,port,path,secure);

        final CookieSpec cookieSpec = new RFC6265LaxSpec();
        // Get all cookies available in the HTTP state
        final List<Cookie> cookies = cookieStore.getCookies();
        final Date now = new Date();
        for (final Cookie cookie : cookies)
        {
            if (!cookie.isExpired(now))
            {
                if (cookieSpec.match(cookie,cookieOrigin))
                {
                    if (LOG.isDebugEnabled())
                    {
                        LOG.debug("Cookie " + cookie + " match " + cookieOrigin);
                    }
                    matchedCookies.add(new HttpCookie(cookie.getName(),cookie.getValue()));
                }
            }
            else
            {
                if (LOG.isDebugEnabled())
                {
                    LOG.debug("Cookie " + cookie + " expired");
                }
            }
        }

        return matchedCookies;
    }

    @OnWebSocketConnect
    public void onConnect(Session sess)
    {
        LOG.info("onConnect {}",sess);
        sess.getRemote().sendStringByFuture("Hello");
    }

    @OnWebSocketClose
    public void onClose(int statusCode, String reason)
    {
        LOG.info("onClose {}, {}",statusCode,reason);
    }

    @OnWebSocketError
    public void onError(Throwable cause)
    {
        LOG.warn(cause);
    }

    @OnWebSocketMessage
    public void onMessage(String msg)
    {
        LOG.info("onMessage {}",msg);
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment