-
Notifications
You must be signed in to change notification settings - Fork 4k
ARROW-10428: [FlightRPC][Java] Add support for HTTP cookies #8554
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
lidavidm
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks straightforward. Just a comment about the implementation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note that the middleware is instantiated per call, so to have persistent cookie values across multiple calls, you actually want this map to be part of the Factory.
Also, FlightClient can handle concurrent calls, so this should be a ConcurrentHashMap.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch. I'll add an end-to-end test for persistence too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we actually expect to see this header, as it's deprecated?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't really. This isn't supported by any major browsers now: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie2 .
It's there for completeness, but given it's buggy in the JDK, let's remove Set-cookie2 handling.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed Set-Cookie2 support.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Calculate seems to imply that we are generating new cookies here but we are just joining existing cookie strings?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
Add a ClientMiddleware that can read HTTP Set-Cookie and Set-Cookie2 headers from server responses and transmit corresponding Cookie headers
- Remove COOKIE2_HEADER - Store cookies in the concurrent hashmap in the factory for persistance. - Added end to end test for cookie persistence
- Fixed test cookieStaysAfterMultipleRequestsEndToEnd. - Cleanup TestCookieHandling resources.
- Update TestCookieHandling to use the test Factory with the ability to intercept the returned ClientCookieMiddleware.
Address code review comments
|
Just to link things: #8572 is implementing support for arbitrary headers, perhaps we should think about if cookies should build on top of that support. |
I'm leaning towards keeping this as just middleware and not involving CallOptions. #8572 is for letting the client arbitrarily add headers at the time of a request, whereas cookie-headers aren't arbitrary and should be automatically sent. The checking of expiration should also be automatic. We could rework this patch to have a subclass of HeaderCallOption that lazily retrieves the cookie header from the cookie middleware during wrapStub, but I feel this is more difficult/error-prone for app-developers. |
Sounds good to me. |
| // The server can also update a cookie to have an Expiry in the past or negative age | ||
| // to signal that the client should stop using the cookie immediately. | ||
| final Consumer<String> handleSetCookieHeader = (headerValue) -> { | ||
| final List<HttpCookie> parsedCookies = HttpCookie.parse(headerValue); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we handle IllegalArgumentException here from HttpCookie.parse?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also instead of a lambda it may be clearer to define Factory#updateFromSetCookieHeader or something like that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
| cookieMiddleware.onHeadersReceived(headersToSend); | ||
|
|
||
| // Verify that the k cookie was discarded because the server told the client it is expired. | ||
| Assert.assertTrue(cookieMiddleware.getValidCookiesAsString().isEmpty()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems this test doesn't always succeed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So I looked into this and found that on my Mac, the JDK explicitly checks if Max-Age == -1 (MAX_AGE_UNSPECIFIED), treat the max age as unset.
In the OpenJDK 11 source code though, they treat any negative number as max age unset:
https://github.com/openjdk/jdk11u-dev/blob/75a42602826c32a1053b10188ec3826eb9c0c898/src/java.base/share/classes/java/net/HttpCookie.java#L236
The RFC states that 0, and any value less than zero is supposed to be treated as immediately expired.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've changed this test to use Max-Age==0 and added a comment.
This bug is still in OpenJDK 15: https://github.com/openjdk/jdk15u/blob/a96a5c59ac49ffb063b093a2674ede2deed87b13/src/java.base/share/classes/java/net/HttpCookie.java#L242
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added a note about this in ClientCookieMiddleware's class description.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah! That's fun. Do you think it's worth filing a JDK bug? Though I'm surprised it's been around so long.
| Assert.assertEquals("k=\"v\"", cookieMiddleware.getValidCookiesAsString()); | ||
|
|
||
| try { | ||
| Thread.sleep(5000); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a little icky, though it appears there's no way to mock time for HttpCookie.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll mark this test as @ignore, since this is essentially just testing that we call isExpired correctly, which we do in the max-age -2 test.
| cookieMiddleware.onHeadersReceived(headersToSend); | ||
|
|
||
| // Verify that the k cookie was discarded because the server told the client it is expired. | ||
| Assert.assertTrue(cookieMiddleware.getValidCookiesAsString().isEmpty()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah! That's fun. Do you think it's worth filing a JDK bug? Though I'm surprised it's been around so long.
|
Will merge on green. |
Add a ClientMiddleware that can read HTTP Set-Cookie and Set-Cookie2 headers from server responses and transmit corresponding Cookie headers Closes apache#8554 from jduo/cookie-handling Lead-authored-by: James Duong <[email protected]> Co-authored-by: Keerat Singh <[email protected]> Co-authored-by: Keerat Singh <[email protected]> Signed-off-by: David Li <[email protected]>
Add a ClientMiddleware that can read HTTP Set-Cookie and Set-Cookie2 headers
from server responses and transmit corresponding Cookie headers