Skip to content

Commit

Permalink
Only cap the input if content length header is given
Browse files Browse the repository at this point in the history
Currently RqLengthAware uses the InputStream#available to cap the input
if no Content-Length header is given, but the return value does not say
anything about the real content length, only how many bytes can be read
without blocking (what might be 0).

This now only returns a CapInputStream when a Content-Length is given in
the request and adds a testcase for the given case.
  • Loading branch information
Christoph Läubrich committed Aug 2, 2024
1 parent 20467cf commit 0e39128
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 9 deletions.
22 changes: 13 additions & 9 deletions src/main/java/org/takes/rq/RqLengthAware.java
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,9 @@
@EqualsAndHashCode(callSuper = true)
public final class RqLengthAware extends RqWrap {

/**
private static final String CONTENT_LENGTH = "Content-Length";

/**
* Ctor.
* @param req Original request
*/
Expand All @@ -68,14 +70,16 @@ public RqLengthAware(final Request req) {
*/
private static InputStream cap(final Request req) throws IOException {
final Iterator<String> hdr = new RqHeaders.Base(req)
.header("Content-Length").iterator();
InputStream body = req.body();
long length = (long) body.available();
if (hdr.hasNext()) {
length = Long.parseLong(hdr.next());
}
body = new CapInputStream(body, length);
return body;
.header(CONTENT_LENGTH).iterator();
if(hdr.hasNext()) {
String value = hdr.next();
try {
return new CapInputStream(req.body(), Long.parseLong(value));
} catch(NumberFormatException e) {
throw new IOException(String.format("Invalid %s header: %s", CONTENT_LENGTH, value));
}
}
return req.body();
}

}
31 changes: 31 additions & 0 deletions src/test/java/org/takes/rq/RqLengthAwareTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,12 @@
*/
package org.takes.rq;

import java.io.ByteArrayInputStream;
import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;

import org.hamcrest.MatcherAssert;
import org.hamcrest.Matchers;
import org.junit.jupiter.api.Test;
Expand Down Expand Up @@ -95,6 +98,34 @@ void readsByte() throws IOException {
Matchers.equalTo(data.length() - 1)
);
}

@Test
void noContentLength() throws IOException {
byte[] bytes = "test".getBytes();
final InputStream data = new FilterInputStream(new ByteArrayInputStream(bytes)) {
@Override
public int available() throws IOException {
//This simulates a stream where only one byte is available at once
return 1;
}
};
final InputStream stream = new RqLengthAware(
new RqFake(
Arrays.asList(
"GET /test1",
"Host: b.example.com"
//We have no content length header so RqLengthAware should simply do nothing
),
data
)
).body();
for(int i = 0; i < bytes.length; i++) {
MatcherAssert.assertThat(
stream.read(),
Matchers.equalTo(bytes[i] & 0xFF)
);
}
}

@Test
void readsByteArray() throws IOException {
Expand Down

0 comments on commit 0e39128

Please sign in to comment.