Tuesday, August 5, 2008

Solving cross domain problems

The problem

At times we need to integrate pages from two/ more domains into a single page. Consider for example the case where the content management (cms) happens by a 3rd party in a specific domain and say we have our page which belongs to some other domain and we want to include this cms functionality into our page. One common way of sloving this is by including the content management service (cms) using an iFrame and let this included page and the parent page communicate via backend server communications. This has problems: the iframe (cms) is of some other web domain not belonging to the parent page's domain... this makes cms javascripts in-accessible i.e. the colour component/ calendar component doestnt work fine. IE throws Access Denied ; mozilla doesnt execute anything... it just ignores this cross domain js.

This seem to make some sence: as they are cross domain pages... it's more logical taht they remain independent. Then how do we solve this issue?

There is a way:

1. From a webserver make a URL call to the 2nd webserver using a JSP/ servlet
2. Let the user send his required parametrs as a request to the 1st webserver.
3. This webserver inturn would call the 2nd webserver, gets the data, processes internal urls (like


i.e. we will write a glue code on a JSP/ Servlet of webserver1 and the client makes all his calls to this as if the webserver 1 is doing all the work; which inturn pulls the content from the webserver 2.

Example:
I implemented this and found it working. Excepth that i need to implement the cookies which i would do soon. The example is as follows;

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"

pageEncoding="ISO-8859-1"%>

DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<html>

<head>

<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">

<title>Insert title heretitle>

head>

<body>

<form action="pcmBroker.jsp" method="post" >

<input type="text" name="webUrl" maxlength="100" />

<input type="submit" />

form>

body>

html>


Now the broker which is a glue code: this is the one which takes the calls from the the jsp, resolves it and makes a new connection to the server in diff domain. The masterUrl and masterContext refers to the newDomain servers URL & context. THe master context is the one which would be replaced with brokerUrl and brokar param. The workign is as follows:

1. The 3rd party server has all the urls starting with masterContext (adm say)
2. The broker page replaces this (generateUrl()) assignes it to param:brokerParam and constructs a new url so that when this page is submitted it comes to broker page.
3. On receiving at the broker page by using brokerParam the 3rd party url is resolved, a new connection is made, and response is sent back.

<%@page import="java.net.URLEncoder"%>

<%@page import="java.util.Enumeration"%>

<%@page import="java.io.IOException"%>

<%@page import="java.net.MalformedURLException"%>

<%@page import="java.io.BufferedInputStream"%>

<%@page import="java.io.OutputStream"%>

<%@page import="java.io.DataInputStream"%>

<%@page import="java.io.InputStream"%>

<%@page import="java.net.URLConnection"%>

<%@page import="java.net.URL"%>

<%!String masterUrl = "http://10.1.39.191:8080/adm";

String masterContext = "/adm";

String brokerUrl = "http://localhost:8080/yui/pcmBroker.jsp";

String brokerParam = "webUrl";


public String generateUrl(String content) {

String clientStr = content.replaceAll(masterContext, brokerUrl + "?" + brokerParam + "=");

return clientStr;

}


public String generateCompleteMasterUrl(HttpServletRequest request){

//get the master url to which we need to submit; request parameters

Enumeration params = request.getParameterNames();

String serverParams = "";

for(String param = params.nextElement();params.hasMoreElements();param = params.nextElement()){

if(param.equals(brokerParam))

continue;

if(serverParams.trim().length()>0)

serverParams += "&";

serverParams += URLEncoder.encode(param) + "=" + URLEncoder.encode(request.getParameter(param));

}

String webUrl = request.getParameter("webUrl");

//remove jsessionId from param

/*if(webUrl.contains("jsessionid")){

int jsessStart = webUrl.indexOf("jsessionid");

//int jsessEnd = webUrl.indexOf(";",jsessStart);

webUrl = webUrl.substring(0,jsessStart-1);

}*/

if(serverParams!=null && serverParams.trim().length()>0)

return masterUrl + webUrl+ "?" + serverParams;

else

return masterUrl + webUrl;

}

%>


<%

try {

String url = generateCompleteMasterUrl(request) ;

System.out.println("web Url:: " + url);

URL master = new URL(url);

URLConnection yahooConnection = master.openConnection();

InputStream istr = yahooConnection.getInputStream();

if (url.indexOf(".jpg")== -1 && url.indexOf(".gif")== -1 ) {

DataInputStream dis = new DataInputStream(istr);

String inputLine;

while ((inputLine = dis.readLine()) != null) {

String htmlSrc = generateUrl(inputLine);

%>


<%=htmlSrc%>


<%

}

dis.close();

}else{

System.out.println("procesing image *** " + url );

OutputStream os = response.getOutputStream();

BufferedInputStream bis = new BufferedInputStream(istr);

response.setContentType("image/gif");

byte[] b ;

int maxBuffSize = 256 * 1024;

int available =0;

while(true){

available = bis.available();

if(available >maxBuffSize){

b = new byte[maxBuffSize];

}else

b = new byte[available];

int readBytes = bis.read(b);

if(readBytes <= 0)

break;

os.write(b,0,readBytes);

}

os.flush();

os.close();

System.out.println("processing the image is complete");

}

} catch (Exception e) {

e.printStackTrace();

}

%>



This is a working example except that

1. cookies is not yet implemented : http://www.hccp.org/java-net-cookie-how-to.html

2. relative urls are not being supported.

If these can be done then I would say this as a complete solution. Hows it???? :)

No comments:

Post a Comment