Client request implementations enforce RFC 6265 (cookies in a single header)
Issue: SPR-12196
This commit is contained in:
@@ -32,6 +32,7 @@ import org.apache.http.protocol.HttpContext;
|
|||||||
|
|
||||||
import org.springframework.http.HttpHeaders;
|
import org.springframework.http.HttpHeaders;
|
||||||
import org.springframework.http.HttpMethod;
|
import org.springframework.http.HttpMethod;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@link org.springframework.http.client.ClientHttpRequest} implementation that uses
|
* {@link org.springframework.http.client.ClientHttpRequest} implementation that uses
|
||||||
@@ -41,6 +42,7 @@ import org.springframework.http.HttpMethod;
|
|||||||
*
|
*
|
||||||
* @author Oleg Kalnichevski
|
* @author Oleg Kalnichevski
|
||||||
* @author Arjen Poutsma
|
* @author Arjen Poutsma
|
||||||
|
* @author Juergen Hoeller
|
||||||
* @since 3.1
|
* @since 3.1
|
||||||
* @see HttpComponentsClientHttpRequestFactory#createRequest(URI, HttpMethod)
|
* @see HttpComponentsClientHttpRequestFactory#createRequest(URI, HttpMethod)
|
||||||
*/
|
*/
|
||||||
@@ -97,8 +99,12 @@ final class HttpComponentsClientHttpRequest extends AbstractBufferingClientHttpR
|
|||||||
static void addHeaders(HttpUriRequest httpRequest, HttpHeaders headers) {
|
static void addHeaders(HttpUriRequest httpRequest, HttpHeaders headers) {
|
||||||
for (Map.Entry<String, List<String>> entry : headers.entrySet()) {
|
for (Map.Entry<String, List<String>> entry : headers.entrySet()) {
|
||||||
String headerName = entry.getKey();
|
String headerName = entry.getKey();
|
||||||
if (!headerName.equalsIgnoreCase(HTTP.CONTENT_LEN) &&
|
if (HttpHeaders.COOKIE.equalsIgnoreCase(headerName)) { // RFC 6265
|
||||||
!headerName.equalsIgnoreCase(HTTP.TRANSFER_ENCODING)) {
|
String headerValue = StringUtils.collectionToDelimitedString(entry.getValue(), "; ");
|
||||||
|
httpRequest.addHeader(headerName, headerValue);
|
||||||
|
}
|
||||||
|
else if (!HTTP.CONTENT_LEN.equalsIgnoreCase(headerName) &&
|
||||||
|
!HTTP.TRANSFER_ENCODING.equalsIgnoreCase(headerName)) {
|
||||||
for (String headerValue : entry.getValue()) {
|
for (String headerValue : entry.getValue()) {
|
||||||
httpRequest.addHeader(headerName, headerValue);
|
httpRequest.addHeader(headerName, headerValue);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,8 +20,6 @@ import java.io.IOException;
|
|||||||
import java.net.HttpURLConnection;
|
import java.net.HttpURLConnection;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.net.URISyntaxException;
|
import java.net.URISyntaxException;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.concurrent.Callable;
|
import java.util.concurrent.Callable;
|
||||||
|
|
||||||
import org.springframework.core.task.AsyncListenableTaskExecutor;
|
import org.springframework.core.task.AsyncListenableTaskExecutor;
|
||||||
@@ -32,7 +30,7 @@ import org.springframework.util.concurrent.ListenableFuture;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* {@link org.springframework.http.client.ClientHttpRequest} implementation that uses
|
* {@link org.springframework.http.client.ClientHttpRequest} implementation that uses
|
||||||
* standard J2SE facilities to execute buffered requests. Created via the
|
* standard JDK facilities to execute buffered requests. Created via the
|
||||||
* {@link org.springframework.http.client.SimpleClientHttpRequestFactory}.
|
* {@link org.springframework.http.client.SimpleClientHttpRequestFactory}.
|
||||||
*
|
*
|
||||||
* @author Arjen Poutsma
|
* @author Arjen Poutsma
|
||||||
@@ -79,12 +77,7 @@ final class SimpleBufferingAsyncClientHttpRequest extends AbstractBufferingAsync
|
|||||||
return this.taskExecutor.submitListenable(new Callable<ClientHttpResponse>() {
|
return this.taskExecutor.submitListenable(new Callable<ClientHttpResponse>() {
|
||||||
@Override
|
@Override
|
||||||
public ClientHttpResponse call() throws Exception {
|
public ClientHttpResponse call() throws Exception {
|
||||||
for (Map.Entry<String, List<String>> entry : headers.entrySet()) {
|
SimpleBufferingClientHttpRequest.addHeaders(connection, headers);
|
||||||
String headerName = entry.getKey();
|
|
||||||
for (String headerValue : entry.getValue()) {
|
|
||||||
connection.addRequestProperty(headerName, headerValue);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (connection.getDoOutput() && outputStreaming) {
|
if (connection.getDoOutput() && outputStreaming) {
|
||||||
connection.setFixedLengthStreamingMode(bufferedOutput.length);
|
connection.setFixedLengthStreamingMode(bufferedOutput.length);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2002-2013 the original author or authors.
|
* Copyright 2002-2014 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -26,12 +26,14 @@ import java.util.Map;
|
|||||||
import org.springframework.http.HttpHeaders;
|
import org.springframework.http.HttpHeaders;
|
||||||
import org.springframework.http.HttpMethod;
|
import org.springframework.http.HttpMethod;
|
||||||
import org.springframework.util.FileCopyUtils;
|
import org.springframework.util.FileCopyUtils;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@link ClientHttpRequest} implementation that uses standard J2SE facilities to execute buffered requests.
|
* {@link ClientHttpRequest} implementation that uses standard JDK facilities to
|
||||||
* Created via the {@link SimpleClientHttpRequestFactory}.
|
* execute buffered requests. Created via the {@link SimpleClientHttpRequestFactory}.
|
||||||
*
|
*
|
||||||
* @author Arjen Poutsma
|
* @author Arjen Poutsma
|
||||||
|
* @author Juergen Hoeller
|
||||||
* @since 3.0
|
* @since 3.0
|
||||||
* @see SimpleClientHttpRequestFactory#createRequest(java.net.URI, HttpMethod)
|
* @see SimpleClientHttpRequestFactory#createRequest(java.net.URI, HttpMethod)
|
||||||
*/
|
*/
|
||||||
@@ -65,12 +67,7 @@ final class SimpleBufferingClientHttpRequest extends AbstractBufferingClientHttp
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected ClientHttpResponse executeInternal(HttpHeaders headers, byte[] bufferedOutput) throws IOException {
|
protected ClientHttpResponse executeInternal(HttpHeaders headers, byte[] bufferedOutput) throws IOException {
|
||||||
for (Map.Entry<String, List<String>> entry : headers.entrySet()) {
|
addHeaders(this.connection, headers);
|
||||||
String headerName = entry.getKey();
|
|
||||||
for (String headerValue : entry.getValue()) {
|
|
||||||
this.connection.addRequestProperty(headerName, headerValue);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.connection.getDoOutput() && this.outputStreaming) {
|
if (this.connection.getDoOutput() && this.outputStreaming) {
|
||||||
this.connection.setFixedLengthStreamingMode(bufferedOutput.length);
|
this.connection.setFixedLengthStreamingMode(bufferedOutput.length);
|
||||||
@@ -83,4 +80,25 @@ final class SimpleBufferingClientHttpRequest extends AbstractBufferingClientHttp
|
|||||||
return new SimpleClientHttpResponse(this.connection);
|
return new SimpleClientHttpResponse(this.connection);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add the given headers to the given HTTP connection.
|
||||||
|
* @param connection the connection to add the headers to
|
||||||
|
* @param headers the headers to add
|
||||||
|
*/
|
||||||
|
static void addHeaders(HttpURLConnection connection, HttpHeaders headers) {
|
||||||
|
for (Map.Entry<String, List<String>> entry : headers.entrySet()) {
|
||||||
|
String headerName = entry.getKey();
|
||||||
|
if (HttpHeaders.COOKIE.equalsIgnoreCase(headerName)) { // RFC 6265
|
||||||
|
String headerValue = StringUtils.collectionToDelimitedString(entry.getValue(), "; ");
|
||||||
|
connection.setRequestProperty(headerName, headerValue);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
for (String headerValue : entry.getValue()) {
|
||||||
|
connection.addRequestProperty(headerName, headerValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,8 +21,6 @@ import java.io.OutputStream;
|
|||||||
import java.net.HttpURLConnection;
|
import java.net.HttpURLConnection;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.net.URISyntaxException;
|
import java.net.URISyntaxException;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.concurrent.Callable;
|
import java.util.concurrent.Callable;
|
||||||
|
|
||||||
import org.springframework.core.task.AsyncListenableTaskExecutor;
|
import org.springframework.core.task.AsyncListenableTaskExecutor;
|
||||||
@@ -91,22 +89,13 @@ final class SimpleStreamingAsyncClientHttpRequest extends AbstractAsyncClientHtt
|
|||||||
this.connection.setChunkedStreamingMode(this.chunkSize);
|
this.connection.setChunkedStreamingMode(this.chunkSize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
writeHeaders(headers);
|
SimpleBufferingClientHttpRequest.addHeaders(this.connection, headers);
|
||||||
this.connection.connect();
|
this.connection.connect();
|
||||||
this.body = this.connection.getOutputStream();
|
this.body = this.connection.getOutputStream();
|
||||||
}
|
}
|
||||||
return StreamUtils.nonClosing(this.body);
|
return StreamUtils.nonClosing(this.body);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void writeHeaders(HttpHeaders headers) {
|
|
||||||
for (Map.Entry<String, List<String>> entry : headers.entrySet()) {
|
|
||||||
String headerName = entry.getKey();
|
|
||||||
for (String headerValue : entry.getValue()) {
|
|
||||||
this.connection.addRequestProperty(headerName, headerValue);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected ListenableFuture<ClientHttpResponse> executeInternal(final HttpHeaders headers) throws IOException {
|
protected ListenableFuture<ClientHttpResponse> executeInternal(final HttpHeaders headers) throws IOException {
|
||||||
return this.taskExecutor.submitListenable(new Callable<ClientHttpResponse>() {
|
return this.taskExecutor.submitListenable(new Callable<ClientHttpResponse>() {
|
||||||
@@ -117,7 +106,7 @@ final class SimpleStreamingAsyncClientHttpRequest extends AbstractAsyncClientHtt
|
|||||||
body.close();
|
body.close();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
writeHeaders(headers);
|
SimpleBufferingClientHttpRequest.addHeaders(connection, headers);
|
||||||
connection.connect();
|
connection.connect();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,16 +21,14 @@ import java.io.OutputStream;
|
|||||||
import java.net.HttpURLConnection;
|
import java.net.HttpURLConnection;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.net.URISyntaxException;
|
import java.net.URISyntaxException;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import org.springframework.http.HttpHeaders;
|
import org.springframework.http.HttpHeaders;
|
||||||
import org.springframework.http.HttpMethod;
|
import org.springframework.http.HttpMethod;
|
||||||
import org.springframework.util.StreamUtils;
|
import org.springframework.util.StreamUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@link ClientHttpRequest} implementation that uses standard J2SE facilities to execute streaming requests.
|
* {@link ClientHttpRequest} implementation that uses standard JDK facilities to
|
||||||
* Created via the {@link SimpleClientHttpRequestFactory}.
|
* execute streaming requests. Created via the {@link SimpleClientHttpRequestFactory}.
|
||||||
*
|
*
|
||||||
* @author Arjen Poutsma
|
* @author Arjen Poutsma
|
||||||
* @since 3.0
|
* @since 3.0
|
||||||
@@ -80,22 +78,13 @@ final class SimpleStreamingClientHttpRequest extends AbstractClientHttpRequest {
|
|||||||
this.connection.setChunkedStreamingMode(this.chunkSize);
|
this.connection.setChunkedStreamingMode(this.chunkSize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
writeHeaders(headers);
|
SimpleBufferingClientHttpRequest.addHeaders(this.connection, headers);
|
||||||
this.connection.connect();
|
this.connection.connect();
|
||||||
this.body = this.connection.getOutputStream();
|
this.body = this.connection.getOutputStream();
|
||||||
}
|
}
|
||||||
return StreamUtils.nonClosing(this.body);
|
return StreamUtils.nonClosing(this.body);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void writeHeaders(HttpHeaders headers) {
|
|
||||||
for (Map.Entry<String, List<String>> entry : headers.entrySet()) {
|
|
||||||
String headerName = entry.getKey();
|
|
||||||
for (String headerValue : entry.getValue()) {
|
|
||||||
this.connection.addRequestProperty(headerName, headerValue);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected ClientHttpResponse executeInternal(HttpHeaders headers) throws IOException {
|
protected ClientHttpResponse executeInternal(HttpHeaders headers) throws IOException {
|
||||||
try {
|
try {
|
||||||
@@ -103,7 +92,7 @@ final class SimpleStreamingClientHttpRequest extends AbstractClientHttpRequest {
|
|||||||
this.body.close();
|
this.body.close();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
writeHeaders(headers);
|
SimpleBufferingClientHttpRequest.addHeaders(this.connection, headers);
|
||||||
this.connection.connect();
|
this.connection.connect();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user