package aQute.bnd.comm.tests; import java.io.File; import java.net.HttpURLConnection; import java.net.URI; import java.net.URISyntaxException; import java.net.URL; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; import org.osgi.util.promise.Promise; import aQute.bnd.http.HttpClient; import aQute.bnd.osgi.Processor; import aQute.bnd.service.progress.ProgressPlugin; import aQute.bnd.service.url.State; import aQute.bnd.service.url.TaggedData; import aQute.bnd.url.HttpsVerification; import aQute.http.testservers.HttpTestServer.Config; import aQute.http.testservers.Httpbin; import aQute.lib.io.IO; import junit.framework.TestCase; public class HttpClientTest extends TestCase { private TestServer httpServer; private Httpbin httpsServer; private File tmp; @Override protected void tearDown() throws Exception { super.tearDown(); httpServer.close(); httpsServer.close(); IO.delete(tmp); } public static class TestServer extends Httpbin { boolean second = false; public TestServer(Config config) throws Exception { super(config); } public void _mftch(Request rq, Response rsp) throws Exception { Thread.sleep(1000); rsp.headers.put("ETag", "FOO"); if (second) { rsp.code = 304; return; } rsp.code = 200; rsp.content = "OK!".getBytes(); second = true; } } @Override protected void setUp() throws Exception { super.setUp(); Config config = new Config(); config.https = false; httpServer = new TestServer(config); httpServer.start(); Config configs = new Config(); configs.https = true; httpsServer = new Httpbin(configs); httpsServer.start(); tmp = IO.getFile("generated/tmp"); IO.delete(tmp); tmp.mkdirs(); } public void testTimeout() throws Exception { try (HttpClient hc = new HttpClient();) { try { TaggedData tag = hc.build().asTag().timeout(1000).go(httpServer.getBaseURI("timeout/10")); assertNotNull(tag); assertEquals(200, tag.getResponseCode()); IO.collect(tag.getInputStream()); fail(); } catch (Exception e) { e.printStackTrace(); } } } public void testCancel() throws Exception { final long deadline = System.currentTimeMillis() + 1000L; try (HttpClient hc = new HttpClient();) { Processor p = new Processor(); p.addBasicPlugin(new ProgressPlugin() { @Override public Task startTask(String name, int size) { return new Task() { @Override public void worked(int units) { System.out.println("Worked " + units); } @Override public void done(String message, Throwable e) { System.out.println("Done " + message + " " + e); } @Override public boolean isCanceled() { System.out.println("Cancel check "); return System.currentTimeMillis() > deadline; } }; } }); hc.setRegistry(p); TaggedData tag = hc.build().asTag().go(httpServer.getBaseURI("timeout/50")); assertNotNull(tag); assertEquals(200, tag.getResponseCode()); try { String s = IO.collect(tag.getInputStream()); fail(); } catch (Exception e) { e.printStackTrace(); } } } public void testCachingMultipleFetch() throws Exception { try (HttpClient hc = new HttpClient();) { hc.setCache(tmp); Promise<TaggedData> a = hc.build() .useCache() .age(1, TimeUnit.DAYS) .asTag() .async(httpServer.getBaseURI("mftch")); Thread.sleep(100); Promise<TaggedData> b = hc.build() .useCache() .age(1, TimeUnit.DAYS) .asTag() .async(httpServer.getBaseURI("mftch")); TaggedData ta = a.getValue(); assertEquals("FOO", ta.getTag()); assertEquals(200, ta.getResponseCode()); assertEquals(true, ta.hasPayload()); assertEquals(true, ta.isOk()); assertEquals(State.UPDATED, ta.getState()); TaggedData tb = b.getValue(); assertEquals("FOO", tb.getTag()); assertEquals(304, tb.getResponseCode()); assertEquals(false, tb.hasPayload()); assertEquals(State.UNMODIFIED, tb.getState()); System.out.println(a.getValue()); System.out.println(b.getValue()); } } public void testFetch() throws Exception { try (HttpClient hc = new HttpClient();) { String text = hc.build().get(String.class).go(httpServer.getBaseURI("get")); assertNotNull(text); assertTrue(text.startsWith("{")); } } public void testRedirect() throws Exception { try (HttpClient hc = new HttpClient();) { TaggedData tag = hc.build().get(TaggedData.class).go(httpServer.getBaseURI("redirect/3/200")); assertNotNull(tag); assertEquals(200, tag.getResponseCode()); } } public void testRedirectTooMany() throws Exception { try (HttpClient hc = new HttpClient();) { TaggedData tag = hc.build() .maxRedirects(3) .get(TaggedData.class) .go(httpServer.getBaseURI("redirect/200/200")); assertEquals(3, tag.getResponseCode() / 100); } } public void testRedirectURL() throws Exception { try (HttpClient hc = new HttpClient();) { HttpsVerification httpsVerification = new HttpsVerification(httpsServer.getCertificateChain(), false, hc.getReporter()); hc.addURLConnectionHandler(httpsVerification); URI uri = httpsServer.getBaseURI("get"); URL go = httpServer.getBaseURI("xlocation").toURL(); TaggedData tag = hc.build() .maxRedirects(3) .get(TaggedData.class) .headers("XLocation", uri.toString()) .go(go); assertNotNull(tag); assertEquals(200, tag.getResponseCode()); } } public void testETag() throws Exception { try (HttpClient hc = new HttpClient();) { TaggedData data = hc.build().get(TaggedData.class).go(httpServer.getBaseURI("etag/1234/0")); assertNotNull(data); assertEquals("1234", data.getTag()); } } public void testNotModifiedEtag() throws Exception { try (HttpClient hc = new HttpClient();) { TaggedData data = hc.build() .get(TaggedData.class) .ifNoneMatch("1234") .go(httpServer.getBaseURI("etag/1234/0")); assertNotNull(data); assertEquals("1234", data.getTag()); assertEquals(HttpURLConnection.HTTP_NOT_MODIFIED, data.getResponseCode()); } } public void testModifiedWithEtag() throws Exception { try (HttpClient hc = new HttpClient();) { TaggedData data = hc.build() .get(TaggedData.class) .ifNoneMatch("0000") .go(httpServer.getBaseURI("etag/1234/0")); assertNotNull(data); assertEquals("1234", data.getTag()); assertEquals(200, data.getResponseCode()); } } public void testNotModifiedSince() throws Exception { try (HttpClient hc = new HttpClient();) { TaggedData data = hc.build().get(TaggedData.class).ifNoneMatch("*").ifModifiedSince(20000).go( httpServer.getBaseURI("etag/1234/10000")); assertNotNull(data); assertEquals("1234", data.getTag()); assertEquals(HttpURLConnection.HTTP_NOT_MODIFIED, data.getResponseCode()); } } public void testNotModifiedSinceAtSameTime() throws Exception { try (HttpClient hc = new HttpClient();) { TaggedData data = hc.build().get(TaggedData.class).ifNoneMatch("*").ifModifiedSince(20000).go( httpServer.getBaseURI("etag/1234/20000")); assertNotNull(data); assertEquals("1234", data.getTag()); assertEquals(HttpURLConnection.HTTP_NOT_MODIFIED, data.getResponseCode()); } } public void testModifiedSince() throws Exception { try (HttpClient hc = new HttpClient();) { TaggedData data = hc.build() .get(TaggedData.class) .ifModifiedSince(10000) .go(httpServer.getBaseURI("etag/1234/20000")); assertNotNull(data); assertEquals("1234", data.getTag()); assertEquals(200, data.getResponseCode()); } try (HttpClient hc = new HttpClient();) { TaggedData data = hc.build() .get(TaggedData.class) .ifModifiedSince(20000) .go(httpServer.getBaseURI("etag/1234/10000")); assertNotNull(data); assertEquals("1234", data.getTag()); assertEquals(304, data.getResponseCode()); } } public void testMultipleProgressPlugins() throws Exception { final long deadline = System.currentTimeMillis() + 1000L; try (HttpClient hc = new HttpClient();) { Processor p = new Processor(); final int[] counts = new int[2]; counts[0] = counts[1] = 0; p.addBasicPlugin(new ProgressPlugin() { @Override public Task startTask(String name, int size) { return new Task() { @Override public void worked(int units) { counts[0]++; } @Override public void done(String message, Throwable e) { counts[0]++; } @Override public boolean isCanceled() { return false; } }; } }); p.addBasicPlugin(new ProgressPlugin() { @Override public Task startTask(String name, int size) { return new Task() { @Override public void worked(int units) { counts[1]++; } @Override public void done(String message, Throwable e) { counts[1]++; } @Override public boolean isCanceled() { return false; } }; } }); hc.setRegistry(p); String text = hc.build().get(String.class).go(httpServer.getBaseURI("get")); assertNotNull(text); assertTrue(counts[0] > 0); assertEquals(counts[0], counts[1]); } } public void testPut() throws URISyntaxException, Exception { try (Processor p = new Processor();) { final AtomicBoolean done = new AtomicBoolean(); p.addBasicPlugin(new ProgressPlugin() { @Override public Task startTask(final String name, int size) { System.out.println("start " + name); return new Task() { @Override public void worked(int units) { System.out.println("worked " + name + " " + units); } @Override public void done(String message, Throwable e) { System.out.println("done " + name + " " + message + " " + e); done.set(true); } @Override public boolean isCanceled() { return false; } }; } }); try (HttpClient c = new HttpClient();) { c.setRegistry(p); TaggedData go = c.build().verb("PUT").upload("hello").asTag().go(httpServer.getBaseURI("put")); go.getInputStream().close(); assertEquals(200, go.getResponseCode()); assertTrue(done.get()); } } } }