Using cURL to Interface GWT with an Existing Site

When I learned about Google’s Web Toolkit, I was very excited to know that I finally had a tool that I could use to create the types of user interfaces I wanted to be building. I love the interactivity, the ability for the client to maintain its state rather than having to manage extensive session variables, and the cleaner feel of a page that can perform tasks in the background.

The one challenge I found was interfacing this new tool with my existing web site. I had written a site which uses standard HTML pages to post data back to a PHP/MySQL back end. It has the usual page loads and transitions, and works well. On pages where I didn’t want to reload everything all the time, I use iframes to show more dynamic content. With a smattering of javascript functions, this has been a user friendly and very successful site. But it is a little awkward compared to the sleek appearance of dynamic HTML.

After working out a simple communication technique as described previously, I was left wondering how best to integrate a web tools widget into the existing software. It is entirely possible to load a widget on any of my existing pages, but that doesn’t really accomplish anything. I still needed to have a back-end interface that suited the flexibility of the client. I decided to keep a single URL for communicating with my gwt client, which gives me a single place for the details of loading and formatting data for appropriate objects when they request it.

For me, this touches on a fuzzy area of any communications technique. There are two ends of the communications chain (server and client in this case), and somehow data goes between them. Ideally, encoding would not define (or constrain) data. But that means that both ends need a way to understand what is being communicated. Whether it’s an RPC technique or the fairly raw technique I’ve used, the server and the client both need to know what is being asked. Unfortunately, in a heterogeneous environment (i.e. Java for client, PHP for server) there is not a particularly easy way to share these definitions. I can’t directly load my java class into PHP and have it make sense. And this is still mostly data encoding. If I don’t have any behavior defined for a class, even if I get the entire set of data for an instance, it tells me nothing.

In the basic communication scheme I outlined, I’m using ‘titles’ to refer to specific objects. Most of the data exchanged is intended for display to a user, so I exchange strings. These strings don’t need interpretation on the client side, they just need to be displayed in the proper widget. So it’s really convenient to have the single PHP script on the server for interfacing. By defining titles in the script that correspond to titles used in the gwt client, it is easy to properly exchange this data.

This works well up to the point that I need access to existing functionality. One function of my existing site is a receipt display script. It is a standard format that is familiar and best to continue using. I need to display a receipt given a receipt number. The receipt is returned as an HTML page as a result of an HTTP POST. I could try to load the receipt directly in my client, parse out extra fields and load the data I want. There may even be a good way to do this with DOM functions. But it wouldn’t be compatible with my existing communication scheme, it adds a lot of requirements to the client to understand server software, and it adds another point of maintenance in that the URL in the client will need to stay current with the server URL.

My solution to this is to have the server request the pages it needs from itself. Initially I tried using includes to obtain the data: parse the request from the client, set up any $_POST, $_SESSION and $_GET parameters and include the other PHP script. It worked well until I needed to make two different calls to the same script. It causes some problems with variables (accidental name collisions), which I tried to address by including the files inside of functions. This caused another headache when a file contained a function using “global $var” to refer to a variable outside the function. The situation was this:

function includeFileInServerComm()
{
$var = “used in included file”;
function insideIncludedFile()
{
//$var is now = “” since it refers to the global scope and not the function scope
// so the included script breaks.
global $var;
}
}

The much better solution to this problem is to use the client-URL functions in PHP. These allow the server to make requests as though it is a client. Support will vary depending on your server configuration, but this shouldn’t be a problem if you aren’t trying to manage cookies or follow redirects automatically. I added the following function to ServerComm.php:

/* call doCurl with $target set to the desired file and any get params.
* don’t use a leading /
*/
function doCurl($target, $postFields)
{
// stick target file name at end of path
$parts = explode(”/”, $_SERVER[’REQUEST_URI’]);
$parts[count($parts)-1] = $target;
$uri = implode(”/”, $parts);

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, “http://{$_SERVER[’SERVER_NAME’]}” . $uri);
if ($postFields != “”)
{
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $postFields);
}
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
$response = curl_exec($ch);
curl_close($ch);

return $response;
}

This function will cause the server to load the requested page. Data for posting can be passed in the second argument, and any GET parameters can be appended to the target URI. The response will be returned without headers.

For my receipt example, I have an HTML widget on my gwt application. I want it to display the HTML from the receipt script. But it will take a little processing. I first strip off everything from the start of the response data to the end of the body tag. I then remove everything from the body close tag to the end of the file. Next I remove any input’s since I don’t want strange things showing up in my HTML widget. The final step to make this compatible with the client communication is to strip off all ‘\n’ characters in the data.

This is very convenient because it lets the server use its more powerful regular expressions to process data and format it properly. The client only has to worry about displaying strings, which is quite easy. The client is simpler because it only interfaces with a single point on the server. The server code is improved by isolating any called scripts from the server interface script.



You are viewing a mobilized version of this site...
View original page here

Mobilized by Mowser Mowser