package ecologylab.bigsemantics.httpclient; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.net.URI; import java.net.URISyntaxException; import java.nio.charset.Charset; import java.util.ArrayList; import java.util.List; import java.util.Map; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.NameValuePair; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.ResponseHandler; import org.apache.http.client.entity.UrlEncodedFormEntity; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPost; import org.apache.http.client.methods.HttpUriRequest; import org.apache.http.client.utils.URIBuilder; import org.apache.http.client.utils.URIUtils; import org.apache.http.impl.client.AbstractHttpClient; import org.apache.http.message.BasicNameValuePair; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Utility methods for the HTTP client. * * @author quyin */ public class HttpClientUtils { static Logger logger; static HttpClientFactory factory; static { logger = LoggerFactory.getLogger(HttpClientUtils.class); factory = new HttpClientFactory(); } /** * Convert a string URL to a URIBuilder. Do basic syntax validation and correction. * * @param url * @return The resulting URIBuilder. * @throws URISyntaxException */ public static URIBuilder toUriBuilder(String url) throws UnsupportedEncodingException, URISyntaxException { URIBuilder ub = null; try { ub = new URIBuilder(url); } catch (URISyntaxException e) { ub = parseToUriBuilder(url); } return ub; } static URIBuilder parseToUriBuilder(String url) throws URISyntaxException, UnsupportedEncodingException { String path = null; String queries = null; int qpos = url.indexOf('?'); if (qpos < 0) { path = url; } else { path = url.substring(0, qpos); queries = url.substring(qpos + 1); } // TODO more escaping path = path.replace(" ", "%20"); URIBuilder ub = new URIBuilder(path); if (queries != null) { String[] params = queries.split("&"); for (int i = 0; i < params.length; ++i) { int epos = params[i].indexOf('='); String name = params[i].substring(0, epos); String value = params[i].substring(epos + 1); // URIBuilder.addParameter() handles URL encoding automatically, no need to do it here. // ub.addParameter(name, URLEncoder.encode(value, "UTF-8")); ub.addParameter(name, value); } } return ub; } public static boolean looksLikeRelative(String url) { return !url.matches("^\\w+://.+"); } public static String relativeToAbsolute(String baseUrl, String url) { try { URI result = URIUtils.resolve(new URI(baseUrl), url); return result.toString(); } catch (Exception e) { logger.warn("Cannot convert relative URL " + url + " to absolute, with base " + baseUrl, e); } return url; } public static SimplHttpResponse doGet(String userAgent, String url, Map<String, String> additionalParams) throws URISyntaxException, IOException { URIBuilder ub = toUriBuilder(url); if (additionalParams != null) { for (String key : additionalParams.keySet()) { String value = additionalParams.get(key); ub.addParameter(key, value); } } URI uri = ub.build(); String hostName = uri.getHost(); int port = uri.getPort(); String host = hostName + ((port > 0) ? (":" + port) : ""); HttpGet get = new HttpGet(uri); get.addHeader("HOST", host); // this header is required by HTTP 1.1 try { return doRequest(userAgent, url, get); } finally { get.releaseConnection(); } } public static SimplHttpResponse doPost(String userAgent, String url, Map<String, String> formParams) throws URISyntaxException, IOException { URIBuilder ub = toUriBuilder(url); URI uri = ub.build(); String hostName = uri.getHost(); int port = uri.getPort(); String host = hostName + ((port > 0) ? (":" + port) : ""); HttpPost post = new HttpPost(uri); post.addHeader("HOST", host); // this header is required by HTTP 1.1 List<NameValuePair> params = new ArrayList<NameValuePair>(); for (String key : formParams.keySet()) { String value = formParams.get(key); if (value != null) { params.add(new BasicNameValuePair(key, value)); } } HttpEntity entity = new UrlEncodedFormEntity(params, Charset.forName("UTF-8")); post.setEntity(entity); try { return doRequest(userAgent, url, post); } finally { post.releaseConnection(); } } private static SimplHttpResponse doRequest(String userAgent, final String url, HttpUriRequest request) throws IOException { AbstractHttpClient client = factory.create(userAgent); // client must use BasicRedirectStrategy! final BasicRedirectStrategy redirectStrategy = (BasicRedirectStrategy) client.getRedirectStrategy(); SimplHttpResponse result = client.execute(request, new ResponseHandler<SimplHttpResponse>() { @Override public SimplHttpResponse handleResponse(HttpResponse response) throws ClientProtocolException, IOException { List<String> redirectedLocations = redirectStrategy.getRedirectedLocations(); return SimplHttpResponse.parse(url, redirectedLocations, response); } }); return result; } }