/** * Copyright (C) 2013 the original author or authors. * * 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 org.doctester.testbrowser; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.dataformat.xml.XmlMapper; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.google.common.collect.Sets; import org.apache.http.Header; import org.apache.http.HttpEntity; import org.apache.http.HttpVersion; import org.apache.http.ParseException; import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.methods.*; import org.apache.http.cookie.Cookie; import org.apache.http.entity.StringEntity; import org.apache.http.entity.mime.HttpMultipartMode; import org.apache.http.entity.mime.MultipartEntity; import org.apache.http.entity.mime.content.FileBody; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.message.BasicNameValuePair; import org.apache.http.params.BasicHttpParams; import org.apache.http.params.CoreProtocolPNames; import org.apache.http.params.HttpParams; import org.apache.http.util.EntityUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.management.RuntimeErrorException; import java.io.File; import java.io.IOException; import java.util.List; import java.util.Map; import java.util.Map.Entry; import static org.doctester.testbrowser.HttpConstants.*; public class TestBrowserImpl implements TestBrowser { private static Logger logger = LoggerFactory.getLogger(TestBrowserImpl.class); private static final String HANDLE_REDIRECTS = "http.protocol.handle-redirects"; private DefaultHttpClient httpClient; public TestBrowserImpl() { httpClient = new DefaultHttpClient(); } @Override public List<Cookie> getCookies() { return httpClient.getCookieStore().getCookies(); } @Override public Cookie getCookieWithName(String name) { List<Cookie> cookies = getCookies(); // skip through cookies and return cookie you want for (Cookie cookie : cookies) { if (cookie.getName().equals(name)) { return cookie; } } return null; } @Override public void clearCookies() { httpClient.getCookieStore().clear(); } @Override public Response makeRequest(Request httpRequest) { Response httpResponse; if (Sets.newHashSet(HEAD, GET, DELETE).contains(httpRequest.httpRequestType)) { httpResponse = makeHeadGetOrDeleteRequest(httpRequest); } else if (Sets.newHashSet(POST, PUT, PATCH).contains(httpRequest.httpRequestType)) { httpResponse = makePatchPostOrPutRequest(httpRequest); } else { throw new RuntimeErrorException(new Error("Your requested httpRequest.httpRequestType is not supported")); } return httpResponse; } private Response makeHeadGetOrDeleteRequest(Request request) { Response response; org.apache.http.HttpResponse apacheHttpClientResponse; try { HttpUriRequest apacheHttpRequest; httpClient.getParams().setParameter( CoreProtocolPNames.PROTOCOL_VERSION, HttpVersion.HTTP_1_1); if (GET.equalsIgnoreCase(request.httpRequestType)) { apacheHttpRequest = new HttpGet(request.uri); } else if (DELETE.equalsIgnoreCase(request.httpRequestType)) { apacheHttpRequest = new HttpDelete(request.uri); } else { apacheHttpRequest = new HttpHead(request.uri); } if (request.headers != null) { // add all headers for (Entry<String, String> header : request.headers .entrySet()) { apacheHttpRequest.addHeader(header.getKey(), header.getValue()); } } setHandleRedirect(apacheHttpRequest, request.followRedirects); apacheHttpClientResponse = httpClient.execute(apacheHttpRequest); response = convertFromApacheHttpResponseToDocTesterHttpResponse(apacheHttpClientResponse); if (apacheHttpRequest instanceof HttpRequestBase) { ((HttpRequestBase) apacheHttpRequest).releaseConnection(); } } catch (IOException e) { logger.error("Fatal problem creating GET or DELETE request in TestBrowser", e); throw new RuntimeException(e); } return response; } private Response makePatchPostOrPutRequest(Request httpRequest) { org.apache.http.HttpResponse apacheHttpClientResponse; Response response = null; try { httpClient.getParams().setParameter( CoreProtocolPNames.PROTOCOL_VERSION, HttpVersion.HTTP_1_1); HttpEntityEnclosingRequestBase apacheHttpRequest; if (PATCH.equalsIgnoreCase(httpRequest.httpRequestType)) { apacheHttpRequest = new HttpPatch(httpRequest.uri); } else if (POST.equalsIgnoreCase(httpRequest.httpRequestType)) { apacheHttpRequest = new HttpPost(httpRequest.uri); } else { apacheHttpRequest = new HttpPut(httpRequest.uri); } if (httpRequest.headers != null) { // add all headers for (Entry<String, String> header : httpRequest.headers .entrySet()) { apacheHttpRequest.addHeader(header.getKey(), header.getValue()); } } /////////////////////////////////////////////////////////////////// // Either add form parameters... /////////////////////////////////////////////////////////////////// if (httpRequest.formParameters != null) { List<BasicNameValuePair> formparams = Lists.newArrayList(); for (Entry<String, String> parameter : httpRequest.formParameters .entrySet()) { formparams.add(new BasicNameValuePair(parameter.getKey(), parameter.getValue())); } // encode form parameters and add UrlEncodedFormEntity entity = new UrlEncodedFormEntity(formparams); apacheHttpRequest.setEntity(entity); } /////////////////////////////////////////////////////////////////// // Or add multipart file upload /////////////////////////////////////////////////////////////////// if (httpRequest.filesToUpload != null) { MultipartEntity entity = new MultipartEntity( HttpMultipartMode.BROWSER_COMPATIBLE); for (Map.Entry<String, File> entry : httpRequest.filesToUpload .entrySet()) { // For File parameters entity.addPart(entry.getKey(), new FileBody((File) entry.getValue())); } apacheHttpRequest.setEntity(entity); } /////////////////////////////////////////////////////////////////// // Or add payload and convert if Json or Xml /////////////////////////////////////////////////////////////////// if (httpRequest.payload != null) { if (httpRequest.headers.containsKey(HEADER_CONTENT_TYPE) && httpRequest.headers.containsValue(APPLICATION_JSON_WITH_CHARSET_UTF8)) { String string = new ObjectMapper().writeValueAsString(httpRequest.payload); StringEntity entity = new StringEntity(string, "utf-8"); entity.setContentType("application/json; charset=utf-8"); apacheHttpRequest.setEntity(entity); } else if (httpRequest.headers.containsKey(HEADER_CONTENT_TYPE) && httpRequest.headers.containsValue(APPLICATION_XML_WITH_CHARSET_UTF_8)) { String string = new XmlMapper().writeValueAsString(httpRequest.payload); StringEntity entity = new StringEntity(string, "utf-8"); entity.setContentType(APPLICATION_XML_WITH_CHARSET_UTF_8); apacheHttpRequest.setEntity(new StringEntity(string, "utf-8")); } else if (httpRequest.payload instanceof String) { StringEntity entity = new StringEntity((String) httpRequest.payload, "utf-8"); apacheHttpRequest.setEntity(entity); } else { StringEntity entity = new StringEntity(httpRequest.payload.toString(), "utf-8"); apacheHttpRequest.setEntity(entity); } } setHandleRedirect(apacheHttpRequest, httpRequest.followRedirects); // Here we go! apacheHttpClientResponse = httpClient.execute(apacheHttpRequest); response = convertFromApacheHttpResponseToDocTesterHttpResponse(apacheHttpClientResponse); apacheHttpRequest.releaseConnection(); } catch (IOException e) { logger.error("Fatal problem creating PATCH, POST or PUT request in TestBrowser", e); throw new RuntimeException(e); } return response; } private org.doctester.testbrowser.Response convertFromApacheHttpResponseToDocTesterHttpResponse(org.apache.http.HttpResponse httpResponse) { Map<String, String> headers = Maps.newHashMap(); for (Header header : httpResponse.getAllHeaders()) { headers.put(header.getName(), header.getValue()); } int httpStatus = httpResponse.getStatusLine().getStatusCode(); String body = null; HttpEntity entity = httpResponse.getEntity(); if (entity != null) { try { body = EntityUtils.toString(entity, "UTF-8"); } catch (IOException | ParseException e) { logger.error("Error while converting ApacheHttpClient response body to a String we can use", e); } } org.doctester.testbrowser.Response doctestJHttpResponse = new org.doctester.testbrowser.Response( headers, httpStatus, body); return doctestJHttpResponse; } /** * Tells ApacheHttpClient whether to follow redirects. See also: * http://stackoverflow.com/questions/1519392/how-to-prevent-apache-http-client-from-following-a-redirect */ private void setHandleRedirect(HttpUriRequest httpUriRequest, boolean handleRedirect) { HttpParams params = new BasicHttpParams(); params.setParameter(HANDLE_REDIRECTS, handleRedirect); httpUriRequest.setParams(params); } }