[jscover] 63/69: Persistent connection prevention fixed for POST requests. Additional unit tests. All tests now pass and coverage requirements are met.

Sylvestre Ledru sylvestre at moszumanska.debian.org
Fri Aug 22 05:54:09 UTC 2014


This is an automated email from the git hooks/post-receive script.

sylvestre pushed a commit to branch master
in repository jscover.

commit 039ad93258fb4b5304536ae5ce12bc6a052c3753
Author: Jake Cobb <jcobb at us.fujitsu.com>
Date:   Thu Aug 14 15:16:16 2014 -0700

    Persistent connection prevention fixed for POST requests.
    Additional unit tests.  All tests now pass and coverage requirements
    are met.
---
 src/main/java/jscover/server/ProxyService.java     | 68 ++++++++++++++--------
 src/test/java/jscover/server/ProxyServiceTest.java | 62 +++++++++++++++++---
 2 files changed, 98 insertions(+), 32 deletions(-)

diff --git a/src/main/java/jscover/server/ProxyService.java b/src/main/java/jscover/server/ProxyService.java
index a43f7a2..9cb7e83 100644
--- a/src/main/java/jscover/server/ProxyService.java
+++ b/src/main/java/jscover/server/ProxyService.java
@@ -352,6 +352,7 @@ import java.nio.charset.Charset;
 import java.util.List;
 import java.util.Map;
 import java.util.logging.Logger;
+import java.util.regex.Pattern;
 
 import static java.lang.String.format;
 import static java.util.logging.Level.FINE;
