Skip to content
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

Cookies 1.0 api #217

Merged
merged 26 commits into from
Jul 26, 2018
Merged

Cookies 1.0 api #217

merged 26 commits into from
Jul 26, 2018

Conversation

kvosper
Copy link
Contributor

@kvosper kvosper commented Jul 23, 2018

A PR to make improvements to the way that Styx handles cookies.
The main changes are:

  • Use the Cookie and Set-Cookie headers as the sole source-of-truth instead of trying to keep a separate collection of cookies in the message object.
  • Introduce a clear distinction between request cookies (key-value pairs set in Cookie header) and response cookies (individual Set-Cookie headers that have attributes like Domain and Path).

@kvosper kvosper requested review from mikkokar and dvlato July 23, 2018 15:34
private static HttpResponse addCookie(HttpResponse response, ResponseCookie cookie) {
return response.newBuilder()
.addHeader(SET_COOKIE, ResponseCookie.encode(cookie))
.build();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be using a yet-to-be-added addCookie method.

.cookies(
RequestCookie.requestCookie("other_cookie1", "foo"),
RequestCookie.requestCookie("styx_origin_app", "app-02"),
RequestCookie.requestCookie("other_cookie2", "bar"))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

static import?

}

/**
* Adds cookies into this request by overwriting the value of the "Cookie" header.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would just say:

Adds cookies into the Cookie header.

What happens if the cookie name is already present?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would also elaborate that:

Adds cookies into Cookie header, or modified existing cookie values.

}

/**
* Adds cookies into this request by overwriting the value of the "Cookie" header.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I cannot see any unit tests for addCookies. Please add tests for addCookies(), or am I just missing something?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add unit tests for the following addTests scenarios:

  1. add a new cookie when Cookie header is not present.
  2. add a new cookie when Cookie header is already present.
  3. modify a cookie value using addCookie when a Cookie header is present and the cookie is already set.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, there are missing tests. I will add tests for the new methods.

.collect(toList());

return cookies(newCookies);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is perhaps bit contrived example, but perhaps worth looking into @kvosper:

    @Test
    public void removesCookies2() {
        HttpRequest r1 = HttpRequest.get("/")
                .addCookies(requestCookie("x", "x1"))
                .removeCookies("x")
                .build();

        assertThat(r1.cookie("x"), is(Optional.empty()));
    }

This test would fail as follows:

java.lang.AssertionError: 
Expected: is <Optional.empty>
     but: was <Optional[x=x1]>

I'll find this counter-intuitive.

Copy link
Contributor

@dvlato dvlato left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don´t think having to decode the cookies for each getCookies() is the best approach. Can´t we apply some memoization so once decoded a cookie list will be kept until we modify the Cookie header?

public Builder cookies(Collection<RequestCookie> cookies) {
headers.remove(COOKIE);

if (!cookies.isEmpty()) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we usually do a null check in these cases.

List<RequestCookie> combinedCookies = new ArrayList<>(currentCookies.size() + cookies.size());
combinedCookies.addAll(cookies);
combinedCookies.addAll(currentCookies);
return cookies(combinedCookies);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We might want to get rid of the creation of the Temporary list (e.g., using Stream.concatenate() and passing in an Stream or Iterables.xx in Guava and an Iterator ).

Also, the fact that we'll override previously existing values is quite difficult to understand in this code (you add the new cookies first so they will be the ones picked up in the Collectors.toSet() in the following method). That´s a path hard to follow and it depends on a non-documented behaviour of Collectors.toSet(). Probably it is better to try to make this clear somehow.

EDIT: probably my next comments will contradict my first request.

*/
public Set<RequestCookie> cookies() {
// Note: there should only be one "Cookie" header, but we check for multiples just in case
// the alternative would be to respond with a 400 Bad Request status if multiple "Cookie" headers were detected
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The RFC clearly states that there should be a single Cookie header. I think we can return an error in that case.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We would need to return the error in the builder. The cookies method could be changed to assume only one Cookie header exists though.

* @param cookies cookies
* @return "Cookie" header value
*/
public static String encode(Collection<RequestCookie> cookies) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The treatment of duplicate cookies is part of the netty encoding logic - it is not something introduced by Styx.

* @param cookies cookies
* @return "Cookie" header value
*/
public static String encode(Collection<RequestCookie> cookies) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The treatment of duplicate cookies is part of the netty encoding logic - it is not something introduced by Styx.

@kvosper kvosper merged commit 280dafb into ExpediaGroup:styx-1.0-dev Jul 26, 2018
@kvosper kvosper deleted the cookies-1.0-api branch July 26, 2018 15:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants