Skip to content

Commit a5397b2

Browse files
committed
Request parsed using UTF-8 charset + Bug Proxy fails when the non-CONNECT HTTP response is chunked ecovaci/winfoom#6 solved
1 parent 47245fd commit a5397b2

File tree

3 files changed

+45
-12
lines changed

3 files changed

+45
-12
lines changed

src/main/java/org/kpax/winfoom/proxy/AsynchronousSocketChannelWrapper.java

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
import org.apache.commons.lang3.Validate;
1717
import org.apache.http.HttpVersion;
1818
import org.apache.http.ProtocolVersion;
19-
import org.kpax.winfoom.util.CrlfFormat;
19+
import org.kpax.winfoom.util.ObjectFormat;
2020
import org.kpax.winfoom.util.HttpUtils;
2121
import org.slf4j.Logger;
2222
import org.slf4j.LoggerFactory;
@@ -28,7 +28,6 @@
2828
import java.nio.ByteBuffer;
2929
import java.nio.channels.AsynchronousSocketChannel;
3030
import java.util.concurrent.ExecutionException;
31-
import java.util.concurrent.TimeUnit;
3231

3332
/**
3433
* A helper class that wraps an {@link AsynchronousSocketChannel}.
@@ -65,7 +64,7 @@ OutputStream getOutputStream() {
6564
}
6665

6766
void write(Object obj) throws IOException {
68-
outputStream.write(CrlfFormat.format(obj));
67+
outputStream.write(ObjectFormat.toCrlf(obj, ObjectFormat.UTF_8));
6968
}
7069

7170
void writeln(Object obj) throws IOException {
@@ -74,7 +73,7 @@ void writeln(Object obj) throws IOException {
7473
}
7574

7675
void writeln() throws IOException {
77-
outputStream.write(CrlfFormat.CRLF.getBytes());
76+
outputStream.write(ObjectFormat.CRLF.getBytes());
7877
}
7978

8079
void writelnError(int statusCode, Exception e) {

src/main/java/org/kpax/winfoom/proxy/SocketHandler.java

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,12 @@
1212

1313
package org.kpax.winfoom.proxy;
1414

15+
import org.apache.commons.lang3.StringUtils;
1516
import org.apache.commons.lang3.tuple.Pair;
1617
import org.apache.http.*;
1718
import org.apache.http.client.ClientProtocolException;
1819
import org.apache.http.client.methods.CloseableHttpResponse;
20+
import org.apache.http.config.MessageConstraints;
1921
import org.apache.http.impl.client.CloseableHttpClient;
2022
import org.apache.http.impl.client.HttpClientBuilder;
2123
import org.apache.http.impl.execchain.TunnelRefusedException;
@@ -28,6 +30,7 @@
2830
import org.kpax.winfoom.config.UserConfig;
2931
import org.kpax.winfoom.util.HttpUtils;
3032
import org.kpax.winfoom.util.LocalIOUtils;
33+
import org.kpax.winfoom.util.ObjectFormat;
3134
import org.slf4j.Logger;
3235
import org.slf4j.LoggerFactory;
3336
import org.springframework.beans.factory.annotation.Autowired;
@@ -103,7 +106,11 @@ void handleRequest() {
103106
try {
104107
// Prepare request parsing (this is the client's request)
105108
SessionInputBufferImpl inputBuffer = new SessionInputBufferImpl(
106-
new HttpTransportMetricsImpl(), LocalIOUtils.DEFAULT_BUFFER_SIZE);
109+
new HttpTransportMetricsImpl(),
110+
LocalIOUtils.DEFAULT_BUFFER_SIZE,
111+
LocalIOUtils.DEFAULT_BUFFER_SIZE,
112+
MessageConstraints.DEFAULT,
113+
ObjectFormat.UTF_8.newDecoder());
107114
inputBuffer.bind(localSocketChannel.getInputStream());
108115

109116
// Parse the request (all but the message body )
@@ -306,8 +313,22 @@ private void handleNonConnectResponse(final CloseableHttpResponse response) {
306313
localSocketChannel.write(response.getStatusLine());
307314

308315
for (Header header : response.getAllHeaders()) {
309-
logger.debug("Write response header: {}", header);
310-
localSocketChannel.write(header);
316+
if (HttpHeaders.TRANSFER_ENCODING.equals(header.getName())) {
317+
// Strip 'chunked' from Transfer-Encoding header's value
318+
// since the response is not chunked
319+
String nonChunkedTransferEncoding = HttpUtils.stripChunked(header.getValue());
320+
if (StringUtils.isNotEmpty(nonChunkedTransferEncoding)) {
321+
localSocketChannel.write(
322+
HttpUtils.createHttpHeader(HttpHeaders.TRANSFER_ENCODING,
323+
nonChunkedTransferEncoding));
324+
logger.debug("Add chunk-striped header response");
325+
} else {
326+
logger.debug("Remove transfer encoding chunked header response");
327+
}
328+
} else {
329+
logger.debug("Write response header: {}", header);
330+
localSocketChannel.write(header);
331+
}
311332
}
312333

313334
// Empty line marking the end

src/main/java/org/kpax/winfoom/util/CrlfFormat.java renamed to src/main/java/org/kpax/winfoom/util/ObjectFormat.java

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,25 +14,38 @@
1414

1515
import org.apache.commons.lang3.Validate;
1616

17+
import java.nio.charset.Charset;
18+
1719
/**
1820
* @author Eugen Covaci
1921
*/
20-
public final class CrlfFormat {
22+
public final class ObjectFormat {
2123

2224
public static final String CRLF = "\r\n";
2325

24-
private CrlfFormat() {
26+
public static final Charset UTF_8 = Charset.forName("UTF-8");
27+
28+
private ObjectFormat() {
2529
}
2630

2731
/**
28-
* Calls the <code>input.toString()</code> and appends CRLF.
32+
* @see #toCrlf(Object, Charset)
2933
*
34+
*/
35+
public static byte[] toCrlf(Object input) {
36+
Validate.notNull(input, "input cannot be null");
37+
return (input + CRLF).getBytes();
38+
}
39+
40+
/**
41+
* Calls the <code>input.toString()</code> and appends CRLF.
3042
* @param input The object to be formatted (not null).
43+
* @param charset The charset to be used (not null).
3144
* @return The resulted string as bytes.
3245
*/
33-
public static byte[] format(Object input) {
46+
public static byte[] toCrlf(Object input, Charset charset) {
3447
Validate.notNull(input, "input cannot be null");
35-
return (input + CRLF).getBytes();
48+
return (input + CRLF).getBytes(charset);
3649
}
3750

3851
}

0 commit comments

Comments
 (0)