Skip to content

Commit cfeae55

Browse files
committed
Enforce verbatim response fetching in HttpWaitStrategy (#7326)
- Fix line ending truncation during response fetching - Fix unintended newline appending in the nc test container command Signed-off-by: Ivan Kropotin <102463202+ivankrn@users.noreply.github.com>
1 parent 2ac3c97 commit cfeae55

2 files changed

Lines changed: 42 additions & 14 deletions

File tree

core/src/main/java/org/testcontainers/containers/wait/strategy/HttpWaitStrategy.java

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,18 @@
33
import com.google.common.base.Strings;
44
import com.google.common.io.BaseEncoding;
55
import lombok.extern.slf4j.Slf4j;
6+
import org.apache.commons.io.IOUtils;
67
import org.rnorth.ducttape.TimeoutException;
78
import org.testcontainers.containers.ContainerLaunchException;
89

9-
import java.io.BufferedReader;
1010
import java.io.IOException;
11-
import java.io.InputStreamReader;
11+
import java.io.InputStream;
1212
import java.net.HttpURLConnection;
1313
import java.net.MalformedURLException;
1414
import java.net.Socket;
1515
import java.net.URI;
1616
import java.net.URL;
17+
import java.nio.charset.StandardCharsets;
1718
import java.security.KeyManagementException;
1819
import java.security.NoSuchAlgorithmException;
1920
import java.security.SecureRandom;
@@ -406,18 +407,10 @@ private String buildAuthString(String username, String password) {
406407
}
407408

408409
private String getResponseBody(HttpURLConnection connection) throws IOException {
409-
BufferedReader reader;
410-
if (200 <= connection.getResponseCode() && connection.getResponseCode() <= 299) {
411-
reader = new BufferedReader(new InputStreamReader((connection.getInputStream())));
412-
} else {
413-
reader = new BufferedReader(new InputStreamReader((connection.getErrorStream())));
414-
}
410+
boolean isSuccess = 200 <= connection.getResponseCode() && connection.getResponseCode() <= 299;
415411

416-
StringBuilder builder = new StringBuilder();
417-
String line;
418-
while ((line = reader.readLine()) != null) {
419-
builder.append(line);
412+
try (InputStream stream = isSuccess ? connection.getInputStream() : connection.getErrorStream()) {
413+
return IOUtils.toString(stream, StandardCharsets.UTF_8);
420414
}
421-
return builder.toString();
422415
}
423416
}

core/src/test/java/org/testcontainers/junit/wait/strategy/HttpWaitStrategyTest.java

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
import org.assertj.core.api.Assertions;
44
import org.jetbrains.annotations.NotNull;
55
import org.junit.jupiter.api.Test;
6+
import org.junit.jupiter.params.ParameterizedTest;
7+
import org.junit.jupiter.params.provider.MethodSource;
68
import org.rnorth.ducttape.RetryCountExceededException;
79
import org.testcontainers.containers.GenericContainer;
810
import org.testcontainers.containers.wait.strategy.HttpWaitStrategy;
@@ -12,6 +14,7 @@
1214
import java.util.HashMap;
1315
import java.util.concurrent.atomic.AtomicBoolean;
1416
import java.util.function.Predicate;
17+
import java.util.stream.Stream;
1518

1619
import static org.assertj.core.api.Assertions.assertThat;
1720

@@ -237,6 +240,38 @@ void testWaitUntilReadyWithTimeoutCausedBySslHandshakeError() {
237240
}
238241
}
239242

243+
static Stream<String> provideResponseBodies() {
244+
return Stream.of(
245+
// A multiline block
246+
"""
247+
A first line,
248+
A second line,
249+
And a third one.
250+
""",
251+
// A single line without any linebreaks
252+
"A single line without any linebreaks",
253+
// Edge cases for leading, trailing and enclosed newlines
254+
"\n\n\nA sample string with leading newlines",
255+
"A sample string with trailing newlines\n\n\n",
256+
"\n\n\nA sample string with both leading and trailing newlines\n\n\n",
257+
// Special symbols
258+
"A sample string with special symbols \uD83D\uDC19 \uD83D\uDC41️"
259+
);
260+
}
261+
262+
@ParameterizedTest
263+
@MethodSource("provideResponseBodies")
264+
void shouldPreserveResponseBody(String expectedResponseBody) {
265+
try (
266+
GenericContainer container = startContainerWithCommand(
267+
createShellCommand("200 OK", expectedResponseBody),
268+
createHttpWaitStrategy(ready).forResponsePredicate(response -> response.equals(expectedResponseBody))
269+
)
270+
) {
271+
waitUntilReadyAndSucceed(container);
272+
}
273+
}
274+
240275
/**
241276
* @param ready the AtomicBoolean on which to indicate success
242277
* @return the WaitStrategy under test
@@ -279,7 +314,7 @@ private String createShellCommand(String header, String responseBody, int port)
279314
length +
280315
NEWLINE +
281316
"\";" +
282-
" echo \"" +
317+
" echo -n \"" +
283318
responseBody +
284319
"\";} | nc -lp " +
285320
port +

0 commit comments

Comments
 (0)