|
72 | 72 | import java.nio.channels.Channel; |
73 | 73 | import java.nio.channels.FileChannel; |
74 | 74 | import java.util.ArrayDeque; |
| 75 | +import java.util.ArrayList; |
75 | 76 | import java.util.Deque; |
| 77 | +import java.util.List; |
76 | 78 | import java.util.Map; |
77 | 79 | import java.util.Set; |
78 | 80 | import java.util.TreeMap; |
@@ -1184,18 +1186,93 @@ public HttpServerExchange setRequestCookie(final Cookie cookie) { |
1184 | 1186 | } |
1185 | 1187 |
|
1186 | 1188 | public Cookie getRequestCookie(final String name) { |
| 1189 | + return getRequestCookie(name, null); |
| 1190 | + } |
| 1191 | + |
| 1192 | + public Cookie getRequestCookie(final String name, final String path) { |
1187 | 1193 | if (name == null) return null; |
| 1194 | + final List<Cookie> optionsToMatch = new ArrayList<>(); |
1188 | 1195 | for (Cookie cookie : requestCookies()) { |
1189 | 1196 | if (name.equals(cookie.getName())) { |
1190 | | - // TODO: QUESTION: Shouldn't we check instead of just name also |
1191 | | - // TODO requestPath (stored in this exchange request path) and |
1192 | | - // TODO: domain (stored in Host HTTP header). |
1193 | | - return cookie; |
| 1197 | + optionsToMatch.add(cookie); |
| 1198 | + } |
| 1199 | + } |
| 1200 | + return matchCookieDetails(optionsToMatch, path); |
| 1201 | + } |
| 1202 | + |
| 1203 | + /** |
| 1204 | + * Match path and domain of cookies to those present in request. This method will match cookies against exchange request path |
| 1205 | + * and once potential pool is identified it will try to find best match based either on supplied 'path' argument |
| 1206 | + * @param optionsToMatch |
| 1207 | + * @param path - prefix of request path that will be a base for match( or request path). May be <b>null</b>. |
| 1208 | + */ |
| 1209 | + private Cookie matchCookieDetails(final List<Cookie> optionsToMatch, String path) { |
| 1210 | + //NOTE: https://www.rfc-editor.org/rfc/rfc6265#section-5.1.4 |
| 1211 | + //NOTE: https://www.rfc-editor.org/rfc/rfc6265#section-5.1.3 |
| 1212 | + // NOTE: Its possible to receive request "/sub" with cookies "/" and "/sub" - |
| 1213 | + //we should return longest match if path is not directly specified |
| 1214 | + //NOTE: order in request is not guaranteed by UA |
| 1215 | + final String requestPath = this.getRequestPath(); |
| 1216 | + if(path == null) { |
| 1217 | + path = requestPath; |
| 1218 | + } else { |
| 1219 | + //path must be a prefix or match request |
| 1220 | + if(!requestPath.startsWith(path)) { |
| 1221 | + return null; |
| 1222 | + } |
| 1223 | + } |
| 1224 | + Cookie potentialReturn = null; |
| 1225 | + for (final Cookie c : optionsToMatch) { |
| 1226 | + if (cookiePathMatch(c, path) && cookieDomainMatch(c)) { |
| 1227 | + if(potentialReturn == null) { |
| 1228 | + potentialReturn = c; |
| 1229 | + } else { |
| 1230 | + // at this point length of path is a factor only |
| 1231 | + if (computeCookiePath(c).length() > computeCookiePath(potentialReturn).length()) { |
| 1232 | + potentialReturn = c; |
| 1233 | + } |
| 1234 | + } |
| 1235 | + |
| 1236 | + if(computeCookiePath(potentialReturn).equals(path)) { |
| 1237 | + //it wont get better |
| 1238 | + return potentialReturn; |
| 1239 | + } |
1194 | 1240 | } |
1195 | 1241 | } |
1196 | | - return null; |
| 1242 | + return potentialReturn; |
1197 | 1243 | } |
1198 | 1244 |
|
| 1245 | + private String computeCookiePath(final Cookie c) { |
| 1246 | + //NOTE: this is shady, seems like default is used if no value is present, though UAs should not send cookies to wrong url: |
| 1247 | + //5.2 https://www.ietf.org/rfc/rfc2109.txt |
| 1248 | + if (c.getPath() != null) { |
| 1249 | + return c.getPath(); |
| 1250 | + } else { |
| 1251 | + // NOTE: assume no Path == '/' |
| 1252 | + // NOTE: possibly compute as UA would |
| 1253 | + return "/"; |
| 1254 | + } |
| 1255 | + } |
| 1256 | + |
| 1257 | + private boolean cookiePathMatch(final Cookie c, final String requestPath) { |
| 1258 | + final String cookiePath = computeCookiePath(c); |
| 1259 | + if(requestPath == null) { |
| 1260 | + return false; |
| 1261 | + } |
| 1262 | + if( requestPath.equals(cookiePath)) { |
| 1263 | + return true; |
| 1264 | + } |
| 1265 | + |
| 1266 | + if(requestPath.startsWith(cookiePath) && (cookiePath.charAt(cookiePath.length()-1) == '/' || requestPath.charAt(cookiePath.length()) == '/')) { |
| 1267 | + return true; |
| 1268 | + } |
| 1269 | + return false; |
| 1270 | + } |
| 1271 | + |
| 1272 | + private boolean cookieDomainMatch(Cookie c) { |
| 1273 | + //TODO: https://issues.redhat.com/browse/UNDERTOW-2261 |
| 1274 | + return true; |
| 1275 | + } |
1199 | 1276 | /** |
1200 | 1277 | * Returns unmodifiable enumeration of request cookies. |
1201 | 1278 | * @return A read-only enumeration of request cookies |
|
0 commit comments