001/* 002 * Copyright 2002-2016 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * https://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.springframework.http.client; 018 019import java.io.IOException; 020import java.net.MalformedURLException; 021import java.net.URI; 022import java.util.List; 023import java.util.Map; 024import java.util.concurrent.TimeUnit; 025 026import com.squareup.okhttp.OkHttpClient; 027import com.squareup.okhttp.Request; 028import com.squareup.okhttp.RequestBody; 029 030import org.springframework.beans.factory.DisposableBean; 031import org.springframework.http.HttpHeaders; 032import org.springframework.http.HttpMethod; 033import org.springframework.util.Assert; 034import org.springframework.util.StringUtils; 035 036/** 037 * {@link ClientHttpRequestFactory} implementation that uses 038 * <a href="https://square.github.io/okhttp/">OkHttp</a> 2.x to create requests. 039 * 040 * @author Luciano Leggieri 041 * @author Arjen Poutsma 042 * @since 4.2 043 * @see org.springframework.http.client.OkHttp3ClientHttpRequestFactory 044 */ 045public class OkHttpClientHttpRequestFactory 046 implements ClientHttpRequestFactory, AsyncClientHttpRequestFactory, DisposableBean { 047 048 private final OkHttpClient client; 049 050 private final boolean defaultClient; 051 052 053 /** 054 * Create a factory with a default {@link OkHttpClient} instance. 055 */ 056 public OkHttpClientHttpRequestFactory() { 057 this.client = new OkHttpClient(); 058 this.defaultClient = true; 059 } 060 061 /** 062 * Create a factory with the given {@link OkHttpClient} instance. 063 * @param client the client to use 064 */ 065 public OkHttpClientHttpRequestFactory(OkHttpClient client) { 066 Assert.notNull(client, "OkHttpClient must not be null"); 067 this.client = client; 068 this.defaultClient = false; 069 } 070 071 072 /** 073 * Sets the underlying read timeout in milliseconds. 074 * A value of 0 specifies an infinite timeout. 075 * @see OkHttpClient#setReadTimeout(long, TimeUnit) 076 */ 077 public void setReadTimeout(int readTimeout) { 078 this.client.setReadTimeout(readTimeout, TimeUnit.MILLISECONDS); 079 } 080 081 /** 082 * Sets the underlying write timeout in milliseconds. 083 * A value of 0 specifies an infinite timeout. 084 * @see OkHttpClient#setWriteTimeout(long, TimeUnit) 085 */ 086 public void setWriteTimeout(int writeTimeout) { 087 this.client.setWriteTimeout(writeTimeout, TimeUnit.MILLISECONDS); 088 } 089 090 /** 091 * Sets the underlying connect timeout in milliseconds. 092 * A value of 0 specifies an infinite timeout. 093 * @see OkHttpClient#setConnectTimeout(long, TimeUnit) 094 */ 095 public void setConnectTimeout(int connectTimeout) { 096 this.client.setConnectTimeout(connectTimeout, TimeUnit.MILLISECONDS); 097 } 098 099 100 @Override 101 public ClientHttpRequest createRequest(URI uri, HttpMethod httpMethod) { 102 return new OkHttpClientHttpRequest(this.client, uri, httpMethod); 103 } 104 105 @Override 106 public AsyncClientHttpRequest createAsyncRequest(URI uri, HttpMethod httpMethod) { 107 return new OkHttpAsyncClientHttpRequest(this.client, uri, httpMethod); 108 } 109 110 111 @Override 112 public void destroy() throws IOException { 113 if (this.defaultClient) { 114 // Clean up the client if we created it in the constructor 115 if (this.client.getCache() != null) { 116 this.client.getCache().close(); 117 } 118 this.client.getDispatcher().getExecutorService().shutdown(); 119 } 120 } 121 122 123 static Request buildRequest(HttpHeaders headers, byte[] content, URI uri, HttpMethod method) 124 throws MalformedURLException { 125 126 com.squareup.okhttp.MediaType contentType = getContentType(headers); 127 RequestBody body = (content.length > 0 || 128 com.squareup.okhttp.internal.http.HttpMethod.requiresRequestBody(method.name()) ? 129 RequestBody.create(contentType, content) : null); 130 131 Request.Builder builder = new Request.Builder().url(uri.toURL()).method(method.name(), body); 132 for (Map.Entry<String, List<String>> entry : headers.entrySet()) { 133 String headerName = entry.getKey(); 134 for (String headerValue : entry.getValue()) { 135 builder.addHeader(headerName, headerValue); 136 } 137 } 138 return builder.build(); 139 } 140 141 private static com.squareup.okhttp.MediaType getContentType(HttpHeaders headers) { 142 String rawContentType = headers.getFirst(HttpHeaders.CONTENT_TYPE); 143 return (StringUtils.hasText(rawContentType) ? 144 com.squareup.okhttp.MediaType.parse(rawContentType) : null); 145 } 146 147}