All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.resthub.web.Client Maven / Gradle / Ivy

Go to download

RESThub webservice client for requesting REST webservices with JSON support bundled

The newest version!
package org.resthub.web;

import com.ning.http.client.*;
import com.ning.http.client.AsyncHttpClientConfig.Builder;
import com.ning.http.client.Realm.AuthScheme;
import com.ning.http.client.Realm.RealmBuilder;
import com.ning.http.client.cookie.Cookie;
import org.resthub.web.exception.ClientException;
import org.resthub.web.exception.ClientExceptionFactory;
import org.resthub.web.oauth2.OAuth2Config;
import org.resthub.web.oauth2.OAuth2RequestFilter;
import org.resthub.web.support.*;

import java.io.Closeable;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;

/**
 * RESThub AsyncHttpClient wrapper inspired from Play! Framework 2
*

* Sample usage: *

 Client httpClient = new Client();
 * User user = httpClient.url("http://localhost:8080/api/user").jsonPost(user).resource(User.class);
*/ public class Client implements Closeable { protected AsyncHttpClient client; protected Builder builder; protected OAuth2Config.Builder oAuth2ConfigBuilder; protected OAuth2Config oAuth2Config; protected List bodyReaders = new ArrayList(); protected List bodyWriters = new ArrayList(); private String username = null; private String password = null; private AuthScheme scheme = null; /** * Create an HTTP client with default configuration */ public Client() { this.builder = new Builder(); } /** * Create an HTTP client with a pre-configured Builder * * @see Builder */ public Client(Builder builder) { this.builder = builder; } /** * Return the AsyncHttpClient native client for advanced features */ public AsyncHttpClient getNativeClient() { return client; } /** * Set HTTP proxy configuration */ public Client setProxy(String host, int port) { this.builder.setProxyServer(new ProxyServer(host, port)); return this; } /** * Add a candidate BodyReader to read an HTTP response body to an object * * @param br a bodyreader * @see BodyReader */ public Client addBodyReader(BodyReader br) { this.bodyReaders.add(br); return this; } /** * Add a candidate BodyWriter to serialize an object to an HTTP response * body * * @param bw a bodywriter * @see BodyWriter */ public Client addBodyWriter(BodyWriter bw) { this.bodyWriters.add(bw); return this; } /** * Sets the authentication header for the current client. * * @param username username identifier * @param password user password * @param scheme authentication scheme */ public Client setAuth(String username, String password, AuthScheme scheme) { this.username = username; this.password = password; this.scheme = scheme; return this; } /** * Set the given OAuth2Config builder for this client. * This builder will create the actual OAuth2Config used * for all OAuth2 related features. * This HTTP Client wrapper already has methods (like setOAuth2()) that * set the OAuth2 configuration on the client. * * @param builder builder to set */ public Client setOAuth2Builder(OAuth2Config.Builder builder) { this.oAuth2ConfigBuilder = builder; return this; } /** * Sets the OAuth2 authentication header for the current client. * * @param username The user's login * @param password The user's password * @param accessTokenEndpoint URL of the OAuth2.0 access token endpoint * service * @param clientId id of the current application registered with the remote * OAuth2.0 provider * @param clientSecret secret of the current application registered with the * remote OAuth2.0 provider */ public Client setOAuth2(String username, String password, String accessTokenEndpoint, String clientId, String clientSecret) { if (null == oAuth2ConfigBuilder) { oAuth2ConfigBuilder = new OAuth2Config.Builder(); } oAuth2ConfigBuilder.setUsername(username).setPassword(password); oAuth2ConfigBuilder.setAccessTokenEndpoint(accessTokenEndpoint); oAuth2ConfigBuilder.setClientId(clientId).setClientSecret(clientSecret); return this; } /** * Prepare a new request. You can then construct it by chaining calls. * * @param url the URL to request */ public RequestHolder url(String url) { if (this.client == null) { this.client = buildClient(); } if (url.contains("?")) { throw new IllegalArgumentException("url should not contain query params; chain with setQueryParam() instead."); } this.bodyReaders.add(new JsonBodyReader()); this.bodyReaders.add(new XmlBodyReader()); this.bodyWriters.add(new JsonBodyWriter()); this.bodyWriters.add(new XmlBodyWriter()); return new RequestHolder(url); } @Override public void close() { if (client != null) { client.close(); } } private AsyncHttpClient buildClient() { if (oAuth2ConfigBuilder != null) { oAuth2Config = oAuth2ConfigBuilder.build(); // TODO create request+response filters in OAuth2Config // -> handle new endpoints, refresh tokens... OAuth2RequestFilter oauth2Filter = new OAuth2RequestFilter(oAuth2Config.getAccessTokenEndpoint(), oAuth2Config.getClientId(), oAuth2Config.getClientSecret()); oauth2Filter.setCredentials(oAuth2Config.getUsername(),oAuth2Config.getPassword()); oauth2Filter.setSchemeName(oAuth2Config.getOAuth2Scheme()); builder.addRequestFilter(oauth2Filter); } return new AsyncHttpClient(builder.build()); } /** * Provides the bridge between the wrapper and the underlying ning request */ public class Request extends RequestBuilderBase { public Request(String method) { super(Request.class, method, false); } private Request auth(String username, String password, AuthScheme scheme) { this.setRealm((new RealmBuilder()).setScheme(scheme).setPrincipal(username).setPassword(password) .setUsePreemptiveAuth(true).build()); return this; } private Future execute() { Future future = null; AsyncEntityHandler handler = new AsyncEntityHandler(); handler.setBodyReaders(bodyReaders); try { future = client.executeRequest(request, handler); } catch (IOException ex) { future.cancel(true); } return future; } } /** * provides the User facing API for building WS request. */ public class RequestHolder { private final String url; private Map> headers = new HashMap>(); private Map> queryParameters = new HashMap>(); private List cookies = new ArrayList(); private String body = null; // UTF-8 by default private String charset = "UTF-8"; public RequestHolder(String url) { this.url = url; } /** * Sets a header with the given name, this can be called repeatedly * * @param name header name to set * @param value header value to set * * @return the current {@code RequestHolder} instance */ public RequestHolder setHeader(String name, String value) { if (headers.containsKey(name)) { Collection values = headers.get(name); values.add(value); } else { List values = new ArrayList(); values.add(value); headers.put(name, values); } return this; } /** * Sets a query parameter with the given name,this can be called * repeatedly * * @param name parameter name to set * @param value parameter value to set * * @return the current {@code RequestHolder} instance */ public RequestHolder setQueryParameter(String name, String value) { if (queryParameters.containsKey(name)) { Collection values = queryParameters.get(name); values.add(value); } else { List values = new ArrayList(); values.add(value); queryParameters.put(name, values); } return this; } public RequestHolder setBodyEncoding(String charset) { this.charset = charset; return this; } /** * Adds a cookie * * @param cookie cookie object to add * * @return the current {@code RequestHolder} instance */ public RequestHolder addCookie(Cookie cookie) { cookies.add(cookie); return this; } /** * Perform a GET request asynchronously. */ public Future asyncGet() { return execute("GET"); } public Future asyncJsonGet() { this.setHeader(Http.ACCEPT, Http.JSON); return execute("GET"); } public Future asyncXmlGet() { this.setHeader(Http.ACCEPT, Http.XML); return execute("GET"); } /** * Perform a GET request synchronously. */ public Response get() { return executeSync("GET"); } public Response jsonGet() { this.setHeader(Http.ACCEPT, Http.JSON); return executeSync("GET"); } public Response xmlGet() { this.setHeader(Http.ACCEPT, Http.XML); return executeSync("GET"); } /** * Perform a POST request asynchronously. * * @param body represented as String */ public Future asyncPost(String body) { return executeString("POST", body); } public Future asyncPost() { return executeString("POST", this.body); } public Future asyncPost(InputStream body) { return executeIS("POST", body); } public Future asyncPost(File body) { return executeFile("POST", body); } public Future asyncJsonPost(Object o) { this.setHeader(Http.ACCEPT, Http.JSON); this.setHeader(Http.CONTENT_TYPE, Http.JSON); return executeString("POST", serialize(Http.JSON, o)); } public Future asyncXmlPost(Object o) { this.setHeader(Http.ACCEPT, Http.XML); this.setHeader(Http.CONTENT_TYPE, Http.XML); return executeString("POST", serialize(Http.XML, o)); } /** * Perform a POST request synchronously. * * @param body represented as String */ public Response post(String body) { return executeStringSync("POST", body); } public Response post() { return executeStringSync("POST", this.body); } public Response post(InputStream body) { return executeISSync("POST", body); } public Response post(File body) { return executeFileSync("POST", body); } public Response jsonPost(Object o) { this.setHeader(Http.ACCEPT, Http.JSON); this.setHeader(Http.CONTENT_TYPE, Http.JSON); return executeStringSync("POST", serialize(Http.JSON, o)); } public Response xmlPost(Object o) { this.setHeader(Http.ACCEPT, Http.XML); this.setHeader(Http.CONTENT_TYPE, Http.XML); return executeStringSync("POST", serialize(Http.XML, o)); } /** * Perform a PUT request asynchronously. * * @param body represented as String */ public Future asyncPut(String body) { return executeString("PUT", body); } public Future asyncPut(InputStream body) { return executeIS("PUT", body); } public Future asyncPut(File body) { return executeFile("PUT", body); } public Future asyncJsonPut(Object o) { this.setHeader(Http.ACCEPT, Http.JSON); this.setHeader(Http.CONTENT_TYPE, Http.JSON); return executeString("PUT", serialize(Http.JSON, o)); } public Future asyncXmlPut(Object o) { this.setHeader(Http.ACCEPT, Http.XML); this.setHeader(Http.CONTENT_TYPE, Http.XML); return executeString("PUT", serialize(Http.XML, o)); } /** * Perform a PUT request synchronously. * * @param body represented as String */ public Response put(String body) { return executeStringSync("PUT", body); } public Response put(InputStream body) { return executeISSync("PUT", body); } public Response put(File body) { return executeFileSync("PUT", body); } public Response jsonPut(Object o) { this.setHeader(Http.ACCEPT, Http.JSON); this.setHeader(Http.CONTENT_TYPE, Http.JSON); return executeStringSync("PUT", serialize(Http.JSON, o)); } public Response xmlPut(Object o) { this.setHeader(Http.ACCEPT, Http.XML); this.setHeader(Http.CONTENT_TYPE, Http.XML); return executeStringSync("PUT", serialize(Http.XML, o)); } /** * Perform a DELETE on the request asynchronously. */ public Future asyncDelete() { return execute("DELETE"); } public Response delete() { return executeSync("DELETE"); } /** * Perform a HEAD on the request asynchronously. */ public Future asyncHead() { return execute("HEAD"); } public Response head() { return executeSync("HEAD"); } /** * Perform a OPTION on the request asynchronously. */ public Future asyncOption() { return execute("OPTION"); } public Response option() { return executeSync("OPTION"); } private Response executeSync(String method) { Response response = null; try { response = this.execute(method).get(); } catch (InterruptedException e) { // throw server error exception, with cause. throw new ClientException(e); } catch (ExecutionException e) { // throw server error exception, with cause. throw new ClientException(e); } if (response.getStatus() >= 400) { throw ClientExceptionFactory.createHttpExceptionFromStatusCode(response.getStatus()); } return response; } private Future execute(String method) { Request req = new Request(method).setUrl(url).setHeaders(headers) .setQueryParameters(new FluentStringsMap(queryParameters)); if (username != null && password != null && scheme != null) { req.auth(username, password, scheme); } if (oAuth2Config != null && oAuth2Config.getAccessTokenEndpoint() != null) { req.setRealm(new Realm.RealmBuilder().setPrincipal(oAuth2Config.getUsername()).setPassword(oAuth2Config.getPassword()).build()); } addCookies(req); return req.execute(); } private Response executeStringSync(String method, String body) { Response response = null; try { response = this.executeString(method, body).get(); } catch (InterruptedException e) { // throw server error exception, with cause. throw new ClientException(e); } catch (ExecutionException e) { // throw server error exception, with cause. throw new ClientException(e); } if (response.getStatus() >= 400) { throw ClientExceptionFactory.createHttpExceptionFromStatusCode(response.getStatus()); } return response; } private Future executeString(String method, String body) { Request req = new Request(method).setBodyEncoding(charset).setBody(body).setUrl(url).setHeaders(headers) .setQueryParameters(new FluentStringsMap(queryParameters)); if (username != null && password != null && scheme != null) { req.auth(username, password, scheme); } addCookies(req); return req.execute(); } private Response executeISSync(String method, InputStream body) { Response response = null; try { response = this.executeIS(method, body).get(); } catch (InterruptedException e) { // throw server error exception, with cause. throw new ClientException(e); } catch (ExecutionException e) { // throw server error exception, with cause. throw new ClientException(e); } if (response.getStatus() >= 400) { throw ClientExceptionFactory.createHttpExceptionFromStatusCode(response.getStatus()); } return response; } private Future executeIS(String method, InputStream body) { Request req = new Request(method).setBodyEncoding(charset).setBody(body).setUrl(url).setHeaders(headers) .setQueryParameters(new FluentStringsMap(queryParameters)); if (username != null && password != null && scheme != null) { req.auth(username, password, scheme); } addCookies(req); return req.execute(); } private Response executeFileSync(String method, File body) { Response response = null; try { response = this.executeFile(method, body).get(); } catch (ExecutionException e) { // throw server error exception, with cause. throw new ClientException(e); } catch (InterruptedException e) { // throw server error exception, with cause. throw new ClientException(e); } if (response.getStatus() >= 400) { throw ClientExceptionFactory.createHttpExceptionFromStatusCode(response.getStatus()); } return response; } private Future executeFile(String method, File body) { Request req = new Request(method).setBodyEncoding(charset).setBody(body).setUrl(url).setHeaders(headers) .setQueryParameters(new FluentStringsMap(queryParameters)); if (username != null && password != null && scheme != null) { req.auth(username, password, scheme); } addCookies(req); return req.execute(); } private void addCookies(Request req) { for (Cookie cookie : cookies) { req.addCookie(cookie); } } private String serialize(String mediaType, Object o) { for (BodyWriter bw : bodyWriters) { if (bw.canWrite(mediaType)) { return bw.writeEntity(mediaType, o); } } throw new RuntimeException("cannot serialize request body for mediaType " + mediaType); } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy