[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