1515 */
1616package org .asynchttpclient .netty .handler .intercept ;
1717
18+ import io .netty .handler .codec .http .cookie .DefaultCookie ;
1819import jakarta .servlet .http .HttpServletRequest ;
1920import jakarta .servlet .http .HttpServletResponse ;
2021import org .asynchttpclient .AbstractBasicTest ;
2122import org .asynchttpclient .AsyncHttpClient ;
23+ import org .asynchttpclient .AsyncHttpClientConfig ;
2224import org .asynchttpclient .BoundRequestBuilder ;
2325import org .eclipse .jetty .server .Request ;
2426import 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