@@ -359,6 +360,7 @@ import static java.util.logging.Level.FINEST;
 import static java.util.logging.Level.SEVERE;
 
 public class ProxyService {
+    private static final Charset UTF8 = Charset.forName("UTF-8");
     private static final Logger logger = Logger.getLogger(ProxyService.class.getName());
     private IoUtils ioUtils = IoUtils.getInstance();
 
@@ -402,7 +404,7 @@ public class ProxyService {
             socket = new Socket(url.getHost(), port == -1 ? 80 : port);
             remoteInputStream = socket.getInputStream();
             remoteOutputStream = socket.getOutputStream();
-            ioUtils.copyNoClose(setHttp10(request.getInputStream()), remoteOutputStream, request.getPostIndex() + request.getContentLength());
+            sendMethodAndHeaders(request, request.getInputStream(), remoteOutputStream);
             ioUtils.copyNoClose(remoteInputStream, request.getOutputStream());
         } catch (IOException e) {
             e.printStackTrace();
@@ -412,26 +414,44 @@ public class ProxyService {
             ioUtils.closeQuietly(socket);
         }
     }
-
-    protected InputStream setHttp10(InputStream is) {
-        try {
-            logger.log(FINE, "Bytes available on stream {0}", is.available());
-            int bufSize = Math.min(is.available(), 2046);
-            PushbackInputStream pbis = new PushbackInputStream(is, bufSize);
-            byte headerBytes[] = new byte[bufSize];
-            int read = pbis.read(headerBytes);
-            int firstLineIndex = ioUtils.getNewLineIndex(headerBytes, Charset.defaultCharset());
-            pbis.unread(headerBytes, firstLineIndex, read - firstLineIndex);
-            String header = new String(headerBytes, 0, firstLineIndex);
-
-            logger.log(FINEST, "Header before {0}", header);
-            header = header.replaceFirst("HTTP/1.1", "HTTP/1.0");
-            logger.log(FINEST, "Header after {0}", header);
-            pbis.unread(header.getBytes());
-            return pbis;
-        } catch (IOException e) {
-            throw new RuntimeException(e);
-        }
+    
+    protected void sendMethodAndHeaders(HttpRequest request, InputStream is, OutputStream remoteOutputStream) throws IOException {
+        
+        // read ahead to see the method and headers
+        logger.log(FINE, "Bytes available on stream {0}", is.available());
+        int bufSize = Math.min(is.available(), HttpServer.HEADER_SIZE);
+        ByteArrayOutputStream baos = new ByteArrayOutputStream(bufSize);
+        PushbackInputStream pbis = new PushbackInputStream(is, bufSize);
+        byte headerBytes[] = new byte[bufSize];
+        int read = pbis.read(headerBytes);
+        int firstLineIndex = ioUtils.getNewLineIndex(headerBytes, UTF8);
+        int dataIndex = ioUtils.getDataIndex(headerBytes, UTF8);
+        
+        // back up to the start of data
+        pbis.unread(headerBytes, dataIndex, read - dataIndex);
+
+        // read the header, drop the remote host part and change protocol to HTTP/1.0
+        String header = new String(headerBytes, 0, firstLineIndex, UTF8);
+        logger.log(FINEST, "Header before {0}", header);
+        final URL url = request.getUrl();
+        header = header.replaceFirst(Pattern.quote(url.toExternalForm()), getRawURI(url));
+        header = header.replaceFirst("HTTP/1.1", "HTTP/1.0");
+        logger.log(FINEST, "Header after {0}", header);
+        
+        // write method and filtered headers to intermediate buffer
+        PrintWriter remotePrintWriter = new PrintWriter(new OutputStreamWriter(baos, UTF8));
+        remotePrintWriter.write(header);
+        remotePrintWriter.write("\r\n");
+        sendHeaders(request, remotePrintWriter);
+        byte[] methodAndHeaderBytes = baos.toByteArray();
+        
+        // push method and headers in front of response data
+        PushbackInputStream requestInputStream = new PushbackInputStream(pbis, methodAndHeaderBytes.length);
+        requestInputStream.unread(methodAndHeaderBytes);
+        
+        // now copy the whole thing
+        int toSend = methodAndHeaderBytes.length + request.getContentLength();
+        ioUtils.copyNoClose(requestInputStream, remoteOutputStream, toSend);
     }
 
     String getRawURI(URL url) {
@@ -441,7 +461,7 @@ public class ProxyService {
         }
         return uri;
     }
-
+    
     private void sendHeaders(HttpRequest request, PrintWriter remotePrintWriter) {
         Map<String, List<String>> clientHeaders = request.getHeaders();
         for (String header : clientHeaders.keySet()) {
@@ -449,10 +469,10 @@ public class ProxyService {
                 continue;
             List<String> values = clientHeaders.get(header);
             for (String value : values) {
-                remotePrintWriter.print(format("%s: %s\n", header, value));
+                remotePrintWriter.print(format("%s: %s\r\n", header, value));
             }
         }
-        remotePrintWriter.print("\n");
+        remotePrintWriter.print("\r\n");
         remotePrintWriter.flush();
     }
     
diff --git a/src/test/java/jscover/server/ProxyServiceTest.java b/src/test/java/jscover/server/ProxyServiceTest.java
index d86a2d3..3cb2f5a 100644
--- a/src/test/java/jscover/server/ProxyServiceTest.java
+++ b/src/test/java/jscover/server/ProxyServiceTest.java
@@ -343,6 +343,8 @@ Public License instead of this License.
  package jscover.server;
 
 import jscover.util.IoUtils;
+
+import org.hamcrest.Matchers;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -350,20 +352,24 @@ import org.mockito.Mock;
 import org.mockito.runners.MockitoJUnitRunner;
 
 import java.io.ByteArrayInputStream;
-import java.io.InputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
 import java.net.HttpURLConnection;
+import java.nio.charset.Charset;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
 import static org.hamcrest.MatcherAssert.assertThat;
-import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.startsWith;
 import static org.mockito.Mockito.*;
 
 
 @RunWith(MockitoJUnitRunner.class)
 public class ProxyServiceTest {
+    private static final Charset UTF8 = Charset.forName("UTF-8");
     private ProxyService proxyService = new ProxyService();
     private HttpRequest request = new HttpRequest("test.js", null, null, 0, null);
     @Mock private HttpURLConnection conn;
@@ -417,11 +423,51 @@ public class ProxyServiceTest {
     }
 
     @Test
-    public void shouldConvertToHTTP10() {
-        String requestString = "POST /someURL HTTP/1.1\r\nHeaders";
-
-        InputStream is = proxyService.setHttp10(new ByteArrayInputStream(requestString.getBytes()));
-
-        assertThat(ioUtils.toString(is), equalTo("POST /someURL HTTP/1.0\r\nHeaders"));
+    public void shouldConvertToHTTP10() throws Exception {
+        Map<String, List<String>> headers = new HashMap<String, List<String>>();
+        headers.put("Content-Length", Collections.singletonList("0"));
+        String url = "http://somehost/someURL";
+        String requestString = "POST " + url + " HTTP/1.1\r\nContent-Length: 0\r\n\r\n";
+        
+        String result = sendMethodAndHeaders(url, requestString, headers).toString("UTF-8");
+        assertThat(result, startsWith("POST /someURL HTTP/1.0"));
+    }
+    
+    @Test
+    public void shouldChangeURLToPath() throws Exception {
+        Map<String, List<String>> headers = new HashMap<String, List<String>>();
+        headers.put("Content-Length", Collections.singletonList("0"));
+        String url = "http://somehost/someURL";
+        String requestString = "POST " + url + " HTTP/1.1\r\nContent-Length: 0\r\n\r\n";
+        
+        String result = sendMethodAndHeaders(url, requestString, headers).toString("UTF-8");
+        assertThat(result, startsWith("POST /someURL"));
+    }
+    
+    @Test
+    public void shouldNotAddKeepAliveHeadersPost() throws Exception {
+        Map<String, List<String>> headers = new HashMap<String, List<String>>();
+        headers.put("Proxy-Connection", Collections.singletonList("keep-alive"));
+        headers.put("Connection", Collections.singletonList("keep-alive"));
+        headers.put("Content-Length", Collections.singletonList("0"));
+
+        String url = "http://somehost/someURL";
+        String requestString = "POST " + url + " HTTP/1.1\r\nProxy-Connection: keep-alive\r\nConnection: keep-alive\r\nContent-Length: 0\r\n\r\n";
+        String result = sendMethodAndHeaders(url, requestString, headers).toString("UTF-8");
+        
+        assertThat(result, Matchers.not(Matchers.containsString("Connection")));
+        assertThat(result, Matchers.not(Matchers.containsString("keep-alive")));
+    }
+    
+    private ByteArrayOutputStream sendMethodAndHeaders(String path, String requestString, Map<String, List<String>> headers) throws IOException {
+        if (headers == null )
+            headers = Collections.emptyMap();
+        
+        ByteArrayOutputStream out = new ByteArrayOutputStream();
+        ByteArrayInputStream in =  new ByteArrayInputStream(requestString.getBytes(UTF8));
+        HttpRequest request = new HttpRequest(path, new ByteArrayInputStream(requestString.getBytes(UTF8)), out, 0, headers);
+        
+        proxyService.sendMethodAndHeaders(request, in, out);
+        return out;
     }
 }

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-java/jscover.git



More information about the pkg-java-commits mailing list