Skip to content

Multiple Cookie headers on request #11819

Open
@kristofdho

Description

@kristofdho

Expected Behavior

Calling MutableHttpRequest.cookie(s) keeps a single cookie header up to date.

Actual Behaviour

Multiple Cookie headers are created depending on the specific request implementation.

Steps To Reproduce

Specifically ran into this when adding additional cookies in a proxy filter, so calling request.mutate().cookie(...) in a HttpServerFilter.

This JUnit test shows the issue, based on the fix provided in #6356:

class CookieTest {

    private static final Set<Cookie> COOKIES = new LinkedHashSet() {{
        add(Cookie.of("a", "1"));
        add(Cookie.of("b", "2"));
        add(Cookie.of("a", "3"));
    }};
    private static final String EXPECTED_VALUE = "a=3; b=2"; // Comment in NettyHttpClientRequest claims a space is needed :shrug:

    static List<Arguments> httpRequests() {
        MutableHttpRequest<?> simpleRequest = new SimpleHttpRequestFactory().get("/");
        MutableHttpRequest<?> nettyClientRequest = new NettyClientHttpRequestFactory().get("/");
        MutableHttpRequest<?> nettyHttpRequest = new NettyHttpRequest<>(
                new DefaultHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, "/"),
                AvailableNettyByteBody.empty(),
                Mockito.mock(ChannelHandlerContext.class),
                Mockito.mock(ConversionService.class),
                Mockito.mock(HttpServerConfiguration.class)).mutate();
        return List.of(
                Arguments.argumentSet(simpleRequest.getClass().getSimpleName(), simpleRequest),
                Arguments.argumentSet(nettyClientRequest.getClass().getSimpleName(), nettyClientRequest),
                Arguments.argumentSet(nettyHttpRequest.getClass().getSimpleName(), nettyHttpRequest)
        );
    }

    @ParameterizedTest
    @MethodSource("httpRequests")
    void requestCookiesOneByOne(MutableHttpRequest<?> request) {
        COOKIES.forEach(request::cookie);

        assertAll(
                () -> assertEquals(1, request.getHeaders().get(HttpHeaders.COOKIE).length()),
                () -> assertEquals(EXPECTED_VALUE, request.getHeaders().get(HttpHeaders.COOKIE))
        );
    }

    @ParameterizedTest
    @MethodSource("httpRequests")
    void requestCookiesBulk(MutableHttpRequest<?> request) {
        COOKIES.forEach(request::cookie);

        assertAll(
                () -> assertEquals(1, request.getHeaders().get(HttpHeaders.COOKIE).length()),
                () -> assertEquals(EXPECTED_VALUE, request.getHeaders().get(HttpHeaders.COOKIE))
        );
    }
}
Image

Environment Information

OS: Windows
JDK: 21

Example Application

No response

Version

4.8.2

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions