Skip to content

Commit 010b37a

Browse files
committed
make http async client implementation be more pluggable
1 parent 9a83b6c commit 010b37a

File tree

8 files changed

+110
-134
lines changed

8 files changed

+110
-134
lines changed

changelog

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
[SNAPSHOT]
2+
* make http async client implementation be more pluggable
3+
14
[2.6.0]
25
* simplify async/sync usages
36
* add optional "User-Agent" config option to use while making http calls
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
package com.github.scribejava.core.async.ning;
2+
3+
import com.github.scribejava.core.model.OAuthAsyncRequestCallback;
4+
import com.github.scribejava.core.model.OAuthRequestAsync;
5+
import com.github.scribejava.core.model.Response;
6+
import com.ning.http.client.AsyncCompletionHandler;
7+
import com.ning.http.client.FluentCaseInsensitiveStringsMap;
8+
import java.io.IOException;
9+
import java.util.HashMap;
10+
import java.util.List;
11+
import java.util.Map;
12+
13+
public class OAuthAsyncCompletionHandler<T> extends AsyncCompletionHandler<T> {
14+
15+
private final OAuthAsyncRequestCallback<T> callback;
16+
private final OAuthRequestAsync.ResponseConverter<T> converter;
17+
18+
public OAuthAsyncCompletionHandler(OAuthAsyncRequestCallback<T> callback,
19+
OAuthRequestAsync.ResponseConverter<T> converter) {
20+
this.callback = callback;
21+
this.converter = converter;
22+
}
23+
24+
@Override
25+
public T onCompleted(com.ning.http.client.Response ningResponse) throws IOException {
26+
final FluentCaseInsensitiveStringsMap map = ningResponse.getHeaders();
27+
final Map<String, String> headersMap = new HashMap<>();
28+
for (FluentCaseInsensitiveStringsMap.Entry<String, List<String>> header : map) {
29+
final StringBuilder value = new StringBuilder();
30+
for (String str : header.getValue()) {
31+
value.append(str);
32+
}
33+
headersMap.put(header.getKey(), value.toString());
34+
}
35+
final Response response = new Response(ningResponse.getStatusCode(), ningResponse.getStatusText(), headersMap,
36+
ningResponse.getResponseBody(), ningResponse.getResponseBodyAsStream());
37+
38+
@SuppressWarnings("unchecked")
39+
final T t = converter == null ? (T) response : converter.convert(response);
40+
if (callback != null) {
41+
callback.onCompleted(t);
42+
}
43+
return t;
44+
}
45+
46+
@Override
47+
public void onThrowable(Throwable t) {
48+
if (callback != null) {
49+
callback.onThrowable(t);
50+
}
51+
}
52+
};

