/* * This file is a component of thundr, a software library from 3wks. * Read more: http://3wks.github.io/thundr/ * Copyright (C) 2014 3wks, <thundr@3wks.com.au> * * 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 com.threewks.thundr.http.service.ning; import java.util.List; import java.util.Map; import org.apache.commons.lang3.StringUtils; import com.atomicleopard.expressive.Expressive; import com.ning.http.client.AsyncHttpClient; import com.ning.http.client.AsyncHttpClient.BoundRequestBuilder; import com.ning.http.client.AsyncHttpClientConfig; import com.ning.http.client.ByteArrayPart; import com.ning.http.multipart.StringPart; import com.threewks.thundr.http.ContentType; import com.threewks.thundr.http.Header; import com.threewks.thundr.http.service.BaseHttpService; import com.threewks.thundr.http.service.FileParameter; import com.threewks.thundr.http.service.HttpException; import com.threewks.thundr.http.service.HttpRequestException; import com.threewks.thundr.http.service.HttpService; import com.threewks.thundr.transformer.TransformerManager; public class HttpServiceNing extends BaseHttpService<HttpServiceNing, HttpRequestNing, HttpResponseNing> implements HttpService { private AsyncHttpClientConfig config; private AsyncHttpClient client; public HttpServiceNing(TransformerManager transformerManager) { this(transformerManager, new AsyncHttpClientConfig.Builder().setMaximumConnectionsPerHost(10).setMaximumConnectionsTotal(100).build()); } public HttpServiceNing(TransformerManager transformerManager, AsyncHttpClientConfig config) { super(transformerManager); this.config = config; this.client = createHttpClient(); } @Override public HttpRequestNing request(String url) { return new HttpRequestNing(this, url); } AsyncHttpClient createHttpClient() { return new AsyncHttpClient(config); } @Override protected HttpResponseNing get(HttpRequestNing request) throws HttpException { String url = request.getUrl(); BoundRequestBuilder builder = client.prepareGet(url); setCommonProperties(request, builder); setContentTypeIfNotPresent(request, builder, ContentType.TextPlain); addHeaders(request, builder); addAuthorization(request, builder); addCookies(request, builder); addQueryParameters(request, builder); addBody(request, builder); try { return new HttpResponseNing(builder.execute(), this); } catch (Exception e) { throw new HttpRequestException(e, "Failed to create a GET request: %s", e.getMessage()); } } @Override protected HttpResponseNing post(HttpRequestNing request) throws HttpException { String url = request.getUrl(); BoundRequestBuilder builder = client.preparePost(url); setCommonProperties(request, builder); setContentTypeIfNotPresent(request, builder, ContentType.ApplicationFormUrlEncoded); addAuthorization(request, builder); addHeaders(request, builder); addCookies(request, builder); addParameters(request, builder); addBody(request, builder); try { return new HttpResponseNing(builder.execute(), this); } catch (Exception e) { throw new HttpRequestException(e, "Failed to create a POST request: %s", e.getMessage()); } } @Override protected HttpResponseNing put(HttpRequestNing request) throws HttpException { String url = request.getUrl(); BoundRequestBuilder builder = client.preparePut(url); setCommonProperties(request, builder); setContentTypeIfNotPresent(request, builder, ContentType.ApplicationFormUrlEncoded); addAuthorization(request, builder); addHeaders(request, builder); addCookies(request, builder); addParameters(request, builder); addBody(request, builder); try { return new HttpResponseNing(builder.execute(), this); } catch (Exception e) { throw new HttpRequestException(e, "Failed to create a PUT request: %s", e.getMessage()); } } @Override protected HttpResponseNing delete(HttpRequestNing request) throws HttpException { String url = request.getUrl(); BoundRequestBuilder builder = client.prepareDelete(url); setCommonProperties(request, builder); setContentTypeIfNotPresent(request, builder, ContentType.TextPlain); addAuthorization(request, builder); addHeaders(request, builder); addCookies(request, builder); addQueryParameters(request, builder); addBody(request, builder); try { return new HttpResponseNing(builder.execute(), this); } catch (Exception e) { throw new HttpRequestException(e, "Failed to create a DELETE request: %s", e.getMessage()); } } @Override protected HttpResponseNing head(HttpRequestNing request) throws HttpException { String url = request.getUrl(); BoundRequestBuilder builder = client.prepareHead(url); setCommonProperties(request, builder); setContentTypeIfNotPresent(request, builder, ContentType.TextPlain); addAuthorization(request, builder); addHeaders(request, builder); addCookies(request, builder); addQueryParameters(request, builder); try { return new HttpResponseNing(builder.execute(), this); } catch (Exception e) { throw new HttpRequestException(e, "Failed to create a HEAD request: %s", e.getMessage()); } } private void setCommonProperties(HttpRequestNing request, BoundRequestBuilder builder) { builder.setFollowRedirects(request.isFollowRedirects()); builder.setBodyEncoding(encoding); } private void addCookies(HttpRequestNing request, BoundRequestBuilder builder) { List<com.ning.http.client.Cookie> cookies = Expressive.Transformers.transformAllUsing(NingTransformers.toNingCookie).from(request.getCookies()); for (com.ning.http.client.Cookie cookie : cookies) { builder.addCookie(cookie); } } private void addHeaders(HttpRequestNing request, BoundRequestBuilder builder) { for (Map.Entry<String, String> header : request.getHeaders().entrySet()) { builder.addHeader(header.getKey(), header.getValue()); } } private void addQueryParameters(HttpRequestNing request, BoundRequestBuilder builder) { for (Map.Entry<String, Object> parameter : request.getParameters().entrySet()) { builder.addQueryParameter(parameter.getKey(), getValueAs(parameter.getValue(), String.class)); } } private void addParameters(HttpRequestNing request, BoundRequestBuilder builder) { for (Map.Entry<String, Object> parameter : request.getParameters().entrySet()) { builder.addParameter(parameter.getKey(), getValueAs(parameter.getValue(), String.class)); } } private void addAuthorization(HttpRequestNing request, BoundRequestBuilder builder) { String authorization = getAuthorization(request); if (authorization != null) { builder.addHeader(Header.Authorization, authorization); } } private void addBody(HttpRequestNing request, BoundRequestBuilder builder) { Object body = request.getBody(); if (isMultipart(request)) { for (Map.Entry<String, Object> parameter : request.getParameters().entrySet()) { Object value = parameter.getValue(); builder.addBodyPart(new StringPart(parameter.getKey(), getValueAs(value, String.class), "UTF-8")); } for (FileParameter fileParam : request.getFileParameters()) { Object partBody = fileParam.getBody(); byte[] data = getValueAs(partBody, byte[].class); String contentType = StringUtils.substringBefore(fileParam.getContentType(), ";"); String characterEncoding = StringUtils.substringBetween(fileParam.getContentType(), "charset=\"", "\""); builder.addBodyPart(new ByteArrayPart(fileParam.getName(), fileParam.getName(), data, contentType, characterEncoding)); } builder.setHeader(Header.ContentType, ContentType.MultipartFormData.value()); } else if (body != null) { builder.setBody(convertOutgoing(body)); } } private void setContentTypeIfNotPresent(HttpRequestNing request, BoundRequestBuilder builder, ContentType contentType) { builder.setHeader(Header.ContentType, contentType.value()); } }