|
3 | 3 | import static org.junit.Assert.assertNull; |
4 | 4 | import static org.junit.jupiter.api.Assertions.assertEquals; |
5 | 5 | import static org.junit.jupiter.api.Assertions.assertNotNull; |
| 6 | +import static org.junit.jupiter.api.Assertions.assertSame; |
6 | 7 | import static org.mockito.Mockito.*; |
7 | 8 |
|
8 | 9 | import com.microsoft.kiota.http.KiotaClientFactory; |
|
14 | 15 | import okhttp3.mockwebserver.RecordedRequest; |
15 | 16 |
|
16 | 17 | import org.junit.jupiter.api.Test; |
| 18 | +import org.junit.jupiter.params.ParameterizedTest; |
| 19 | +import org.junit.jupiter.params.provider.ValueSource; |
17 | 20 |
|
18 | 21 | import java.net.*; |
19 | 22 | import java.util.Collections; |
20 | 23 |
|
21 | 24 | @SuppressWarnings("resource") |
22 | 25 | public class RedirectHandlerTests { |
| 26 | + private static final MediaType REQUEST_MEDIA_TYPE = |
| 27 | + MediaType.parse("application/json; charset=utf-8"); |
| 28 | + private static final String REQUEST_BODY = "{\"value\":\"test\"}"; |
| 29 | + |
| 30 | + @ParameterizedTest |
| 31 | + @ValueSource(ints = {301, 302}) |
| 32 | + void postRedirectsToGetWithoutBodyOrBodyHeaders(int statusCode) throws Exception { |
| 33 | + Request original = createRequest("POST"); |
| 34 | + Response redirect = |
| 35 | + createRedirectResponse(original, statusCode, "http://other.example.com/redirected"); |
| 36 | + |
| 37 | + Request result = |
| 38 | + new RedirectHandler().getRedirect(original, redirect, new RedirectHandlerOption()); |
| 39 | + |
| 40 | + assertNotNull(result); |
| 41 | + assertEquals("GET", result.method()); |
| 42 | + assertNull(result.body()); |
| 43 | + assertBodyHeadersRemoved(result); |
| 44 | + assertCrossOriginHeadersRemoved(result); |
| 45 | + } |
| 46 | + |
| 47 | + @Test |
| 48 | + void seeOtherRedirectsNonGetOrHeadToGetWithoutBodyOrBodyHeaders() throws Exception { |
| 49 | + Request original = createRequest("PUT"); |
| 50 | + Response redirect = |
| 51 | + createRedirectResponse(original, 303, "http://other.example.com/redirected"); |
| 52 | + |
| 53 | + Request result = |
| 54 | + new RedirectHandler().getRedirect(original, redirect, new RedirectHandlerOption()); |
| 55 | + |
| 56 | + assertNotNull(result); |
| 57 | + assertEquals("GET", result.method()); |
| 58 | + assertNull(result.body()); |
| 59 | + assertBodyHeadersRemoved(result); |
| 60 | + assertCrossOriginHeadersRemoved(result); |
| 61 | + } |
| 62 | + |
| 63 | + @ParameterizedTest |
| 64 | + @ValueSource(strings = {"GET", "HEAD"}) |
| 65 | + void seeOtherPreservesGetAndHead(String method) throws Exception { |
| 66 | + Request original = createBodylessRequest(method); |
| 67 | + Response redirect = |
| 68 | + createRedirectResponse(original, 303, "http://other.example.com/redirected"); |
| 69 | + |
| 70 | + Request result = |
| 71 | + new RedirectHandler().getRedirect(original, redirect, new RedirectHandlerOption()); |
| 72 | + |
| 73 | + assertNotNull(result); |
| 74 | + assertEquals(method, result.method()); |
| 75 | + assertNull(result.body()); |
| 76 | + assertBodyHeadersPreserved(result); |
| 77 | + assertCrossOriginHeadersRemoved(result); |
| 78 | + } |
| 79 | + |
| 80 | + @ParameterizedTest |
| 81 | + @ValueSource(ints = {307, 308}) |
| 82 | + void redirectsPreserveMethodBodyAndBodyHeaders(int statusCode) throws Exception { |
| 83 | + Request original = createRequest("POST"); |
| 84 | + Response redirect = |
| 85 | + createRedirectResponse(original, statusCode, "http://other.example.com/redirected"); |
| 86 | + |
| 87 | + Request result = |
| 88 | + new RedirectHandler().getRedirect(original, redirect, new RedirectHandlerOption()); |
| 89 | + |
| 90 | + assertNotNull(result); |
| 91 | + assertEquals("POST", result.method()); |
| 92 | + assertSame(original.body(), result.body()); |
| 93 | + assertBodyHeadersPreserved(result); |
| 94 | + assertCrossOriginHeadersRemoved(result); |
| 95 | + } |
23 | 96 |
|
24 | 97 | @Test |
25 | 98 | void redirectsAreFollowedByDefault() throws Exception { |
@@ -384,4 +457,66 @@ void customScrubberRemovesCustomHeaders() throws Exception { |
384 | 457 | assertNull(result.header("X-Api-Key")); // stripped by custom scrubber |
385 | 458 | assertNotNull(result.header("X-Safe-Header")); // kept (not in scrub list) |
386 | 459 | } |
| 460 | + |
| 461 | + private static Request createRequest(String method) { |
| 462 | + RequestBody body = RequestBody.create(REQUEST_BODY, REQUEST_MEDIA_TYPE); |
| 463 | + return new Request.Builder() |
| 464 | + .url("http://trusted.example.com/api") |
| 465 | + .method(method, body) |
| 466 | + .headers(createRequestHeaders()) |
| 467 | + .build(); |
| 468 | + } |
| 469 | + |
| 470 | + private static Request createBodylessRequest(String method) { |
| 471 | + return new Request.Builder() |
| 472 | + .url("http://trusted.example.com/api") |
| 473 | + .method(method, null) |
| 474 | + .headers(createRequestHeaders()) |
| 475 | + .build(); |
| 476 | + } |
| 477 | + |
| 478 | + private static Headers createRequestHeaders() { |
| 479 | + return new Headers.Builder() |
| 480 | + .set("Content-Length", String.valueOf(REQUEST_BODY.length())) |
| 481 | + .set("Transfer-Encoding", "chunked") |
| 482 | + .set("Content-Type", REQUEST_MEDIA_TYPE.toString()) |
| 483 | + .set("Content-Encoding", "gzip") |
| 484 | + .set("Content-Language", "en-US") |
| 485 | + .set("Authorization", "Bearer secret") |
| 486 | + .set("Cookie", "session=SECRET") |
| 487 | + .build(); |
| 488 | + } |
| 489 | + |
| 490 | + private static Response createRedirectResponse( |
| 491 | + Request request, int statusCode, String location) { |
| 492 | + return new Response.Builder() |
| 493 | + .request(request) |
| 494 | + .protocol(Protocol.HTTP_1_1) |
| 495 | + .code(statusCode) |
| 496 | + .message("Redirect") |
| 497 | + .header("Location", location) |
| 498 | + .body(ResponseBody.create("", MediaType.parse("text/plain"))) |
| 499 | + .build(); |
| 500 | + } |
| 501 | + |
| 502 | + private static void assertBodyHeadersRemoved(Request request) { |
| 503 | + assertNull(request.header("Content-Length")); |
| 504 | + assertNull(request.header("Transfer-Encoding")); |
| 505 | + assertNull(request.header("Content-Type")); |
| 506 | + assertNull(request.header("Content-Encoding")); |
| 507 | + assertNull(request.header("Content-Language")); |
| 508 | + } |
| 509 | + |
| 510 | + private static void assertBodyHeadersPreserved(Request request) { |
| 511 | + assertEquals(String.valueOf(REQUEST_BODY.length()), request.header("Content-Length")); |
| 512 | + assertEquals("chunked", request.header("Transfer-Encoding")); |
| 513 | + assertEquals(REQUEST_MEDIA_TYPE.toString(), request.header("Content-Type")); |
| 514 | + assertEquals("gzip", request.header("Content-Encoding")); |
| 515 | + assertEquals("en-US", request.header("Content-Language")); |
| 516 | + } |
| 517 | + |
| 518 | + private static void assertCrossOriginHeadersRemoved(Request request) { |
| 519 | + assertNull(request.header("Authorization")); |
| 520 | + assertNull(request.header("Cookie")); |
| 521 | + } |
387 | 522 | } |
0 commit comments