Skip to content

Commit 25f77b2

Browse files
Merge pull request #55 from SAP/fix/InputReader
Fix Request Content-Length Calculation when using Reader
2 parents 1e3719f + a46e920 commit 25f77b2

File tree

4 files changed

+135
-21
lines changed

4 files changed

+135
-21
lines changed

cf-java-logging-support-servlet/src/main/java/com/sap/hcp/cf/logging/servlet/filter/ContentLengthTrackingRequestWrapper.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ public ServletInputStream getInputStream() throws IOException {
3535
@Override
3636
public BufferedReader getReader() throws IOException {
3737
wrappedReader = new WrappedInputReader(super.getReader());
38-
return wrappedReader;
38+
return new BufferedReader(wrappedReader);
3939
}
4040

4141
@Override

cf-java-logging-support-servlet/src/main/java/com/sap/hcp/cf/logging/servlet/filter/WrappedInputReader.java

Lines changed: 37 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
package com.sap.hcp.cf.logging.servlet.filter;
22

3-
import java.io.BufferedReader;
3+
import java.io.FilterReader;
44
import java.io.IOException;
5+
import java.io.Reader;
56

6-
public class WrappedInputReader extends BufferedReader {
7+
public class WrappedInputReader extends FilterReader {
78

8-
private final BufferedReader wrappedReader;
99
private int contentLength = -1;
10+
private int markContentLength = -1;
1011

11-
protected WrappedInputReader(BufferedReader in) {
12-
super(in, 1); // unused
13-
wrappedReader = in;
12+
protected WrappedInputReader(Reader in) {
13+
super(in);
1414
}
1515

1616
public int getContentLength() {
@@ -19,7 +19,7 @@ public int getContentLength() {
1919

2020
@Override
2121
public int read() throws IOException {
22-
int c = wrappedReader.read();
22+
int c = in.read();
2323
if (c != -1) {
2424
incrContentLength(1);
2525
}
@@ -28,21 +28,42 @@ public int read() throws IOException {
2828

2929
@Override
3030
public int read(char[] cbuf, int off, int len) throws IOException {
31-
int c = wrappedReader.read(cbuf, off, len);
31+
int c = in.read(cbuf, off, len);
3232
if (c != -1) {
3333
incrContentLength(c);
3434
}
3535
return c;
3636
}
3737

38-
@Override
39-
public String readLine() throws IOException {
40-
String s = wrappedReader.readLine();
41-
if (s != null) {
42-
incrContentLength(s.length());
43-
}
44-
return s;
45-
}
38+
@Override
39+
public long skip(long n) throws IOException {
40+
long skipped = in.skip(n);
41+
incrContentLength(toIntExact(skipped));
42+
return skipped;
43+
}
44+
45+
private static int toIntExact(long value) {
46+
if ((int) value != value) {
47+
throw new ArithmeticException("integer overflow");
48+
}
49+
return (int) value;
50+
}
51+
52+
@Override
53+
public void mark(int readAheadLimit) throws IOException {
54+
super.mark(readAheadLimit);
55+
synchronized (lock) {
56+
this.markContentLength = contentLength;
57+
}
58+
}
59+
60+
@Override
61+
public void reset() throws IOException {
62+
super.reset();
63+
synchronized (lock) {
64+
this.contentLength = markContentLength;
65+
}
66+
}
4667

4768
private void incrContentLength(int i) {
4869
if (contentLength == -1) {

cf-java-logging-support-servlet/src/test/java/com/sap/hcp/cf/logging/servlet/filter/RequestLoggingFilterTest.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import java.io.BufferedReader;
1313
import java.io.IOException;
1414
import java.io.PrintWriter;
15+
import java.io.StringReader;
1516
import java.util.HashMap;
1617
import java.util.Map;
1718

@@ -118,10 +119,9 @@ public void doFilter(ServletRequest request, ServletResponse response)
118119

119120
@Test
120121
public void testReader() throws IOException, ServletException {
121-
BufferedReader mockReader = mock(BufferedReader.class);
122+
BufferedReader reader = new BufferedReader(new StringReader("TEST"));
122123

123-
when(mockReq.getReader()).thenReturn(mockReader);
124-
when(mockReader.read()).thenReturn(1);
124+
when(mockReq.getReader()).thenReturn(reader);
125125
FilterChain mockFilterChain = new FilterChain() {
126126
@Override
127127
public void doFilter(ServletRequest request, ServletResponse response)
@@ -136,7 +136,7 @@ public void doFilter(ServletRequest request, ServletResponse response)
136136
assertThat(getField(Fields.REMOTE_HOST), is(Defaults.UNKNOWN));
137137
assertThat(getField(Fields.COMPONENT_ID), is(Defaults.UNKNOWN));
138138
assertThat(getField(Fields.CONTAINER_ID), is(Defaults.UNKNOWN));
139-
assertThat(getField(Fields.REQUEST_SIZE_B), is("1"));
139+
assertThat(getField(Fields.REQUEST_SIZE_B), is("4"));
140140
assertThat(getField(Fields.TENANT_ID), is(Defaults.UNKNOWN));
141141
}
142142

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
package com.sap.hcp.cf.logging.servlet.filter;
2+
3+
import static org.hamcrest.Matchers.equalTo;
4+
import static org.hamcrest.Matchers.is;
5+
import static org.junit.Assert.assertThat;
6+
7+
import java.io.BufferedReader;
8+
import java.io.IOException;
9+
import java.io.StringReader;
10+
11+
import org.junit.Test;
12+
13+
public class WrappedInputReaderTest {
14+
15+
private static final String MESSAGE = "ABCDEFGH";
16+
17+
private static WrappedInputReader wrap(String text) {
18+
return new WrappedInputReader(new BufferedReader(new StringReader(text)));
19+
}
20+
21+
@Test
22+
public void unreadInputGivesMinusOne() throws Exception {
23+
WrappedInputReader reader = wrap(MESSAGE);
24+
25+
assertThat(reader.getContentLength(), is(equalTo(-1)));
26+
}
27+
28+
@Test
29+
public void readSingleCharacter() throws Exception {
30+
WrappedInputReader reader = wrap(MESSAGE);
31+
32+
int read = reader.read();
33+
34+
assertThat((char) read, is(equalTo('A')));
35+
assertThat(reader.getContentLength(), is(equalTo(1)));
36+
}
37+
38+
@Test
39+
public void readCharacterArray() throws Exception {
40+
WrappedInputReader reader = wrap(MESSAGE);
41+
char[] cbuf = new char[3];
42+
43+
reader.read(cbuf);
44+
45+
assertThat(new String(cbuf), is(equalTo("ABC")));
46+
assertThat(reader.getContentLength(), is(equalTo(3)));
47+
}
48+
49+
@Test
50+
public void readCharacterArrayWithOffset() throws Exception {
51+
WrappedInputReader reader = wrap(MESSAGE);
52+
53+
char[] cbuf = new char[5];
54+
reader.read(cbuf, 1, 4);
55+
56+
assertThat(cbuf, is(equalTo(new char[] { 0, 'A', 'B', 'C', 'D' })));
57+
assertThat(reader.getContentLength(), is(equalTo(4)));
58+
}
59+
60+
61+
@Test
62+
public void skipCharacters() throws Exception {
63+
WrappedInputReader reader = wrap(MESSAGE);
64+
65+
long skipped = reader.skip(3);
66+
67+
assertThat(reader.getContentLength(), is(equalTo((int) skipped)));
68+
}
69+
70+
@Test
71+
public void markAndReset() throws Exception {
72+
WrappedInputReader reader = wrap(MESSAGE);
73+
74+
reader.mark(1);
75+
int blind = reader.read();
76+
reader.reset();
77+
String text = consume(reader);
78+
79+
assertThat((char) blind, is(equalTo('A')));
80+
assertThat(text, is(equalTo(MESSAGE)));
81+
assertThat(reader.getContentLength(), is(equalTo(MESSAGE.length())));
82+
}
83+
84+
private String consume(WrappedInputReader reader) throws IOException {
85+
StringBuffer buffer = new StringBuffer();
86+
int current;
87+
while ((current = reader.read()) != -1) {
88+
buffer.append((char) current);
89+
}
90+
return buffer.toString();
91+
}
92+
93+
}

0 commit comments

Comments
 (0)