Java tutorial
/* * Copyright (c) 2013 3 Round Stones Inc., Some Rights Reserved * * 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.callimachusproject.client; import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; import java.util.Collections; import java.util.LinkedList; import java.util.List; import java.util.Queue; import junit.framework.TestCase; import org.apache.http.HttpEntity; import org.apache.http.HttpException; import org.apache.http.HttpHost; import org.apache.http.HttpRequest; import org.apache.http.HttpResponse; import org.apache.http.HttpVersion; import org.apache.http.auth.AuthScope; import org.apache.http.auth.UsernamePasswordCredentials; import org.apache.http.auth.params.AuthPNames; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.CookieStore; import org.apache.http.client.CredentialsProvider; import org.apache.http.client.HttpClient; import org.apache.http.client.ResponseHandler; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpExecutionAware; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpRequestWrapper; import org.apache.http.client.methods.HttpUriRequest; import org.apache.http.client.params.AuthPolicy; import org.apache.http.client.params.ClientPNames; import org.apache.http.client.params.CookiePolicy; import org.apache.http.client.protocol.ClientContext; import org.apache.http.client.protocol.HttpClientContext; import org.apache.http.conn.routing.HttpRoute; import org.apache.http.entity.ByteArrayEntity; import org.apache.http.entity.ContentType; import org.apache.http.impl.client.BasicCookieStore; import org.apache.http.impl.client.BasicCredentialsProvider; import org.apache.http.impl.execchain.ClientExecChain; import org.apache.http.message.BasicHttpResponse; import org.apache.http.message.BasicStatusLine; import org.apache.http.protocol.BasicHttpContext; import org.apache.http.protocol.ExecutionContext; import org.apache.http.protocol.HttpContext; import org.callimachusproject.fluid.FluidBuilder; import org.callimachusproject.fluid.FluidException; import org.callimachusproject.fluid.FluidFactory; import org.junit.After; import org.junit.Before; import org.junit.ComparisonFailure; import org.junit.Test; public class HttpClientFactoryTest extends TestCase { private static final String ORIGIN = "http://example.com"; private static final BasicStatusLine _200 = new BasicStatusLine(HttpVersion.HTTP_1_1, 200, "OK"); private static final BasicStatusLine _302 = new BasicStatusLine(HttpVersion.HTTP_1_1, 302, "Found"); private static final BasicStatusLine _401 = new BasicStatusLine(HttpVersion.HTTP_1_1, 401, "Unauthorized"); private final Queue<HttpResponse> responses = new LinkedList<HttpResponse>(); private final HttpClient client = HttpClientFactory.getInstance().createHttpClient(ORIGIN); private final FluidBuilder builder = FluidFactory.getInstance().builder(); private final ClientExecChain director = new ClientExecChain() { public CloseableHttpResponse execute(HttpRoute route, HttpRequestWrapper request, HttpClientContext clientContext, HttpExecutionAware execAware) throws IOException, HttpException { HttpResponse response = responses.poll(); byte[] http = asByteArray(request); ByteArrayEntity entity = new ByteArrayEntity(http, ContentType.create("message/http")); response.setHeader(entity.getContentType()); long length = entity.getContentLength(); if (length >= 0) { response.setHeader("Content-Length", Long.toString(length)); } response.setEntity(entity); HttpHost target = route.getTargetHost(); try { URI root = new URI(target.getSchemeName(), null, target.getHostName(), target.getPort(), "/", null, null); return new HttpUriResponse(root.resolve(request.getURI()).toASCIIString(), response); } catch (URISyntaxException e) { return new HttpUriResponse(request.getURI().toASCIIString(), response); } } }; @Before public void setUp() throws Exception { responses.clear(); HttpClientFactory.getInstance().setProxy(new HttpHost("example.com", -1, "http"), director); } @After public void tearDown() throws Exception { HttpClientFactory.getInstance().removeProxy(new HttpHost("example.com", -1, "http"), director); } @Test public void test200() throws Exception { responses.add(new BasicHttpResponse(_200)); client.execute(new HttpGet("http://example.com/200"), new ResponseHandler<Void>() { public Void handleResponse(HttpResponse response) throws ClientProtocolException, IOException { assertEquals(_200.getStatusCode(), response.getStatusLine().getStatusCode()); return null; } }); } @Test public void testTargetHost() throws Exception { HttpContext localContext = new BasicHttpContext(); responses.add(new BasicHttpResponse(_200)); client.execute(new HttpGet("http://example.com/200"), new ResponseHandler<Void>() { public Void handleResponse(HttpResponse response) throws ClientProtocolException, IOException { assertEquals(_200.getStatusCode(), response.getStatusLine().getStatusCode()); return null; } }, localContext); HttpHost host = (HttpHost) localContext.getAttribute(ExecutionContext.HTTP_TARGET_HOST); assertEquals(ORIGIN, host.toString()); } @Test public void testTarget() throws Exception { HttpContext localContext = new BasicHttpContext(); responses.add(new BasicHttpResponse(_200)); client.execute(new HttpGet("http://example.com/200"), new ResponseHandler<Void>() { public Void handleResponse(HttpResponse response) throws ClientProtocolException, IOException { assertEquals(_200.getStatusCode(), response.getStatusLine().getStatusCode()); return null; } }, localContext); HttpHost host = (HttpHost) localContext.getAttribute(ExecutionContext.HTTP_TARGET_HOST); HttpUriRequest req = (HttpUriRequest) localContext.getAttribute(ExecutionContext.HTTP_REQUEST); URI root = new URI(host.getSchemeName(), null, host.getHostName(), host.getPort(), "/", null, null); assertEquals("http://example.com/200", root.resolve(req.getURI()).toASCIIString()); } @Test public void test302() throws Exception { responses.add(new BasicHttpResponse(_302)); client.execute(new HttpGet("http://example.com/302"), new ResponseHandler<Void>() { public Void handleResponse(HttpResponse response) throws ClientProtocolException, IOException { assertEquals(_302.getStatusCode(), response.getStatusLine().getStatusCode()); return null; } }); } @Test public void test302Redirect() throws Exception { HttpGet get = new HttpGet("http://example.com/302"); get.getParams().setBooleanParameter(ClientPNames.HANDLE_REDIRECTS, true); BasicHttpResponse redirect = new BasicHttpResponse(_302); redirect.setHeader("Location", "http://example.com/200"); responses.add(redirect); responses.add(new BasicHttpResponse(_200)); client.execute(get, new ResponseHandler<Void>() { public Void handleResponse(HttpResponse response) throws ClientProtocolException, IOException { assertEquals(_200.getStatusCode(), response.getStatusLine().getStatusCode()); return null; } }); } @Test public void test302RedirectTarget() throws Exception { HttpContext localContext = new BasicHttpContext(); HttpGet get = new HttpGet("http://example.com/302"); get.getParams().setBooleanParameter(ClientPNames.HANDLE_REDIRECTS, true); BasicHttpResponse redirect = new BasicHttpResponse(_302); redirect.setHeader("Location", "http://example.com/200"); responses.add(redirect); responses.add(new BasicHttpResponse(_200)); client.execute(get, new ResponseHandler<Void>() { public Void handleResponse(HttpResponse response) throws ClientProtocolException, IOException { assertEquals(_200.getStatusCode(), response.getStatusLine().getStatusCode()); return null; } }, localContext); HttpHost host = (HttpHost) localContext.getAttribute(ExecutionContext.HTTP_TARGET_HOST); HttpUriRequest req = (HttpUriRequest) localContext.getAttribute(ExecutionContext.HTTP_REQUEST); URI root = new URI(host.getSchemeName(), null, host.getHostName(), host.getPort(), "/", null, null); assertEquals("http://example.com/200", root.resolve(req.getURI()).toASCIIString()); } @Test public void test302CachedRedirectTarget() throws Exception { do { HttpGet get = new HttpGet("http://example.com/302"); get.getParams().setBooleanParameter(ClientPNames.HANDLE_REDIRECTS, true); BasicHttpResponse redirect = new BasicHttpResponse(_302); redirect.setHeader("Location", "http://example.com/200"); redirect.setHeader("Cache-Control", "public,max-age=3600"); responses.add(redirect); BasicHttpResponse doc = new BasicHttpResponse(_200); doc.setHeader("Cache-Control", "public,max-age=3600"); responses.add(doc); client.execute(get, new ResponseHandler<Void>() { public Void handleResponse(HttpResponse response) throws ClientProtocolException, IOException { assertEquals(_200.getStatusCode(), response.getStatusLine().getStatusCode()); return null; } }); } while (false); do { HttpContext localContext = new BasicHttpContext(); HttpGet get = new HttpGet("http://example.com/302"); get.getParams().setBooleanParameter(ClientPNames.HANDLE_REDIRECTS, false); BasicHttpResponse redirect = new BasicHttpResponse(_302); redirect.setHeader("Location", "http://example.com/200"); redirect.setHeader("Cache-Control", "public,max-age=3600"); responses.add(redirect); client.execute(get, new ResponseHandler<Void>() { public Void handleResponse(HttpResponse response) throws ClientProtocolException, IOException { assertEquals(_302.getStatusCode(), response.getStatusLine().getStatusCode()); return null; } }, localContext); HttpHost host = (HttpHost) localContext.getAttribute(ExecutionContext.HTTP_TARGET_HOST); HttpUriRequest req = (HttpUriRequest) localContext.getAttribute(ExecutionContext.HTTP_REQUEST); URI root = new URI(host.getSchemeName(), null, host.getHostName(), -1, "/", null, null); assertEquals("http://example.com/302", root.resolve(req.getURI()).toASCIIString()); } while (false); } @Test public void testCookieStored() throws Exception { CookieStore cookieStore = new BasicCookieStore(); do { HttpGet get = new HttpGet("http://example.com/setcookie"); HttpContext localContext = new BasicHttpContext(); localContext.setAttribute(ClientContext.COOKIE_STORE, cookieStore); get.getParams().setParameter(ClientPNames.COOKIE_POLICY, CookiePolicy.RFC_2109); BasicHttpResponse setcookie = new BasicHttpResponse(_200); setcookie.addHeader("Set-Cookie", "oat=meal"); setcookie.addHeader("Cache-Control", "no-store"); responses.add(setcookie); client.execute(get, new ResponseHandler<Void>() { public Void handleResponse(HttpResponse response) throws ClientProtocolException, IOException { assertEquals(_200.getStatusCode(), response.getStatusLine().getStatusCode()); assertTrue(response.containsHeader("Set-Cookie")); return null; } }, localContext); } while (false); do { HttpGet get = new HttpGet("http://example.com/getcookie"); HttpContext localContext = new BasicHttpContext(); localContext.setAttribute(ClientContext.COOKIE_STORE, cookieStore); get.getParams().setParameter(ClientPNames.COOKIE_POLICY, CookiePolicy.RFC_2109); BasicHttpResponse getcookie = new BasicHttpResponse(_200); responses.add(getcookie); client.execute(get, new ResponseHandler<Void>() { public Void handleResponse(HttpResponse response) throws ClientProtocolException, IOException { assertEquals(_200.getStatusCode(), response.getStatusLine().getStatusCode()); assertContains("oat=meal", asString(response.getEntity())); return null; } }, localContext); } while (false); } @Test public void testAuthentication() throws Exception { HttpGet get = new HttpGet("http://example.com/protected"); HttpContext localContext = new BasicHttpContext(); List<String> authpref = Collections.singletonList(AuthPolicy.BASIC); AuthScope scope = new AuthScope("example.com", -1); UsernamePasswordCredentials cred = new UsernamePasswordCredentials("Aladdin", "open sesame"); CredentialsProvider credsProvider = new BasicCredentialsProvider(); credsProvider.setCredentials(scope, cred); localContext.setAttribute(ClientContext.CREDS_PROVIDER, credsProvider); get.getParams().setBooleanParameter(ClientPNames.HANDLE_AUTHENTICATION, true); get.getParams().setParameter(AuthPNames.TARGET_AUTH_PREF, authpref); BasicHttpResponse unauth = new BasicHttpResponse(_401); unauth.setHeader("WWW-Authenticate", "Basic realm=\"insert realm\""); responses.add(unauth); responses.add(new BasicHttpResponse(_200)); client.execute(get, new ResponseHandler<Void>() { public Void handleResponse(HttpResponse response) throws ClientProtocolException, IOException { assertEquals(_200.getStatusCode(), response.getStatusLine().getStatusCode()); assertContains("Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==", asString(response.getEntity())); return null; } }, localContext); } byte[] asByteArray(HttpRequest request) throws IOException { try { String url = request.getRequestLine().getUri(); if (url.startsWith("/")) { url = "http://" + request.getFirstHeader("Host").getValue() + url; } return (byte[]) builder.consume(request, url, HttpRequest.class, "message/http").as(byte[].class, "message/http"); } catch (FluidException e) { throw new IOException(e.getMessage(), e); } } String asString(HttpEntity entity) throws IOException { try { String url = ORIGIN + "/entity"; return builder.consume(entity, url, HttpEntity.class, "text/plain").asString("text/plain"); } catch (FluidException e) { throw new IOException(e.getMessage(), e); } } void assertContains(String needle, String actual) { if (actual == null || !actual.contains(needle)) throw new ComparisonFailure("", needle, actual); } }