Skip to content

Commit 3a1f7b6

Browse files
committed
Client request implementations enforce RFC 6265 (cookies in a single header)
Issue: SPR-12196 (cherry picked from commit 26a93b6)
1 parent 44c52a9 commit 3a1f7b6

File tree

3 files changed

+61
-38
lines changed

3 files changed

+61
-38
lines changed

spring-web/src/main/java/org/springframework/http/client/HttpComponentsClientHttpRequest.java

Lines changed: 30 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2012 the original author or authors.
2+
* Copyright 2002-2014 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -21,9 +21,6 @@
2121
import java.util.List;
2222
import java.util.Map;
2323

24-
import org.springframework.http.HttpHeaders;
25-
import org.springframework.http.HttpMethod;
26-
2724
import org.apache.http.HttpEntity;
2825
import org.apache.http.HttpEntityEnclosingRequest;
2926
import org.apache.http.HttpResponse;
@@ -33,6 +30,10 @@
3330
import org.apache.http.protocol.HTTP;
3431
import org.apache.http.protocol.HttpContext;
3532

33+
import org.springframework.http.HttpHeaders;
34+
import org.springframework.http.HttpMethod;
35+
import org.springframework.util.StringUtils;
36+
3637
/**
3738
* {@link org.springframework.http.client.ClientHttpRequest} implementation that uses
3839
* Apache HttpComponents HttpClient to execute requests.
@@ -53,7 +54,7 @@ final class HttpComponentsClientHttpRequest extends AbstractBufferingClientHttpR
5354
private final HttpContext httpContext;
5455

5556

56-
public HttpComponentsClientHttpRequest(HttpClient httpClient, HttpUriRequest httpRequest, HttpContext httpContext) {
57+
HttpComponentsClientHttpRequest(HttpClient httpClient, HttpUriRequest httpRequest, HttpContext httpContext) {
5758
this.httpClient = httpClient;
5859
this.httpRequest = httpRequest;
5960
this.httpContext = httpContext;
@@ -71,15 +72,8 @@ public URI getURI() {
7172

7273
@Override
7374
protected ClientHttpResponse executeInternal(HttpHeaders headers, byte[] bufferedOutput) throws IOException {
74-
for (Map.Entry<String, List<String>> entry : headers.entrySet()) {
75-
String headerName = entry.getKey();
76-
if (!headerName.equalsIgnoreCase(HTTP.CONTENT_LEN) &&
77-
!headerName.equalsIgnoreCase(HTTP.TRANSFER_ENCODING)) {
78-
for (String headerValue : entry.getValue()) {
79-
this.httpRequest.addHeader(headerName, headerValue);
80-
}
81-
}
82-
}
75+
addHeaders(this.httpRequest, headers);
76+
8377
if (this.httpRequest instanceof HttpEntityEnclosingRequest) {
8478
HttpEntityEnclosingRequest entityEnclosingRequest = (HttpEntityEnclosingRequest) this.httpRequest;
8579
HttpEntity requestEntity = new ByteArrayEntity(bufferedOutput);
@@ -89,4 +83,26 @@ protected ClientHttpResponse executeInternal(HttpHeaders headers, byte[] buffere
8983
return new HttpComponentsClientHttpResponse(httpResponse);
9084
}
9185

86+
87+
/**
88+
* Add the given headers to the given HTTP request.
89+
* @param httpRequest the request to add the headers to
90+
* @param headers the headers to add
91+
*/
92+
static void addHeaders(HttpUriRequest httpRequest, HttpHeaders headers) {
93+
for (Map.Entry<String, List<String>> entry : headers.entrySet()) {
94+
String headerName = entry.getKey();
95+
if ("Cookie".equalsIgnoreCase(headerName)) { // RFC 6265
96+
String headerValue = StringUtils.collectionToDelimitedString(entry.getValue(), "; ");
97+
httpRequest.addHeader(headerName, headerValue);
98+
}
99+
else if (!HTTP.CONTENT_LEN.equalsIgnoreCase(headerName) &&
100+
!HTTP.TRANSFER_ENCODING.equalsIgnoreCase(headerName)) {
101+
for (String headerValue : entry.getValue()) {
102+
httpRequest.addHeader(headerName, headerValue);
103+
}
104+
}
105+
}
106+
}
107+
92108
}

spring-web/src/main/java/org/springframework/http/client/SimpleBufferingClientHttpRequest.java

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2013 the original author or authors.
2+
* Copyright 2002-2014 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -26,12 +26,14 @@
2626
import org.springframework.http.HttpHeaders;
2727
import org.springframework.http.HttpMethod;
2828
import org.springframework.util.FileCopyUtils;
29+
import org.springframework.util.StringUtils;
2930

