Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ configure(allprojects) { project ->
ext.jtaVersion = "1.2"
ext.junitVersion = "4.12"
ext.nettyVersion = "4.0.34.Final"
ext.okhttp3Version = "3.2.0"
ext.okhttpVersion = "2.7.4"
ext.openjpaVersion = "2.4.0"
ext.poiVersion = "3.13"
Expand Down Expand Up @@ -712,6 +713,7 @@ project("spring-web") {
optional("org.apache.httpcomponents:httpclient:${httpclientVersion}")
optional("org.apache.httpcomponents:httpasyncclient:${httpasyncVersion}")
optional("io.netty:netty-all:${nettyVersion}")
optional("com.squareup.okhttp3:okhttp:${okhttp3Version}")
optional("com.squareup.okhttp:okhttp:${okhttpVersion}")
optional("com.fasterxml.jackson.core:jackson-databind:${jackson2Version}")
optional("com.fasterxml.jackson.dataformat:jackson-dataformat-xml:${jackson2Version}")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
/*
* Copyright 2002-2016 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.springframework.http.client;

import java.io.IOException;
import java.net.URI;

import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;

import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.util.concurrent.ListenableFuture;
import org.springframework.util.concurrent.SettableListenableFuture;

/**
* {@link AsyncClientHttpRequest} implementation that uses OkHttp to execute requests.
*
* <p>Created via the {@link OkHttpClientHttpRequestFactory}.
*
* @author Luciano Leggieri
* @author Arjen Poutsma
* @author Roy Clarkson
* @since 4.3
*/
class OkHttp3AsyncClientHttpRequest extends AbstractBufferingAsyncClientHttpRequest {

private final OkHttpClient client;

private final URI uri;

private final HttpMethod method;


public OkHttp3AsyncClientHttpRequest(OkHttpClient client, URI uri, HttpMethod method) {
this.client = client;
this.uri = uri;
this.method = method;
}


@Override
public HttpMethod getMethod() {
return this.method;
}

@Override
public URI getURI() {
return this.uri;
}

@Override
protected ListenableFuture<ClientHttpResponse> executeInternal(HttpHeaders headers, byte[] content)
throws IOException {

Request request = OkHttp3ClientHttpRequestFactory.buildRequest(headers, content, this.uri, this.method);
return new OkHttpListenableFuture(this.client.newCall(request));
}


private static class OkHttpListenableFuture extends SettableListenableFuture<ClientHttpResponse> {

private final Call call;

public OkHttpListenableFuture(Call call) {
this.call = call;
this.call.enqueue(new Callback() {
@Override
public void onResponse(Call call, Response response) {
set(new OkHttp3ClientHttpResponse(response));
}
@Override
public void onFailure(Call call, IOException ex) {
setException(ex);
}
});
}

@Override
protected void interruptTask() {
this.call.cancel();
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/*
* Copyright 2002-2016 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.springframework.http.client;

import java.io.IOException;
import java.net.URI;

import okhttp3.OkHttpClient;
import okhttp3.Request;

import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;

/**
* {@link ClientHttpRequest} implementation that uses OkHttp 3.x to execute requests.
*
* <p>Created via the {@link OkHttp3ClientHttpRequestFactory}.
*
* @author Luciano Leggieri
* @author Arjen Poutsma
* @author Roy Clarkson
* @since 4.3
*/
class OkHttp3ClientHttpRequest extends AbstractBufferingClientHttpRequest {

private final OkHttpClient client;

private final URI uri;

private final HttpMethod method;


public OkHttp3ClientHttpRequest(OkHttpClient client, URI uri, HttpMethod method) {
this.client = client;
this.uri = uri;
this.method = method;
}


@Override
public HttpMethod getMethod() {
return this.method;
}

@Override
public URI getURI() {
return this.uri;
}


@Override
protected ClientHttpResponse executeInternal(HttpHeaders headers, byte[] content) throws IOException {
Request request = OkHttp3ClientHttpRequestFactory.buildRequest(headers, content, this.uri, this.method);
return new OkHttp3ClientHttpResponse(this.client.newCall(request).execute());
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
/*
* Copyright 2002-2016 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.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.springframework.http.client;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;

import org.springframework.beans.factory.DisposableBean;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

/**
* {@link ClientHttpRequestFactory} implementation that uses
* <a href="http://square.github.io/okhttp/">OkHttp</a> 3.x to create requests.
*
* @author Luciano Leggieri
* @author Arjen Poutsma
* @author Roy Clarkson
* @since 4.3
*/
public class OkHttp3ClientHttpRequestFactory
implements ClientHttpRequestFactory, AsyncClientHttpRequestFactory, DisposableBean {

private OkHttpClient client;

private final boolean defaultClient;


/**
* Create a factory with a default {@link OkHttpClient} instance.
*/
public OkHttp3ClientHttpRequestFactory() {
this.client = new OkHttpClient();
this.defaultClient = true;
}

/**
* Create a factory with the given {@link OkHttpClient} instance.
* @param client the client to use
*/
public OkHttp3ClientHttpRequestFactory(OkHttpClient client) {
Assert.notNull(client, "OkHttpClient must not be null");
this.client = client;
this.defaultClient = false;
}


/**
* Sets the underlying read timeout in milliseconds.
* A value of 0 specifies an infinite timeout.
* @see okhttp3.OkHttpClient.Builder#readTimeout(long, TimeUnit)
*/
public void setReadTimeout(int readTimeout) {
this.client = this.client.newBuilder()
.readTimeout(readTimeout, TimeUnit.MILLISECONDS)
.build();
}

/**
* Sets the underlying write timeout in milliseconds.
* A value of 0 specifies an infinite timeout.
* @see okhttp3.OkHttpClient.Builder#writeTimeout(long, TimeUnit)
*/
public void setWriteTimeout(int writeTimeout) {
this.client = this.client.newBuilder()
.writeTimeout(writeTimeout, TimeUnit.MILLISECONDS)
.build();
}

/**
* Sets the underlying connect timeout in milliseconds.
* A value of 0 specifies an infinite timeout.
* @see okhttp3.OkHttpClient.Builder#connectTimeout(long, TimeUnit)
*/
public void setConnectTimeout(int connectTimeout) {
this.client = this.client.newBuilder()
.connectTimeout(connectTimeout, TimeUnit.MILLISECONDS)
.build();
}


@Override
public ClientHttpRequest createRequest(URI uri, HttpMethod httpMethod) {
return new OkHttp3ClientHttpRequest(this.client, uri, httpMethod);
}

@Override
public AsyncClientHttpRequest createAsyncRequest(URI uri, HttpMethod httpMethod) {
return new OkHttp3AsyncClientHttpRequest(this.client, uri, httpMethod);
}


@Override
public void destroy() throws IOException {
if (this.defaultClient) {
// Clean up the client if we created it in the constructor
if (this.client.cache() != null) {
this.client.cache().close();
}
this.client.dispatcher().executorService().shutdown();
}
}


static Request buildRequest(HttpHeaders headers, byte[] content, URI uri,
HttpMethod method) throws MalformedURLException {

okhttp3.MediaType contentType = getContentType(headers);
RequestBody body = (content.length > 0 ? RequestBody.create(contentType, content) : null);

URL url = uri.toURL();
String methodName = method.name();
Request.Builder builder = new Request.Builder().url(url).method(methodName, body);

for (Map.Entry<String, List<String>> entry : headers.entrySet()) {
String headerName = entry.getKey();
for (String headerValue : entry.getValue()) {
builder.addHeader(headerName, headerValue);
}
}

return builder.build();
}

private static okhttp3.MediaType getContentType(HttpHeaders headers) {
String rawContentType = headers.getFirst(HttpHeaders.CONTENT_TYPE);
return (StringUtils.hasText(rawContentType) ? okhttp3.MediaType.parse(rawContentType) : null);
}

}
Loading