Skip to content

Commit dadc504

Browse files
committed
Address comments
1 parent 3b08641 commit dadc504

2 files changed

Lines changed: 66 additions & 10 deletions

File tree

‎client/src/main/java/org/asynchttpclient/netty/handler/intercept/Redirect30xInterceptor.java‎

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -186,9 +186,6 @@ public boolean exitAfterHandlingRedirect(Channel channel, NettyResponseFuture<?>
186186
if (keepBody) {
187187
ensureBodyReplayable(request, bodyRepresentation, future.isStreamConsumed());
188188
requestBuilder = request.toBuilder();
189-
// These include what the store held before this response, which would outrank what the
190-
// redirect just set; the store adds back below whatever matches the new URI.
191-
requestBuilder.resetCookies();
192189
if (!sameBase) {
193190
// An explicitly resolved address and virtual host belong to the previous target.
194191
requestBuilder.setAddress(null);
@@ -202,6 +199,14 @@ public boolean exitAfterHandlingRedirect(Channel channel, NettyResponseFuture<?>
202199
.setProxyServer(request.getProxyServer())
203200
.setRangeOffset(request.getRangeOffset());
204201
}
202+
// Without a cookie store every cookie on the request is the caller's, so a same-origin hop keeps
203+
// them. With one, they also hold what the store had before this response, which would outrank
204+
// what it just set, so the hop carries only the store's cookies for the new URI, added below.
205+
if (config.getCookieStore() == null && !stripAuth) {
206+
requestBuilder.setCookies(request.getCookies());
207+
} else {
208+
requestBuilder.resetCookies();
209+
}
205210

206211
requestBuilder.setMethod(switchToGet ? GET : originalMethod)
207212
.setFollowRedirect(true)

‎client/src/test/java/org/asynchttpclient/netty/handler/intercept/RedirectCookieRotationTest.java‎

Lines changed: 58 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,12 @@
1515
*/
1616
package org.asynchttpclient.netty.handler.intercept;
1717

18+
import io.netty.handler.codec.http.cookie.DefaultCookie;
1819
import jakarta.servlet.http.HttpServletRequest;
1920
import jakarta.servlet.http.HttpServletResponse;
2021
import org.asynchttpclient.AbstractBasicTest;
2122
import org.asynchttpclient.AsyncHttpClient;
23+
import org.asynchttpclient.AsyncHttpClientConfig;
2224
import org.asynchttpclient.BoundRequestBuilder;
2325
import org.eclipse.jetty.server.Request;
2426
import org.eclipse.jetty.server.handler.AbstractHandler;
@@ -65,9 +67,18 @@ public void handle(String target, Request baseRequest, HttpServletRequest reques
6567
case "/logout-303":
6668
redirect(response, HttpServletResponse.SC_SEE_OTHER, "SID=; Path=/; Max-Age=0", "/home");
6769
break;
70+
case "/logout-307":
71+
redirect(response, 307, "SID=; Path=/; Max-Age=0", "/home");
72+
break;
6873
case "/p/a":
6974
redirect(response, HttpServletResponse.SC_FOUND, null, "/q/b");
7075
break;
76+
case "/see-other":
77+
redirect(response, HttpServletResponse.SC_SEE_OTHER, null, "/home");
78+
break;
79+
case "/elsewhere":
80+
redirect(response, HttpServletResponse.SC_FOUND, null, "http://127.0.0.1:" + port1 + "/home");
81+
break;
7182
default:
7283
String cookie = request.getHeader("Cookie");
7384
if (cookie != null) {
@@ -80,16 +91,23 @@ public void handle(String target, Request baseRequest, HttpServletRequest reques
8091
}
8192

8293
@Test
83-
void aSessionRotatedByARedirectIsTheOneSent() throws Exception {
84-
assertEquals("SID=new", afterSeeding(client -> client.prepareGet(url("/login"))), "GET, 302");
85-
assertEquals("SID=new", afterSeeding(client -> client.preparePost(url("/login"))), "POST, 302 to GET");
86-
assertEquals("SID=new", afterSeeding(client -> client.preparePost(url("/login-307"))), "POST, 307");
94+
void aGetRedirectSendsTheSessionItRotated() throws Exception {
95+
assertEquals("SID=new", afterSeeding(client -> client.prepareGet(url("/login"))));
8796
}
8897

8998
@Test
90-
void aCookieARedirectDeletedStaysDeleted() throws Exception {
91-
assertNull(afterSeeding(client -> client.prepareGet(url("/logout"))), "GET, 302");
92-
assertNull(afterSeeding(client -> client.preparePost(url("/logout-303"))), "POST, 303");
99+
void a307SendsTheSessionItRotated() throws Exception {
100+
assertEquals("SID=new", afterSeeding(client -> client.preparePost(url("/login-307"))));
101+
}
102+
103+
@Test
104+
void aGetRedirectDoesNotResendACookieItDeleted() throws Exception {
105+
assertNull(afterSeeding(client -> client.prepareGet(url("/logout"))));
106+
}
107+
108+
@Test
109+
void a307DoesNotResendACookieItDeleted() throws Exception {
110+
assertNull(afterSeeding(client -> client.preparePost(url("/logout-307"))));
93111
}
94112

95113
@Test
@@ -98,13 +116,46 @@ void aPathScopedCookieDoesNotFollowARedirectOutOfItsPath() throws Exception {
98116
assertFalse(received != null && received.contains("P="), "sent to /q/b: " + received);
99117
}
100118

119+
// The next two already hold on main, where a redirect to GET is built from scratch; they keep it that way.
120+
121+
@Test
122+
void aPostRedirectedToGetSendsTheSessionItRotated() throws Exception {
123+
assertEquals("SID=new", afterSeeding(client -> client.preparePost(url("/login"))));
124+
}
125+
126+
@Test
127+
void a303DoesNotResendACookieItDeleted() throws Exception {
128+
assertNull(afterSeeding(client -> client.preparePost(url("/logout-303"))));
129+
}
130+
131+
// Without a cookie store every cookie on the request is the caller's own.
132+
133+
@Test
134+
void withoutAStoreTheCallersCookieFollowsASameOriginRedirect() throws Exception {
135+
assertEquals("X=1", withoutAStore(client -> client.prepareGet(url("/login"))), "GET, 302");
136+
assertEquals("X=1", withoutAStore(client -> client.preparePost(url("/see-other"))), "POST, 303");
137+
}
138+
139+
@Test
140+
void withoutAStoreTheCallersCookieStaysBehindOnACrossOriginRedirect() throws Exception {
141+
assertNull(withoutAStore(client -> client.prepareGet(url("/elsewhere"))));
142+
}
143+
101144
private String afterSeeding(Function<AsyncHttpClient, BoundRequestBuilder> request) throws Exception {
102145
try (AsyncHttpClient client = asyncHttpClient(config().setFollowRedirect(true))) {
103146
client.prepareGet(url("/seed")).execute().get(TIMEOUT, TimeUnit.SECONDS);
104147
return request.apply(client).execute().get(TIMEOUT, TimeUnit.SECONDS).getHeader(RECEIVED_COOKIE);
105148
}
106149
}
107150

151+
private String withoutAStore(Function<AsyncHttpClient, BoundRequestBuilder> request) throws Exception {
152+
AsyncHttpClientConfig noStore = config().setFollowRedirect(true).setCookieStore(null).build();
153+
try (AsyncHttpClient client = asyncHttpClient(noStore)) {
154+
return request.apply(client).addCookie(new DefaultCookie("X", "1"))
155+
.execute().get(TIMEOUT, TimeUnit.SECONDS).getHeader(RECEIVED_COOKIE);
156+
}
157+
}
158+
108159
private static void redirect(HttpServletResponse response, int status, String setCookie, String location) {
109160
if (setCookie != null) {
110161
response.addHeader("Set-Cookie", setCookie);

0 commit comments

Comments
 (0)