diff --git a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/http/SimpleHTTPClient.java b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/http/SimpleHTTPClient.java index ad3f5c7d5..52ce02bd6 100644 --- a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/http/SimpleHTTPClient.java +++ b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/http/SimpleHTTPClient.java @@ -91,16 +91,18 @@ public class SimpleHTTPClient { c.setInstanceFollowRedirects(false); switch (c.getResponseCode()) { - case HttpURLConnection.HTTP_MOVED_PERM: - case HttpURLConnection.HTTP_MOVED_TEMP: - String location = c.getHeaderField("Location"); - location = URLDecoder.decode(location, "UTF-8"); - URL base = new URL(url); - URL next = new URL(base, location); // Deal with relative URLs - url = next.toExternalForm(); - continue; - default: - done = true; + case HttpURLConnection.HTTP_MOVED_PERM: + case HttpURLConnection.HTTP_MOVED_TEMP: + case 307: + case 308: // Same as HTTP_MOVED_PERM, but does not allow changing the request method from POST to GET + String location = c.getHeaderField("Location"); + location = URLDecoder.decode(location, "UTF-8"); + URL base = new URL(url); + URL next = new URL(base, location); // Deal with relative URLs + url = next.toExternalForm(); + continue; + default: + done = true; } } diff --git a/org.hl7.fhir.utilities/src/test/java/org/hl7/fhir/utilities/SimpleHTTPClientTest.java b/org.hl7.fhir.utilities/src/test/java/org/hl7/fhir/utilities/SimpleHTTPClientTest.java index 866894056..3973cdd94 100644 --- a/org.hl7.fhir.utilities/src/test/java/org/hl7/fhir/utilities/SimpleHTTPClientTest.java +++ b/org.hl7.fhir.utilities/src/test/java/org/hl7/fhir/utilities/SimpleHTTPClientTest.java @@ -1,24 +1,111 @@ package org.hl7.fhir.utilities; -import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.assertj.core.api.Assertions.assertThat; import java.io.IOException; +import java.util.stream.Stream; +import okhttp3.HttpUrl; +import okhttp3.mockwebserver.MockResponse; +import okhttp3.mockwebserver.MockWebServer; +import okhttp3.mockwebserver.RecordedRequest; import org.hl7.fhir.utilities.http.HTTPResult; import org.hl7.fhir.utilities.http.SimpleHTTPClient; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; public class SimpleHTTPClientTest { + + private MockWebServer server; + + @BeforeEach + void setup() { + setupMockServer(); + } + + void setupMockServer() { + server = new MockWebServer(); + } + @Test - public void testSimpleHTTPClient() throws IOException { + public void testGetApplicationJson() throws IOException, InterruptedException { + + HttpUrl serverUrl = server.url("fhir/us/core/package-list.json?nocache=1724353440974"); + + server.enqueue( + new MockResponse() + .setBody("Monkeys").setResponseCode(200) + ); SimpleHTTPClient http = new SimpleHTTPClient(); - String url = "https://hl7.org/fhir/us/core/package-list.json?nocache=" + System.currentTimeMillis(); - HTTPResult res = http.get(url, "application/json"); + HTTPResult res = http.get(serverUrl.url().toString(), "application/json"); + + assertThat(res.getCode()).isEqualTo(200); + + RecordedRequest packageRequest = server.takeRequest(); + + assert packageRequest.getRequestUrl() != null; + assertThat(packageRequest.getRequestUrl().toString()).isEqualTo(serverUrl.url().toString()); + assertThat(packageRequest.getMethod()).isEqualTo("GET"); + assertThat(packageRequest.getHeader("Accept")).isEqualTo("application/json"); -// System.out.println(res.getCode()); -// System.out.println(new String(res.getContent(), StandardCharsets.UTF_8)); - assertTrue(res.getCode() != 400); } + + public static Stream getRedirectArgs() { + return Stream.of( + Arguments.of(301, new String[]{"url1", "url2"}), + Arguments.of(301, new String[]{"url1", "url2", "url3"}), + Arguments.of(301, new String[]{"url1", "url2", "url3", "url4"}), + Arguments.of(302, new String[]{"url1", "url2"}), + Arguments.of(302, new String[]{"url1", "url2", "url3"}), + Arguments.of(302, new String[]{"url1", "url2", "url3", "url4"}), + Arguments.of(307, new String[]{"url1", "url2"}), + Arguments.of(307, new String[]{"url1", "url2", "url3"}), + Arguments.of(307, new String[]{"url1", "url2", "url3", "url4"}), + Arguments.of(308, new String[]{"url1", "url2"}), + Arguments.of(308, new String[]{"url1", "url2", "url3"}), + Arguments.of(308, new String[]{"url1", "url2", "url3", "url4"}) + ); + } + + @ParameterizedTest + @MethodSource("getRedirectArgs") + public void testRedirectsGet(int code, String[] urlArgs) throws IOException, InterruptedException { + + HttpUrl[] urls = new HttpUrl[urlArgs.length]; + for (int i = 0; i < urlArgs.length; i++) { + urls[i] = server.url(urlArgs[i]); + if (i > 0) { + server.enqueue( + new MockResponse() + .setResponseCode(code) + .setBody("Pumas") + .addHeader("Location", urls[i].url().toString())); + } + } + server.enqueue( + new MockResponse() + .setBody("Monkeys").setResponseCode(200) + ); + HttpUrl[] url = urls; + + SimpleHTTPClient http = new SimpleHTTPClient(); + + HTTPResult res = http.get(url[0].url().toString(), "application/json"); + + assertThat(res.getCode()).isEqualTo(200); + assertThat(res.getContentAsString()).isEqualTo("Monkeys"); + assertThat(server.getRequestCount()).isEqualTo(urlArgs.length); + + for (int i = 0; i < urlArgs.length; i++) { + RecordedRequest packageRequest = server.takeRequest(); + assertThat(packageRequest.getMethod()).isEqualTo("GET"); + assertThat(packageRequest.getHeader("Accept")).isEqualTo("application/json"); + } + } + } \ No newline at end of file