View difference between Paste ID: ZGY25cq4 and
SHOW:
|
|
- or go back to the newest paste.
1 | - | |
1 | + | |
2 | import groovyx.net.http.HTTPBuilder; | |
3 | ||
4 | import java.io.IOException; | |
5 | import java.net.URISyntaxException; | |
6 | import java.util.HashMap; | |
7 | import java.util.Map; | |
8 | ||
9 | import org.apache.http.client.ClientProtocolException; | |
10 | import org.scribe.http.Request; | |
11 | import org.scribe.http.Request.Verb; | |
12 | import org.scribe.oauth.Scribe; | |
13 | import org.scribe.oauth.Token; | |
14 | ||
15 | /** | |
16 | * Adds OAuth Consumer support to HttpBuilder using Pablo Fernandez's Scribe | |
17 | * library (http://github.com/fernandezpablo85/scribe). | |
18 | * | |
19 | * Instantiate your own Scribe and pass it to the <code>create</code> factory | |
20 | * method. Provide an <code>accessToken</code> parameter in the | |
21 | * <code>args</code> map of each request or use <code>setAccessToken</code> to | |
22 | * use the same one repeatedly. | |
23 | * | |
24 | * Example: <code> | |
25 | * def serviceProps = new Properties([ "consumer.key" : "myApiToken", | |
26 | * "consumer.secret" : "myApiSecret" ]) | |
27 | * | |
28 | * def scribe = new Scribe(serviceProps) | |
29 | * | |
30 | * //Use Scribe as described on its github to get the request and access | |
31 | * //tokens. We'll pretend we just have one. | |
32 | * | |
33 | * def access = new Token("theAccessToken","andItsSecret") | |
34 | * | |
35 | * def http = OAuthHttpBuilder.create( | |
36 | * "http://www.twitter.com/oauth/some_resource", | |
37 | * scribe | |
38 | * ); | |
39 | * | |
40 | * http.get( query : [ arg1 : "value1", arg2 : "value2" ], | |
41 | * accessToken: access ); | |
42 | * </code> | |
43 | * | |
44 | * @author Erem Boto | |
45 | */ | |
46 | @SuppressWarnings("unchecked") | |
47 | public class OAuthHttpBuilder { | |
48 | private final Scribe signer; | |
49 | private final HTTPBuilder delegate; | |
50 | private Token defaultAccessToken = null; | |
51 | ||
52 | ||
53 | /* | |
54 | * Class provision | |
55 | */ | |
56 | public static OAuthHttpBuilder create( Object defaultUri, | |
57 | Object defaultContentType, | |
58 | Scribe signer ) throws URISyntaxException { | |
59 | return new OAuthHttpBuilder( | |
60 | new HTTPBuilder(defaultUri, defaultContentType), signer); | |
61 | } | |
62 | ||
63 | public static OAuthHttpBuilder create( Object defaultUri, | |
64 | Scribe signer ) | |
65 | throws URISyntaxException { | |
66 | return new OAuthHttpBuilder(new HTTPBuilder(defaultUri), signer); | |
67 | } | |
68 | ||
69 | public OAuthHttpBuilder(HTTPBuilder delegate, Scribe signer) { | |
70 | this.signer = signer; | |
71 | this.delegate = delegate; | |
72 | } | |
73 | ||
74 | /* | |
75 | * Public Methods | |
76 | */ | |
77 | /** | |
78 | * Sets the default access token to use when making OAuth requests. | |
79 | * | |
80 | * @param token | |
81 | */ | |
82 | public void setAccessToken(Token token) { | |
83 | this.defaultAccessToken = token; | |
84 | } | |
85 | ||
86 | /* | |
87 | * Wrapped HttpBuilder Methods | |
88 | */ | |
89 | public Object get(Map<String, ?> args) | |
90 | throws ClientProtocolException, IOException, URISyntaxException { | |
91 | preProcessArgsHeader(Verb.GET, args); | |
92 | return delegate.get(args); | |
93 | } | |
94 | ||
95 | public Object post(Map<String, ?> args) | |
96 | throws ClientProtocolException, URISyntaxException, IOException { | |
97 | preProcessArgsHeader(Verb.POST, args); | |
98 | return delegate.post(args); | |
99 | } | |
100 | ||
101 | ||
102 | /* | |
103 | * Private Methods | |
104 | */ | |
105 | /** | |
106 | * Uses provided "accessToken" and "uri" parameters to construct an | |
107 | * Authorization header with Scribe. | |
108 | * | |
109 | * @param method | |
110 | * the request's HTTP method | |
111 | * @param args | |
112 | * the argument map as passed to get() or post() | |
113 | */ | |
114 | public void preProcessArgsHeader(Verb method, Map<String, ?> args) { | |
115 | Token accessToken = accessTokenFromArgs(args); | |
116 | String uriParam = uriParamFromArgs(args); | |
117 | ||
118 | // God knows what happens if they aren't strings. | |
119 | Map<String, String> query = (Map<String, String>) args.get("query"); | |
120 | ||
121 | Object bodyParams = args.get("body"); | |
122 | ||
123 | // because we're using one map, the request won't be to spec if you have | |
124 | // repeated query parameters =( | |
125 | Map oauthParams = new HashMap(); | |
126 | if (query != null) { | |
127 | oauthParams.putAll(query); | |
128 | } | |
129 | ||
130 | boolean shouldPutBody = (method == Verb.POST && bodyParams instanceof Map); | |
131 | if (shouldPutBody) { | |
132 | oauthParams.putAll((Map<String, String>) bodyParams); | |
133 | } | |
134 | ||
135 | String authHeader = makeAuthHeader( method, | |
136 | uriParam, | |
137 | accessToken, | |
138 | oauthParams ); | |
139 | addAuthorizationHeader(authHeader, args); | |
140 | } | |
141 | ||
142 | /** | |
143 | * Grabs the Scribe access token from the provided arguments, or returns the | |
144 | * default token. | |
145 | * | |
146 | * @param args | |
147 | * the arguments passed to either get or post. | |
148 | * @return the accessToken that was provided | |
149 | * @throws IllegalStateException | |
150 | * when the accessToken parameter is not provided and no default | |
151 | * accessToken was available. | |
152 | */ | |
153 | private Token accessTokenFromArgs(Map args) throws IllegalStateException { | |
154 | Token accessToken = (Token) args.get("accessToken"); | |
155 | if (accessToken == null) { | |
156 | accessToken = defaultAccessToken; | |
157 | } | |
158 | if (accessToken == null) { | |
159 | accessToken = new Token("", ""); | |
160 | } | |
161 | return accessToken; | |
162 | } | |
163 | ||
164 | /** | |
165 | * Grabs the uri from the provided argument map, or returns the default URI. | |
166 | * | |
167 | * @param args | |
168 | * the arguments passed to either get or post | |
169 | * @return the provided uri | |
170 | * @throws IllegalStateException | |
171 | * when the 'uri' parameters is not provided and no default uri was | |
172 | * available. | |
173 | */ | |
174 | private String uriParamFromArgs(Map args) throws IllegalStateException { | |
175 | String uriParam = (String) args.get("uri"); | |
176 | ||
177 | if (uriParam == null) { | |
178 | uriParam = delegate.getUri().toString(); | |
179 | } | |
180 | if (uriParam == null) { | |
181 | throw new IllegalStateException( | |
182 | "Default URI is null and no 'uri' parameter was provided" | |
183 | ); | |
184 | } | |
185 | return uriParam; | |
186 | } | |
187 | ||
188 | /** | |
189 | * Adds the OAuth Authorization header to the wrapped HTTPBuilder. | |
190 | * | |
191 | * @param authHeader | |
192 | * the authorization header value | |
193 | * @param args | |
194 | * the map of arguments passed to post/get | |
195 | */ | |
196 | private void addAuthorizationHeader(String authHeader, Map args) { | |
197 | Map headers = (Map) args.get("headers"); | |
198 | if (headers == null) { | |
199 | headers = new HashMap<String, String>(); | |
200 | args.put("headers", headers); | |
201 | } | |
202 | headers.put("Authorization", authHeader); | |
203 | } | |
204 | ||
205 | /** | |
206 | * Constructs the authorization header from OAuth parameters. | |
207 | * | |
208 | * @param method | |
209 | * the request's HTTP method | |
210 | * @param uri | |
211 | * the request's URI | |
212 | * @param accessToken | |
213 | * the token for signing: can be access token or request token. | |
214 | * @param queryOrBodyParams | |
215 | * the DECODED parameters for oauth to sign. With GET these are the | |
216 | * query parameters. With POST both query parameters and body | |
217 | * parameters (if this is a form-encoded request). | |
218 | * @return the signed OAuth "Authorization" header. | |
219 | */ | |
220 | private String makeAuthHeader( Verb method, | |
221 | String uri, | |
222 | Token | |
223 | accessToken, | |
224 | Map<String, ?> queryOrBodyParams ) { | |
225 | CustomRequest req = new CustomRequest(method, uri); | |
226 | for (Map.Entry param : queryOrBodyParams.entrySet()) { | |
227 | req.addBodyParameter( (String) param.getKey(), | |
228 | param.getValue().toString() ); | |
229 | } | |
230 | signer.signRequest(req, accessToken); | |
231 | return req.authorization; | |
232 | } | |
233 | ||
234 | /** | |
235 | * Custom Scribe Request subclass gives us access to the Authorization header | |
236 | * when Scribe sets it. | |
237 | */ | |
238 | protected static class CustomRequest extends Request { | |
239 | public CustomRequest(Verb verb, String url) { | |
240 | super(verb, url); | |
241 | } | |
242 | ||
243 | public String authorization = null; | |
244 | ||
245 | @Override | |
246 | public void addHeader(String key, String value) { | |
247 | if ("Authorization".equals(key)) { | |
248 | authorization = value; | |
249 | } | |
250 | super.addHeader(key, value); | |
251 | } | |
252 | } | |
253 | } |