Hi All,
In the process of working on a project that involves loading data and images from a cookie protected server, and I thought I'd share some of my findings. We are working with a custom installation of Jive (
http://www.jivesoftware.com/ a corporate social networking system) on our clients server.
I need to load activity streams and and other data feeds from their system. The catch is that they have overridden Jive's regular way of logging in users and have their own OneLogin system. So when you go to their Jive install, you are redirected to a OneLogin page that you enter a password, then redirected back to Jive which checks the cookies and lets you access information.
Jive has a nice rss system for all the data, however for security they have turned that functionality off, so I am using the REST api to get json files of the data to be loaded. But, the REST api also requires a user to be logged in. This requires me to pass a cookie (JSESSIONID) into my requests. This works great.... about 1/4 of the time :/ so to get around this limitation, I ended up asking for the json file until I get it; if it fails, it tries again. This pounds their server with requests, which is undesirable, but ends up working pretty reliably.
Another consideration is that I need to update the content as regularly as possible to feel like a live view of their activity. So all this loading happens on a thread that I can keep calling ever 5-10 seconds without disrupting other parts of the application.
Part of these Activity posts in Jive is the user's avatar image, and sometimes images they have posted. Initially I thought 'no big deal, loading images is easy in processing,' but, the url's to the images that is loaded in the json file are not .jpg/.png/whatever, they are server requests, which the server responds with base64 strings. So I was getting these strings and using a byte array to translate them to PImages. Then it gets frustrating. Most of the images I was trying worked great, but then I came across a few that had malformed headers. they had both jpeg and exif data, which apparently causes errors in the BufferedImage IOreading I was using. my workaround for this was to simply save the byte array to a local .jpg using saveBytes(), then load that saved image back in. For some reason this works great! :)
Anyway just thought I would share my findings and some code snippets in case anyone else was facing similar issues. so here's my cookie-passing html loading code:
- JSONObject loadJson(String query, Boolean verbose) {
- JSONObject json = null;
- JSONArray dataArray = null;
- try {
- setupClient();
- HttpGet getRequest = new HttpGet(query);
- getRequest.addHeader("accept", "application/json");
- HttpResponse response = httpClient.execute(getRequest);
- org.apache.http.params.SyncBasicHttpParams params = (org.apache.http.params.SyncBasicHttpParams) httpClient.getParams();
- if (response.getStatusLine().getStatusCode() != 200) {
- if (response.getStatusLine().getStatusCode() == 401) {
- return null;
- } else {
- throw new RuntimeException("Failed : HTTP error code : " + response.getStatusLine().getStatusCode());
- }
- }
- InputStreamReader isr = new InputStreamReader((response.getEntity().getContent()));
- BufferedReader br = new BufferedReader(isr);
- String output = "";
- String out;
- while ( (out = br.readLine ()) != null) {
- output += out;
- }
- int jsonStart = output.indexOf("{");
- output = output.substring(jsonStart, output.length());
- try {
- json = new JSONObject(output);
- } catch (JSONException e) {
- println("JSONException in loadJiveJson JSONEx : "+e);
- }
- } catch (ClientProtocolException e) {
- e.printStackTrace();
- } catch (IOException e) {
- e.printStackTrace();
- }
- if (verbose) {
- println("json here: "+json);
- }
- return json;
- }
- void bakeCookies () {
- cookieJsess = cookieMonster("JSESSIONID", jsession, "example.server.com");
- }
- BasicClientCookie cookieMonster(String c, String v, String domain) {
- BasicClientCookie cookie = new BasicClientCookie(c, v);
- cookie.setVersion(1);
- cookie.setDomain(domain);
- cookie.setPath("/");
- return cookie;
- }
- void setupClient() {
- bakeCookies();
- //create the httpClient
- httpClient = new DefaultHttpClient();
- //add the cookie to the client
- httpClient.getCookieStore().addCookie(cookieJsess);
- }
I leave my httpClient open at the end of this loading so I can continue using it in my future update calls and for my image requests, which are done like this:
- PImage loadProtectedImg(String url) {
- PImage pimg = new PImage();
- String output = "";
- try {
- HttpGet getRequest = new HttpGet(url);
- HttpResponse response = httpClient.execute(getRequest);
- byte[] bytes = EntityUtils.toByteArray(response.getEntity());
- ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
- saveBytes("image.jpg", bytes);
- //BufferedImage jimg = ImageIO.read(bis);
- pimg = loadImage("image.jpg");
- //pimg=new PImage(jimg.getWidth(), jimg.getHeight(), PConstants.ARGB);
- //jimg.getRGB(0, 0, pimg.width, pimg.height, pimg.pixels, 0, pimg.width);
- //pimg.updatePixels();
- if (response.getStatusLine().getStatusCode() != 200) {
- throw new RuntimeException("Failed : HTTP error code : " + response.getStatusLine().getStatusCode());
- }
- } catch (ClientProtocolException e) {
- e.printStackTrace();
- } catch (IOException e) {
- e.printStackTrace();
- }
- return pimg;
- }
Sorry if that got a bit rant-ish, been working around the limitations of their REST api and specific installation for a few days now. hopefully some of this helps someone. Or if you have any suggestions on any of the process I'd love to hear!
ak