scribejava-core/src/main/java/com/github/scribejava/core/model/AbstractRequest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@
1515
public abstract class AbstractRequest {
1616

1717
public static final String DEFAULT_CONTENT_TYPE = "application/x-www-form-urlencoded";
18+
public static final String CONTENT_TYPE = "Content-Type";
1819
protected static final String CONTENT_LENGTH = "Content-Length";
19-
protected static final String CONTENT_TYPE = "Content-Type";
2020
private static final String OAUTH_PREFIX = "oauth_";
2121

2222
private final String url;

scribejava-core/src/main/java/com/github/scribejava/core/model/OAuthRequestAsync.java

Lines changed: 3 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -2,46 +2,17 @@
22

33
import com.github.scribejava.core.exceptions.OAuthException;
44
import com.github.scribejava.core.oauth.OAuthService;
5-
import com.ning.http.client.AsyncCompletionHandler;
6-
import com.ning.http.client.AsyncHttpClient;
7-
import com.ning.http.client.FluentCaseInsensitiveStringsMap;
8-
import com.ning.http.client.ProxyServer;
95

106
import java.io.IOException;
11-
import java.util.HashMap;
12-
import java.util.List;
13-
import java.util.Map;
147
import java.util.concurrent.Future;
158

169
public class OAuthRequestAsync extends AbstractRequest {
1710

18-
public static final ResponseConverter<Response> RESPONSE_CONVERTER = new ResponseConverter<Response>() {
19-
@Override
20-
public Response convert(com.ning.http.client.Response response) throws IOException {
21-
final FluentCaseInsensitiveStringsMap map = response.getHeaders();
22-
final Map<String, String> headersMap = new HashMap<>();
23-
for (FluentCaseInsensitiveStringsMap.Entry<String, List<String>> header : map) {
24-
final StringBuilder value = new StringBuilder();
25-
for (String str : header.getValue()) {
26-
value.append(str);
27-
}
28-
headersMap.put(header.getKey(), value.toString());
29-
}
30-
return new Response(response.getStatusCode(), response.getStatusText(), headersMap,
31-
response.getResponseBody(), response.getResponseBodyAsStream());
32-
}
33-
};
34-
3511
public OAuthRequestAsync(Verb verb, String url, OAuthService service) {
3612
super(verb, url, service);
3713
}
3814

3915
public <T> Future<T> sendAsync(OAuthAsyncRequestCallback<T> callback, ResponseConverter<T> converter) {
40-
return sendAsync(callback, converter, null);
41-
}
42-
43-
public <T> Future<T> sendAsync(OAuthAsyncRequestCallback<T> callback, ResponseConverter<T> converter,
44-
ProxyServer proxyServer) {
4516
final ForceTypeOfHttpRequest forceTypeOfHttpRequest = ScribeJavaConfig.getForceTypeOfHttpRequests();
4617
if (ForceTypeOfHttpRequest.FORCE_SYNC_ONLY_HTTP_REQUESTS == forceTypeOfHttpRequest) {
4718
throw new OAuthException("Cannot use async operations, only sync");
@@ -51,76 +22,15 @@ public <T> Future<T> sendAsync(OAuthAsyncRequestCallback<T> callback, ResponseCo
5122
if (ForceTypeOfHttpRequest.PREFER_SYNC_ONLY_HTTP_REQUESTS == forceTypeOfHttpRequest) {
5223
config.log("Cannot use async operations, only sync");
5324
}
54-
final String completeUrl = getCompleteUrl();
55-
final AsyncHttpClient.BoundRequestBuilder boundRequestBuilder;
56-
final AsyncHttpClient asyncHttpClient = service.getAsyncHttpClient();
57-
final Map<String, String> headers = getHeaders();
58-
switch (getVerb()) {
59-
case GET:
60-
boundRequestBuilder = asyncHttpClient.prepareGet(completeUrl);
61-
break;
62-
case POST:
63-
AsyncHttpClient.BoundRequestBuilder requestBuilder = asyncHttpClient.preparePost(completeUrl);
64-
if (!headers.containsKey(CONTENT_TYPE)) {
65-
requestBuilder = requestBuilder.addHeader(CONTENT_TYPE, DEFAULT_CONTENT_TYPE);
66-
}
67-
boundRequestBuilder = requestBuilder.setBody(getBodyContents());
68-
break;
69-
default:
70-
throw new IllegalArgumentException("message build error: unknown verb type");
71-
}
72-
73-
for (Map.Entry<String, String> header : headers.entrySet()) {
74-
boundRequestBuilder.addHeader(header.getKey(), header.getValue());
75-
}
76-
final String userAgent = config.getUserAgent();
77-
if (userAgent != null) {
78-
boundRequestBuilder.setHeader(OAuthConstants.USER_AGENT_HEADER_NAME, userAgent);
79-
}
80-
81-
if (proxyServer != null) {
82-
boundRequestBuilder.setProxyServer(proxyServer);
83-
}
84-
return boundRequestBuilder.execute(new OAuthAsyncCompletionHandler<>(callback, converter));
25+
return service.executeAsync(getHeaders(), getVerb(), getCompleteUrl(), getBodyContents(), callback, converter);
8526
}
8627

87-
private static class OAuthAsyncCompletionHandler<T> extends AsyncCompletionHandler<T> {
88-
89-
private final OAuthAsyncRequestCallback<T> callback;
90-
private final ResponseConverter<T> converter;
91-
92-
OAuthAsyncCompletionHandler(OAuthAsyncRequestCallback<T> callback, ResponseConverter<T> converter) {
93-
this.callback = callback;
94-
this.converter = converter;
95-
}
96-
97-
@Override
98-
public T onCompleted(com.ning.http.client.Response response) throws IOException {
99-
final T t = converter.convert(response);
100-
if (callback != null) {
101-
callback.onCompleted(t);
102-
}
103-
return t;
104-
}
105-
106-
@Override
107-
public void onThrowable(Throwable t) {
108-
if (callback != null) {
109-
callback.onThrowable(t);
110-
}
111-
}
112-
};
113-
11428
public Future<Response> sendAsync(OAuthAsyncRequestCallback<Response> callback) {
115-
return sendAsync(callback, RESPONSE_CONVERTER, null);
116-
}
117-
118-
public Future<Response> sendAsync(OAuthAsyncRequestCallback<Response> callback, ProxyServer proxyServer) {
119-
return sendAsync(callback, RESPONSE_CONVERTER, proxyServer);
29+
return sendAsync(callback, null);
12030
}
12131

12232
public interface ResponseConverter<T> {
12333

124-
T convert(com.ning.http.client.Response response) throws IOException;
34+
T convert(Response response) throws IOException;
12535
}
12636
}

scribejava-core/src/main/java/com/github/scribejava/core/oauth/OAuth10aService.java

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package com.github.scribejava.core.oauth;
22

3-
import com.ning.http.client.ProxyServer;
43
import java.io.IOException;
54
import java.util.Map;
65
import java.util.concurrent.Future;
@@ -96,23 +95,17 @@ public final OAuth1AccessToken getAccessToken(OAuth1RequestToken requestToken, S
9695
*/
9796
public final Future<OAuth1AccessToken> getAccessTokenAsync(OAuth1RequestToken requestToken, String oauthVerifier,
9897
OAuthAsyncRequestCallback<OAuth1AccessToken> callback) {
99-
return getAccessTokenAsync(requestToken, oauthVerifier, callback, null);
100-
}
101-
102-
public final Future<OAuth1AccessToken> getAccessTokenAsync(OAuth1RequestToken requestToken, String oauthVerifier,
103-
OAuthAsyncRequestCallback<OAuth1AccessToken> callback, ProxyServer proxyServer) {
10498
final OAuthConfig config = getConfig();
10599
config.log("async obtaining access token from " + api.getAccessTokenEndpoint());
106100
final OAuthRequestAsync request
107101
= new OAuthRequestAsync(api.getAccessTokenVerb(), api.getAccessTokenEndpoint(), this);
108102
prepareAccessTokenRequest(request, requestToken, oauthVerifier);
109103
return request.sendAsync(callback, new OAuthRequestAsync.ResponseConverter<OAuth1AccessToken>() {
110104
@Override
111-
public OAuth1AccessToken convert(com.ning.http.client.Response response) throws IOException {
112-
return getApi().getAccessTokenExtractor()
113-
.extract(OAuthRequestAsync.RESPONSE_CONVERTER.convert(response).getBody());
105+
public OAuth1AccessToken convert(Response response) throws IOException {
106+
return getApi().getAccessTokenExtractor().extract(response.getBody());
114107
}
115-
}, proxyServer);
108+
});
116109
}
117110

118111
protected void prepareAccessTokenRequest(AbstractRequest request, OAuth1RequestToken requestToken,

scribejava-core/src/main/java/com/github/scribejava/core/oauth/OAuth20Service.java

Lines changed: 8 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package com.github.scribejava.core.oauth;
22

33
import com.github.scribejava.core.services.Base64Encoder;
4-
import com.ning.http.client.ProxyServer;
54
import java.io.IOException;
65
import java.nio.charset.Charset;
76
import java.util.concurrent.Future;
@@ -14,6 +13,7 @@
1413
import com.github.scribejava.core.model.OAuthConstants;
1514
import com.github.scribejava.core.model.OAuthRequest;
1615
import com.github.scribejava.core.model.OAuthRequestAsync;
16+
import com.github.scribejava.core.model.Response;
1717
import java.util.Map;
1818

1919
public class OAuth20Service extends OAuthService {
@@ -39,15 +39,14 @@ protected OAuth2AccessToken sendAccessTokenRequestSync(OAuthRequest request) {
3939

4040
//async version, protected to facilitate mocking
4141
protected Future<OAuth2AccessToken> sendAccessTokenRequestAsync(OAuthRequestAsync request,
42-
OAuthAsyncRequestCallback<OAuth2AccessToken> callback, ProxyServer proxyServer) {
42+
OAuthAsyncRequestCallback<OAuth2AccessToken> callback) {
4343

4444
return request.sendAsync(callback, new OAuthRequestAsync.ResponseConverter<OAuth2AccessToken>() {
4545
@Override
46-
public OAuth2AccessToken convert(com.ning.http.client.Response response) throws IOException {
47-
return getApi().getAccessTokenExtractor()
48-
.extract(OAuthRequestAsync.RESPONSE_CONVERTER.convert(response).getBody());
46+
public OAuth2AccessToken convert(Response response) throws IOException {
47+
return getApi().getAccessTokenExtractor().extract(response.getBody());
4948
}
50-
}, proxyServer);
49+
});
5150
}
5251

5352
public final OAuth2AccessToken getAccessToken(String code) {
@@ -67,15 +66,10 @@ public final OAuth2AccessToken getAccessToken(String code) {
6766
*/
6867
public final Future<OAuth2AccessToken> getAccessTokenAsync(String code,
6968
OAuthAsyncRequestCallback<OAuth2AccessToken> callback) {
70-
return getAccessTokenAsync(code, callback, null);
71-
}
72-
73-
public final Future<OAuth2AccessToken> getAccessTokenAsync(String code,
74-
OAuthAsyncRequestCallback<OAuth2AccessToken> callback, ProxyServer proxyServer) {
7569
final OAuthRequestAsync request = createAccessTokenRequest(code,
7670
new OAuthRequestAsync(api.getAccessTokenVerb(), api.getAccessTokenEndpoint(), this));
7771

78-
return sendAccessTokenRequestAsync(request, callback, proxyServer);
72+
return sendAccessTokenRequestAsync(request, callback);
7973
}
8074

8175
protected <T extends AbstractRequest> T createAccessTokenRequest(String code, T request) {
@@ -101,15 +95,10 @@ public final OAuth2AccessToken refreshAccessToken(String refreshToken) {
10195

10296
public final Future<OAuth2AccessToken> refreshAccessTokenAsync(String refreshToken,
10397
OAuthAsyncRequestCallback<OAuth2AccessToken> callback) {
104-
return refreshAccessTokenAsync(refreshToken, callback, null);
105-
}
106-
107-
public final Future<OAuth2AccessToken> refreshAccessTokenAsync(String refreshToken,
108-
OAuthAsyncRequestCallback<OAuth2AccessToken> callback, ProxyServer proxyServer) {
10998
final OAuthRequestAsync request = createRefreshTokenRequest(refreshToken,
11099
new OAuthRequestAsync(api.getAccessTokenVerb(), api.getRefreshTokenEndpoint(), this));
111100

112-
return sendAccessTokenRequestAsync(request, callback, proxyServer);
101+
return sendAccessTokenRequestAsync(request, callback);
113102
}
114103

115104
protected <T extends AbstractRequest> T createRefreshTokenRequest(String refreshToken, T request) {
@@ -148,15 +137,10 @@ public final OAuth2AccessToken getAccessTokenPasswordGrant(String uname, String
148137
*/
149138
public final Future<OAuth2AccessToken> getAccessTokenPasswordGrantAsync(String uname, String password,
150139
OAuthAsyncRequestCallback<OAuth2AccessToken> callback) {
151-
return getAccessTokenPasswordGrantAsync(uname, password, callback, null);
152-
}
153-
154-
public final Future<OAuth2AccessToken> getAccessTokenPasswordGrantAsync(String uname, String password,
155-
OAuthAsyncRequestCallback<OAuth2AccessToken> callback, ProxyServer proxyServer) {
156140
final OAuthRequestAsync request = createAccessTokenPasswordGrantRequest(uname, password,
157141
new OAuthRequestAsync(api.getAccessTokenVerb(), api.getAccessTokenEndpoint(), this));
158142

159-
return sendAccessTokenRequestAsync(request, callback, proxyServer);
143+
return sendAccessTokenRequestAsync(request, callback);
160144
}
161145

162146
protected <T extends AbstractRequest> T createAccessTokenPasswordGrantRequest(String username, String password,

scribejava-core/src/main/java/com/github/scribejava/core/oauth/OAuthService.java

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,20 @@
11
package com.github.scribejava.core.oauth;
22

3+
import com.github.scribejava.core.async.ning.OAuthAsyncCompletionHandler;
34
import com.ning.http.client.AsyncHttpClient;
45
import com.github.scribejava.core.exceptions.OAuthException;
6+
import com.github.scribejava.core.model.AbstractRequest;
7+
import static com.github.scribejava.core.model.AbstractRequest.DEFAULT_CONTENT_TYPE;
58
import com.github.scribejava.core.model.ForceTypeOfHttpRequest;
9+
import com.github.scribejava.core.model.OAuthAsyncRequestCallback;
610
import com.github.scribejava.core.model.OAuthConfig;
11+
import com.github.scribejava.core.model.OAuthConstants;
12+
import com.github.scribejava.core.model.OAuthRequestAsync;
713
import com.github.scribejava.core.model.ScribeJavaConfig;
14+
import com.github.scribejava.core.model.Verb;
815
import com.ning.http.client.AsyncHttpClientConfig;
16+
import java.util.Map;
17+
import java.util.concurrent.Future;
918

1019
/**
1120
* The main ScribeJava object.
@@ -43,10 +52,6 @@ public OAuthService(OAuthConfig config) {
4352
}
4453
}
4554

46-
public AsyncHttpClient getAsyncHttpClient() {
47-
return asyncHttpClient;
48-
}
49-
5055
public void closeAsyncClient() {
5156
asyncHttpClient.close();
5257
}
@@ -61,4 +66,34 @@ public OAuthConfig getConfig() {
6166
* @return OAuth version as string
6267
*/
6368
public abstract String getVersion();
69+
70+
public <T> Future<T> executeAsync(Map<String, String> headers, Verb httpVerb, String completeUrl,
71+
String bodyContents, OAuthAsyncRequestCallback<T> callback,
72+
OAuthRequestAsync.ResponseConverter<T> converter) {
73+
final AsyncHttpClient.BoundRequestBuilder boundRequestBuilder;
74+
switch (httpVerb) {
75+
case GET:
76+
boundRequestBuilder = asyncHttpClient.prepareGet(completeUrl);
77+
break;
78+
case POST:
79+
AsyncHttpClient.BoundRequestBuilder requestBuilder = asyncHttpClient.preparePost(completeUrl);
80+
if (!headers.containsKey(AbstractRequest.CONTENT_TYPE)) {
81+
requestBuilder = requestBuilder.addHeader(AbstractRequest.CONTENT_TYPE, DEFAULT_CONTENT_TYPE);
82+
}
83+
boundRequestBuilder = requestBuilder.setBody(bodyContents);
84+
break;
85+
default:
86+
throw new IllegalArgumentException("message build error: unknown verb type");
87+
}
88+
89+
for (Map.Entry<String, String> header : headers.entrySet()) {
90+
boundRequestBuilder.addHeader(header.getKey(), header.getValue());
91+
}
92+
final String userAgent = config.getUserAgent();
93+
if (userAgent != null) {
94+
boundRequestBuilder.setHeader(OAuthConstants.USER_AGENT_HEADER_NAME, userAgent);
95+
}
96+
97+
return boundRequestBuilder.execute(new OAuthAsyncCompletionHandler<>(callback, converter));
98+
}
6499
}

0 commit comments

Comments
 (0)