Skip to content

Update Cookie headers in MockServerHttpRequest and Response [SPR-15522] #20081

@spring-projects-issues

Description

@spring-projects-issues

Rob Winch opened SPR-15522 and commented

When using the WebTestClient with the mock support (i.e. bindToHttpHandler) cookies are not written as headers to the response like they are when a real server is used. This is illustrated in the tests below.

package sample;

import org.junit.Test;
import org.springframework.http.ResponseCookie;
import org.springframework.http.server.reactive.HttpHandler;
import org.springframework.http.server.reactive.ReactorHttpHandlerAdapter;
import org.springframework.test.web.reactive.server.FluxExchangeResult;
import org.springframework.test.web.reactive.server.WebTestClient;
import org.springframework.web.server.ServerWebExchange;
import org.springframework.web.server.WebFilter;
import org.springframework.web.server.WebFilterChain;
import org.springframework.web.server.adapter.WebHttpHandlerBuilder;
import reactor.core.publisher.Mono;
import reactor.ipc.netty.NettyContext;

import java.util.Arrays;

import static org.assertj.core.api.Assertions.assertThat;

public class HttpSessionCookieTests {

	// fails
	@Test
	public void createMockWebClient() {
		HttpHandler handler = handler();
		WebTestClient client = WebTestClient.bindToHttpHandler(handler).build();

		assertSetCookieHeaderExists(client);
	}

	// works
	@Test
	public void createReactorNetty() {
		NettyContext netty = null;
		try {
			netty = nettyContext();
			WebTestClient client = WebTestClient.bindToServer()
				.baseUrl("http://localhost:" + netty.address().getPort())
				.build();

			assertSetCookieHeaderExists(client);
		} finally {
			if(netty != null) {
				netty.dispose();
			}
		}
	}

	private HttpHandler handler() {
		return WebHttpHandlerBuilder.webHandler(e -> Mono.empty()).filters(Arrays.asList(new WritesCookieFilter())).build();
	}

	private void assertSetCookieHeaderExists(WebTestClient client) {
		FluxExchangeResult<String> result = client.get()
			.uri("/")
			.exchange()
			.returnResult(String.class);

		assertThat(result.getResponseHeaders()).containsKeys("Set-Cookie");
	}


	private NettyContext nettyContext() {
		HttpHandler handler = handler();
		ReactorHttpHandlerAdapter adapter = new ReactorHttpHandlerAdapter(handler);
		reactor.ipc.netty.http.server.HttpServer httpServer = reactor.ipc.netty.http.server.HttpServer.create("localhost", 0);
		return httpServer.newHandler(adapter).block();
	}

	static class WritesCookieFilter implements WebFilter {

		@Override
		public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
			exchange.getResponse().getCookies().add("FOO", ResponseCookie.from("FOO","BAR").build());
			return chain.filter(exchange);
		}
	}
}

This appears to be related to the fact that AbstractServerHttpResponse relies on applyCookies to be implemented. While ReactorServerHttpResponse implements applyCookies, MockServerHttpResponse does not implement applyCookies.


Affects: 5.0 RC1

Issue Links:

Referenced from: commits 5dcfd84

Metadata

Metadata

Assignees

Labels

in: testIssues in the test modulein: webIssues in web modules (web, webmvc, webflux, websocket)type: enhancementA general enhancement

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions