Avoid parse cookies when mutating request or response

When mutating a ServerHttpRequest or ClientResponse, the respective
builders no longer access cookies automatically which causes them to
be parsed and does so only if necessary. Likewise re-applying the
read-only HttpHeaders wrapper is avoided.

See gh-24680
This commit is contained in:
Rossen Stoyanchev
2020-05-09 09:49:44 +01:00
parent 0e9ecb6c99
commit 94824e30a4
3 changed files with 96 additions and 74 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2019 the original author or authors.
* Copyright 2002-2020 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -20,7 +20,6 @@ import java.net.InetSocketAddress;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.function.Consumer;
import reactor.core.publisher.Flux;
@@ -31,7 +30,6 @@ import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.util.StringUtils;
@@ -46,12 +44,10 @@ class DefaultServerHttpRequestBuilder implements ServerHttpRequest.Builder {
private URI uri;
private HttpHeaders httpHeaders;
private HttpHeaders headers;
private String httpMethodValue;
private final MultiValueMap<String, HttpCookie> cookies;
@Nullable
private String uriPath;
@@ -70,21 +66,12 @@ class DefaultServerHttpRequestBuilder implements ServerHttpRequest.Builder {
Assert.notNull(original, "ServerHttpRequest is required");
this.uri = original.getURI();
this.headers = HttpHeaders.writableHttpHeaders(original.getHeaders());
this.httpMethodValue = original.getMethodValue();
this.body = original.getBody();
this.httpHeaders = HttpHeaders.writableHttpHeaders(original.getHeaders());
this.cookies = new LinkedMultiValueMap<>(original.getCookies().size());
copyMultiValueMap(original.getCookies(), this.cookies);
this.originalRequest = original;
}
private static <K, V> void copyMultiValueMap(MultiValueMap<K,V> source, MultiValueMap<K,V> target) {
source.forEach((key, value) -> target.put(key, new LinkedList<>(value)));
}
@Override
public ServerHttpRequest.Builder method(HttpMethod httpMethod) {
@@ -113,14 +100,14 @@ class DefaultServerHttpRequestBuilder implements ServerHttpRequest.Builder {
@Override
public ServerHttpRequest.Builder header(String headerName, String... headerValues) {
this.httpHeaders.put(headerName, Arrays.asList(headerValues));
this.headers.put(headerName, Arrays.asList(headerValues));
return this;
}
@Override
public ServerHttpRequest.Builder headers(Consumer<HttpHeaders> headersConsumer) {
Assert.notNull(headersConsumer, "'headersConsumer' must not be null");
headersConsumer.accept(this.httpHeaders);
headersConsumer.accept(this.headers);
return this;
}
@@ -132,8 +119,8 @@ class DefaultServerHttpRequestBuilder implements ServerHttpRequest.Builder {
@Override
public ServerHttpRequest build() {
return new MutatedServerHttpRequest(getUriToUse(), this.contextPath, this.httpHeaders,
this.httpMethodValue, this.cookies, this.sslInfo, this.body, this.originalRequest);
return new MutatedServerHttpRequest(getUriToUse(), this.contextPath,
this.httpMethodValue, this.sslInfo, this.body, this.originalRequest);
}
private URI getUriToUse() {
@@ -179,8 +166,6 @@ class DefaultServerHttpRequestBuilder implements ServerHttpRequest.Builder {
private final String methodValue;
private final MultiValueMap<String, HttpCookie> cookies;
@Nullable
private final SslInfo sslInfo;
@@ -190,12 +175,11 @@ class DefaultServerHttpRequestBuilder implements ServerHttpRequest.Builder {
public MutatedServerHttpRequest(URI uri, @Nullable String contextPath,
HttpHeaders headers, String methodValue, MultiValueMap<String, HttpCookie> cookies,
@Nullable SslInfo sslInfo, Flux<DataBuffer> body, ServerHttpRequest originalRequest) {
String methodValue, @Nullable SslInfo sslInfo,
Flux<DataBuffer> body, ServerHttpRequest originalRequest) {
super(uri, contextPath, headers);
super(uri, contextPath, originalRequest.getHeaders());
this.methodValue = methodValue;
this.cookies = cookies;
this.sslInfo = sslInfo != null ? sslInfo : originalRequest.getSslInfo();
this.body = body;
this.originalRequest = originalRequest;
@@ -208,7 +192,7 @@ class DefaultServerHttpRequestBuilder implements ServerHttpRequest.Builder {
@Override
protected MultiValueMap<String, HttpCookie> initCookies() {
return this.cookies;
return this.originalRequest.getCookies();
}
@Nullable