3031
/**
31-
* {@link ClientHttpRequest} implementation that uses standard J2SE facilities to execute buffered requests.
32-
* Created via the {@link SimpleClientHttpRequestFactory}.
32+
* {@link ClientHttpRequest} implementation that uses standard JDK facilities to
33+
* execute buffered requests. Created via the {@link SimpleClientHttpRequestFactory}.
3334
*
3435
* @author Arjen Poutsma
36+
* @author Juergen Hoeller
3537
* @since 3.0
3638
* @see SimpleClientHttpRequestFactory#createRequest(java.net.URI, HttpMethod)
3739
*/
@@ -63,12 +65,7 @@ public URI getURI() {
6365

6466
@Override
6567
protected ClientHttpResponse executeInternal(HttpHeaders headers, byte[] bufferedOutput) throws IOException {
66-
for (Map.Entry<String, List<String>> entry : headers.entrySet()) {
67-
String headerName = entry.getKey();
68-
for (String headerValue : entry.getValue()) {
69-
this.connection.addRequestProperty(headerName, headerValue);
70-
}
71-
}
68+
addHeaders(this.connection, headers);
7269

7370
if (this.connection.getDoOutput() && this.outputStreaming) {
7471
this.connection.setFixedLengthStreamingMode(bufferedOutput.length);
@@ -81,4 +78,25 @@ protected ClientHttpResponse executeInternal(HttpHeaders headers, byte[] buffere
8178
return new SimpleClientHttpResponse(this.connection);
8279
}
8380

81+
82+
/**
83+
* Add the given headers to the given HTTP connection.
84+
* @param connection the connection to add the headers to
85+
* @param headers the headers to add
86+
*/
87+
static void addHeaders(HttpURLConnection connection, HttpHeaders headers) {
88+
for (Map.Entry<String, List<String>> entry : headers.entrySet()) {
89+
String headerName = entry.getKey();
90+
if ("Cookie".equalsIgnoreCase(headerName)) { // RFC 6265
91+
String headerValue = StringUtils.collectionToDelimitedString(entry.getValue(), "; ");
92+
connection.setRequestProperty(headerName, headerValue);
93+
}
94+
else {
95+
for (String headerValue : entry.getValue()) {
96+
connection.addRequestProperty(headerName, headerValue);
97+
}
98+
}
99+
}
100+
}
101+
84102
}

spring-web/src/main/java/org/springframework/http/client/SimpleStreamingClientHttpRequest.java

Lines changed: 4 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -21,16 +21,14 @@
2121
import java.net.HttpURLConnection;
2222
import java.net.URI;
2323
import java.net.URISyntaxException;
24-
import java.util.List;
25-
import java.util.Map;
2624

2725
import org.springframework.http.HttpHeaders;
2826
import org.springframework.http.HttpMethod;
2927
import org.springframework.util.StreamUtils;
3028

3129
/**
32-
* {@link ClientHttpRequest} implementation that uses standard J2SE facilities to execute streaming requests.
33-
* Created via the {@link SimpleClientHttpRequestFactory}.
30+
* {@link ClientHttpRequest} implementation that uses standard JDK facilities to
31+
* execute streaming requests. Created via the {@link SimpleClientHttpRequestFactory}.
3432
*
3533
* @author Arjen Poutsma
3634
* @since 3.0
@@ -79,30 +77,21 @@ protected OutputStream getBodyInternal(HttpHeaders headers) throws IOException {
7977
this.connection.setChunkedStreamingMode(this.chunkSize);
8078
}
8179
}
82-
writeHeaders(headers);
80+
SimpleBufferingClientHttpRequest.addHeaders(this.connection, headers);
8381
this.connection.connect();
8482
this.body = this.connection.getOutputStream();
8583
}
8684
return StreamUtils.nonClosing(this.body);
8785
}
8886

89-
private void writeHeaders(HttpHeaders headers) {
90-
for (Map.Entry<String, List<String>> entry : headers.entrySet()) {
91-
String headerName = entry.getKey();
92-
for (String headerValue : entry.getValue()) {
93-
this.connection.addRequestProperty(headerName, headerValue);
94-
}
95-
}
96-
}
97-
9887
@Override
9988
protected ClientHttpResponse executeInternal(HttpHeaders headers) throws IOException {
10089
try {
10190
if (this.body != null) {
10291
this.body.close();
10392
}
10493
else {
105-
writeHeaders(headers);
94+
SimpleBufferingClientHttpRequest.addHeaders(this.connection, headers);
10695
this.connection.connect();
10796
}
10897
}

0 commit comments

Comments
 (0)