From 0c26271dcbbc8986526baeb2532bd5607635a4cc Mon Sep 17 00:00:00 2001 From: Peter Wu Date: Wed, 30 Apr 2014 10:08:29 +0200 Subject: Move classes not related to mining to io package --- src/io/BearerRequester.java | 92 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 src/io/BearerRequester.java (limited to 'src/io/BearerRequester.java') diff --git a/src/io/BearerRequester.java b/src/io/BearerRequester.java new file mode 100644 index 0000000..4cb554b --- /dev/null +++ b/src/io/BearerRequester.java @@ -0,0 +1,92 @@ +package io; + +import java.io.IOException; +import java.net.HttpURLConnection; +import java.net.URL; +import java.net.URLConnection; +import org.apache.commons.io.Charsets; +import org.json.JSONException; +import org.json.JSONObject; +import support.ConsumerKeySecret; + +/** + * An API requester used for application-only requests. Not all requests are + * allowed, see https://dev.twitter.com/docs/auth/application-only-auth for + * details. + * + * @author Peter Wu + */ +public class BearerRequester extends AbstractRequester { + + /** + * A base64-encoded access token that authenticates requests. + */ + private final String access_token; + + /** + * Instantiates a requester with the given access token. The caller should + * test the token for validity. + * + * @param access_token The bearer token that authenticates a request. + */ + public BearerRequester(String access_token) { + this.access_token = access_token; + } + + /** + * Instantiates an instance, requesting an access token from the provided + * consumer key and secret. + * + * @param secrets The consumer secrets provided by Twitter. + * @throws IOException if a failure occurred while acquiring a token. + */ + public BearerRequester(ConsumerKeySecret secrets) + throws IOException { + String postData = "grant_type=client_credentials"; + URL url = buildUrl("oauth2/token"); + HttpURLConnection conn = open(url); + conn.setRequestMethod("POST"); + // set request headers + conn.addRequestProperty("Authorization", "Basic " + + secrets.getBearerTokenBase64()); + conn.addRequestProperty("Content-Type", + "application/x-www-form-urlencoded; charset=UTF-8"); + conn.setFixedLengthStreamingMode(postData.length()); + // connect and send request + conn.setDoOutput(true); + conn.getOutputStream().write(postData.getBytes(Charsets.UTF_8)); + + try { + JSONObject resp = getResponseAsJson(conn); + // TODO: parse resp.errors + if (!resp.getString("token_type").equals("bearer")) { + throw new IOException("Expected bearer token type"); + } + access_token = resp.getString("access_token"); + } catch (JSONException ex) { + // treat JSON errors as if an I/O error occurred + throw new IOException(ex); + } + } + + @Override + protected void preconnect(URLConnection conn) throws IOException { + // requests do not have to be signed, instead rely on the Bearer token + conn.addRequestProperty("Authorization", "Bearer " + access_token); + } + + /** + * @return the access token that authenticates requests. + */ + public String getAccessToken() { + return access_token; + } + + @Override + public boolean isValid() throws IOException { + // NOTE: this actually contributes to the ratelimit (12/minute) + // TODO: find alternative that does not hit the ratelimit + JSONObject obj = getJSONRelax("application/rate_limit_status"); + return !obj.has("errors"); + } +} -- cgit v1.2.1