Wednesday, April 14, 2010

HTTP Server with logging in 20 lines of Groovy code

Developing web services often there is need for testing client against mock implementation. You can develop web service that will return response with mock data. Quicker way is to serve predefined SOAP response. Groovy can be very handy to do just that. Basically you can use Groovy CLI with -l option to run Groovy script against TCP port. Simple server that logs HTTP headers that was used as starting point you can find here. Here is the server code:
if (init) {
  request = "";
  log = new File('server.log')
}
if (line.size() > 0) {
  request += line + "\n"
}
else {
  response = 'HTTP/1.0 200 OK\n'
  responseFile = new File('SoapResponse.xml').text
  responseSize = responseFile.bytes.length
  response += "Content-Type: text/xml\n"
  response += "Content-Length: ${responseSize}\n\n"
  response += responseFile
  out << response

  log << "${new Date().format('dd.MM.yyyy HH:mm:ss.SSS')} - REQUEST: '\n${request}'\n\n"
  log << "${new Date().format('dd.MM.yyyy HH:mm:ss.SSS')} - RESPONSE: '\n${response}'\n\n"
  return "success"
}
Save this code as GroovyServer.groovy in directory where you have yours SoapResponse.xml and run it with:
groovy -l 8000 GroovyServer.groovy
If you go in your browser to http://localhost:8000 you should see yours SoapResponse.xml in browser. Now you can test your web service clients against this mock response. If you are curious how this works you can take a peek at groovy.ui.GroovySocketServer class from Groovy source. The interesting part is below:
...
String line = null;
script.setProperty("out", writer);
script.setProperty("socket", socket);
script.setProperty("init", Boolean.TRUE);
while ((line = reader.readLine()) != null) {
    // System.out.println(line);
    script.setProperty("line", line);
    Object o = script.run();
    script.setProperty("init", Boolean.FALSE);
    if (o != null) {
        if ("success".equals(o)) {
            break; // to close sockets gracefully etc...
        } else {
            if (autoOutputFlag) {
                writer.println(o);
            }
        }
    }
    writer.flush();
}
...
From the Java source one can see that Groovy script can't know when it gets last line from socket. Groovy server logs lines from request until it gets empty one. Usually there is empty line between header and body in POST so one will see only headers from HTTP request. Response is logged in complete. Feel free to reuse this code as you wish.

No comments:

Post a Comment