From 33fac6be6874fb78df89d63803098d903a21d15c Mon Sep 17 00:00:00 2001 From: hns Date: Fri, 17 Oct 2008 12:02:24 +0000 Subject: [PATCH] Fix bug in request handling when incoming requests are attached to an existing response and the response is generated by directly accessing the res.servletResponse HttpServletResponse instance. --- src/helma/framework/ResponseTrans.java | 18 ++++++++++------ src/helma/framework/core/Application.java | 10 +++++++-- src/helma/servlet/AbstractServletClient.java | 22 ++++++++++---------- 3 files changed, 31 insertions(+), 19 deletions(-) diff --git a/src/helma/framework/ResponseTrans.java b/src/helma/framework/ResponseTrans.java index 8e8a322a..8baeb479 100644 --- a/src/helma/framework/ResponseTrans.java +++ b/src/helma/framework/ResponseTrans.java @@ -493,11 +493,11 @@ public final class ResponseTrans extends Writer implements Serializable { /** * Allow to directly set the byte array for the response. Calling this more than once will - * overwrite the previous output. We take a generic object as parameter to be able to - * generate a better error message, but it must be byte[]. + * overwrite the previous output. + * @param bytes an arbitrary byte array */ - public void writeBinary(byte[] what) { - response = what; + public void writeBinary(byte[] bytes) { + response = bytes; } /** @@ -649,6 +649,11 @@ public final class ResponseTrans extends Writer implements Serializable { // there's no point in closing the response buffer HttpServletResponse res = reqtrans.getServletResponse(); if (res != null && res.isCommitted()) { + // response was committed using HttpServletResponse directly. We need + // set response to null and notify waiters in order to let attached + // requests know they can't reuse this response. + response = null; + notifyAll(); return; } @@ -664,7 +669,8 @@ public final class ResponseTrans extends Writer implements Serializable { boolean encodingError = false; - // only close if the response hasn't been closed yet + // only close if the response hasn't been closed yet, and if no + // response was generated using writeBinary(). if (response == null) { // if debug buffer exists, append it to main buffer if (contentType != null && @@ -747,7 +753,7 @@ public final class ResponseTrans extends Writer implements Serializable { * @return the response body */ public byte[] getContent() { - return (response == null) ? new byte[0] : response; + return response; } /** diff --git a/src/helma/framework/core/Application.java b/src/helma/framework/core/Application.java index c214d050..d02b3da4 100644 --- a/src/helma/framework/core/Application.java +++ b/src/helma/framework/core/Application.java @@ -720,6 +720,14 @@ public final class Application implements Runnable { if (ev != null) { res = ev.attachHttpRequest(req); + if (res != null) { + // we can only use the existing response object if the response + // wasn't written to the HttpServletResponse directly. + res.waitForClose(); + if (res.getContent() == null) { + res = null; + } + } } if (res == null) { @@ -752,8 +760,6 @@ public final class Application implements Runnable { } catch (UnsupportedEncodingException uee) { logError("Unsupported response encoding", uee); } - } else { - res.waitForClose(); } } diff --git a/src/helma/servlet/AbstractServletClient.java b/src/helma/servlet/AbstractServletClient.java index 8624278f..0a349843 100644 --- a/src/helma/servlet/AbstractServletClient.java +++ b/src/helma/servlet/AbstractServletClient.java @@ -345,17 +345,17 @@ public abstract class AbstractServletClient extends HttpServlet { res.setContentLength(hopres.getContentLength()); res.setContentType(hopres.getContentType()); - if ("HEAD".equalsIgnoreCase(req.getMethod())) { - return; - } - - try { - OutputStream out = res.getOutputStream(); - - out.write(hopres.getContent()); - out.flush(); - } catch (Exception iox) { - log("Exception in writeResponse: " + iox); + if (!"HEAD".equalsIgnoreCase(req.getMethod())) { + byte[] content = hopres.getContent(); + if (content != null) { + try { + OutputStream out = res.getOutputStream(); + out.write(content); + out.flush(); + } catch (Exception iox) { + log("Exception in writeResponse: " + iox); + } + } } } }