View Javadoc
1   /*
2    * Copyright 2002-2014 the original author or authors.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package org.springframework.http.client;
18  
19  import java.io.IOException;
20  import java.net.HttpURLConnection;
21  import java.net.URI;
22  import java.net.URISyntaxException;
23  import java.util.List;
24  import java.util.Map;
25  
26  import org.springframework.http.HttpHeaders;
27  import org.springframework.http.HttpMethod;
28  import org.springframework.util.FileCopyUtils;
29  import org.springframework.util.ObjectUtils;
30  import org.springframework.util.StringUtils;
31  
32  /**
33   * {@link ClientHttpRequest} implementation that uses standard JDK facilities to
34   * execute buffered requests. Created via the {@link SimpleClientHttpRequestFactory}.
35   *
36   * @author Arjen Poutsma
37   * @author Juergen Hoeller
38   * @since 3.0
39   * @see SimpleClientHttpRequestFactory#createRequest(java.net.URI, HttpMethod)
40   */
41  final class SimpleBufferingClientHttpRequest extends AbstractBufferingClientHttpRequest {
42  
43  	private final HttpURLConnection connection;
44  
45  	private final boolean outputStreaming;
46  
47  
48  	SimpleBufferingClientHttpRequest(HttpURLConnection connection, boolean outputStreaming) {
49  		this.connection = connection;
50  		this.outputStreaming = outputStreaming;
51  	}
52  
53  
54  	@Override
55  	public HttpMethod getMethod() {
56  		return HttpMethod.valueOf(this.connection.getRequestMethod());
57  	}
58  
59  	@Override
60  	public URI getURI() {
61  		try {
62  			return this.connection.getURL().toURI();
63  		}
64  		catch (URISyntaxException ex) {
65  			throw new IllegalStateException("Could not get HttpURLConnection URI: " + ex.getMessage(), ex);
66  		}
67  	}
68  
69  	@Override
70  	protected ClientHttpResponse executeInternal(HttpHeaders headers, byte[] bufferedOutput) throws IOException {
71  		addHeaders(this.connection, headers);
72  
73  		// JDK < 1.8 doesn't support getOutputStream with HTTP DELETE
74  		if (HttpMethod.DELETE.equals(getMethod()) && bufferedOutput.length == 0) {
75  			this.connection.setDoOutput(false);
76  		}
77  
78  		if (this.connection.getDoOutput() && this.outputStreaming) {
79  			this.connection.setFixedLengthStreamingMode(bufferedOutput.length);
80  		}
81  		this.connection.connect();
82  		if (this.connection.getDoOutput()) {
83  			FileCopyUtils.copy(bufferedOutput, this.connection.getOutputStream());
84  		}
85  
86  		return new SimpleClientHttpResponse(this.connection);
87  	}
88  
89  
90  	/**
91  	 * Add the given headers to the given HTTP connection.
92  	 * @param connection the connection to add the headers to
93  	 * @param headers the headers to add
94  	 */
95  	static void addHeaders(HttpURLConnection connection, HttpHeaders headers) {
96  		for (Map.Entry<String, List<String>> entry : headers.entrySet()) {
97  			String headerName = entry.getKey();
98  			if (HttpHeaders.COOKIE.equalsIgnoreCase(headerName)) {  // RFC 6265
99  				String headerValue = StringUtils.collectionToDelimitedString(entry.getValue(), "; ");
100 				connection.setRequestProperty(headerName, headerValue);
101 			}
102 			else {
103 				for (String headerValue : entry.getValue()) {
104 					connection.addRequestProperty(headerName, headerValue);
105 				}
106 			}
107 		}
108 	}
109 
110 }