Skip to content

Revise cookies support with Apache HTTP Components in WebClient and WebTestClient #33822

Closed
@MFAshby

Description

@MFAshby

Steps to reproduce

  • Setup Spring WebTestClient using apache httpcomponents as the underlying HTTP client library.
  • Send a request with some cookies
  • Read cookies from the response

Expected bevaviour:

only cookies which were returned from a 'Set-Cookie' header in the HTTP response are found when calling org.springframework.test.web.reactive.server.ExchangeResult#getResponseCookies.

Actual behaviour:

cookies set on the request are also present in getResponseCookies, with spurious 'Path' metadata, even though no such cookies were returned from the server.

It seems like the problem is in org.springframework.http.client.reactive.HttpComponentsClientHttpRequest#applyCookies: this is creating entries in the cookieStore with 'path' and 'domain' metadata set to whatever we are currently requesting.

	@Override
	protected void applyCookies() {
		if (getCookies().isEmpty()) {
			return;
		}

		CookieStore cookieStore = this.context.getCookieStore();

		getCookies().values()
				.stream()
				.flatMap(Collection::stream)
				.forEach(cookie -> {
					BasicClientCookie clientCookie = new BasicClientCookie(cookie.getName(), cookie.getValue());
					clientCookie.setDomain(getURI().getHost());
					clientCookie.setPath(getURI().getPath());
					cookieStore.addCookie(clientCookie);
				});
	}

Then this same cookieStore then used to store response cookies; see org.springframework.http.client.reactive.HttpComponentsClientHttpResponse#getCookies:

	@Override
	public MultiValueMap<String, ResponseCookie> getCookies() {
		LinkedMultiValueMap<String, ResponseCookie> result = new LinkedMultiValueMap<>();
		this.context.getCookieStore().getCookies().forEach(cookie ->
				result.add(cookie.getName(),
						ResponseCookie.fromClientResponse(cookie.getName(), cookie.getValue())
								.domain(cookie.getDomain())
								.path(cookie.getPath())
								.maxAge(getMaxAgeSeconds(cookie))
								.secure(cookie.isSecure())
								.httpOnly(cookie.containsAttribute("httponly"))
								.sameSite(cookie.getAttribute("samesite"))
								.build()));
		return result;
	}

I can prepare a simple example project shortly.

Metadata

Metadata

Assignees

Labels

in: 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