/* * Copyright 2010 Ning, Inc. * * This program is licensed to you 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.asynchttpclient; import static io.netty.handler.codec.http.HttpHeaderNames.CONTENT_TYPE; import static java.util.concurrent.TimeUnit.SECONDS; import static org.asynchttpclient.Dsl.config; import static org.asynchttpclient.test.TestUtils.*; import static org.testng.Assert.*; import io.netty.handler.codec.http.HttpRequest; import io.netty.handler.codec.http.HttpResponse; import java.util.Arrays; import java.util.concurrent.ExecutionException; import java.util.concurrent.atomic.AtomicBoolean; import javax.net.ssl.SSLHandshakeException; import javax.servlet.http.HttpServletResponse; import org.asynchttpclient.channel.KeepAliveStrategy; import org.asynchttpclient.test.EventCollectingHandler; import org.asynchttpclient.testserver.HttpServer; import org.asynchttpclient.testserver.HttpTest; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; public class BasicHttpsTest extends HttpTest { private static HttpServer server; @BeforeClass public static void start() throws Throwable { server = new HttpServer(); server.start(); } @AfterClass public static void stop() throws Throwable { server.close(); } private static String getTargetUrl() { return server.getHttpsUrl() + "/foo/bar"; } @Test public void postFileOverHttps() throws Throwable { logger.debug(">>> postBodyOverHttps"); withClient(config().setSslEngineFactory(createSslEngineFactory())).run(client -> { withServer(server).run(server -> { server.enqueueEcho(); Response resp = client.preparePost(getTargetUrl()).setBody(SIMPLE_TEXT_FILE).setHeader(CONTENT_TYPE, "text/html").execute().get(); assertNotNull(resp); assertEquals(resp.getStatusCode(), HttpServletResponse.SC_OK); assertEquals(resp.getResponseBody(), SIMPLE_TEXT_FILE_STRING); }); }); logger.debug("<<< postBodyOverHttps"); } @Test public void postLargeFileOverHttps() throws Throwable { logger.debug(">>> postLargeFileOverHttps"); withClient(config().setSslEngineFactory(createSslEngineFactory())).run(client -> { withServer(server).run(server -> { server.enqueueEcho(); Response resp = client.preparePost(getTargetUrl()).setBody(LARGE_IMAGE_FILE).setHeader(CONTENT_TYPE, "image/png").execute().get(); assertNotNull(resp); assertEquals(resp.getStatusCode(), HttpServletResponse.SC_OK); assertEquals(resp.getResponseBodyAsBytes().length, LARGE_IMAGE_FILE.length()); }); }); logger.debug("<<< postLargeFileOverHttps"); } @Test public void multipleSequentialPostRequestsOverHttps() throws Throwable { logger.debug(">>> multipleSequentialPostRequestsOverHttps"); withClient(config().setSslEngineFactory(createSslEngineFactory())).run(client -> { withServer(server).run(server -> { server.enqueueEcho(); server.enqueueEcho(); String body = "hello there"; Response response = client.preparePost(getTargetUrl()).setBody(body).setHeader(CONTENT_TYPE, "text/html").execute().get(TIMEOUT, SECONDS); assertEquals(response.getResponseBody(), body); response = client.preparePost(getTargetUrl()).setBody(body).setHeader(CONTENT_TYPE, "text/html").execute().get(TIMEOUT, SECONDS); assertEquals(response.getResponseBody(), body); }); }); logger.debug("<<< multipleSequentialPostRequestsOverHttps"); } @Test public void multipleConcurrentPostRequestsOverHttpsWithDisabledKeepAliveStrategy() throws Throwable { logger.debug(">>> multipleConcurrentPostRequestsOverHttpsWithDisabledKeepAliveStrategy"); KeepAliveStrategy keepAliveStrategy = new KeepAliveStrategy() { @Override public boolean keepAlive(Request ahcRequest, HttpRequest nettyRequest, HttpResponse nettyResponse) { return !ahcRequest.getUri().isSecured(); } }; withClient(config().setSslEngineFactory(createSslEngineFactory()).setKeepAliveStrategy(keepAliveStrategy)).run(client -> { withServer(server).run(server -> { server.enqueueEcho(); server.enqueueEcho(); server.enqueueEcho(); String body = "hello there"; client.preparePost(getTargetUrl()).setBody(body).setHeader(CONTENT_TYPE, "text/html").execute(); client.preparePost(getTargetUrl()).setBody(body).setHeader(CONTENT_TYPE, "text/html").execute(); Response response = client.preparePost(getTargetUrl()).setBody(body).setHeader(CONTENT_TYPE, "text/html").execute().get(); assertEquals(response.getResponseBody(), body); }); }); logger.debug("<<< multipleConcurrentPostRequestsOverHttpsWithDisabledKeepAliveStrategy"); } @Test public void reconnectAfterFailedCertificationPath() throws Throwable { logger.debug(">>> reconnectAfterFailedCertificationPath"); AtomicBoolean trust = new AtomicBoolean(); withClient(config().setMaxRequestRetry(0).setSslEngineFactory(createSslEngineFactory(trust))).run(client -> { withServer(server).run(server -> { server.enqueueEcho(); server.enqueueEcho(); String body = "hello there"; // first request fails because server certificate is rejected Throwable cause = null; try { client.preparePost(getTargetUrl()).setBody(body).setHeader(CONTENT_TYPE, "text/html").execute().get(TIMEOUT, SECONDS); } catch (final ExecutionException e) { cause = e.getCause(); } assertNotNull(cause); // second request should succeed trust.set(true); Response response = client.preparePost(getTargetUrl()).setBody(body).setHeader(CONTENT_TYPE, "text/html").execute().get(TIMEOUT, SECONDS); assertEquals(response.getResponseBody(), body); }); }); logger.debug("<<< reconnectAfterFailedCertificationPath"); } @Test(timeOut = 2000, expectedExceptions = SSLHandshakeException.class) public void failInstantlyIfNotAllowedSelfSignedCertificate() throws Throwable { logger.debug(">>> failInstantlyIfNotAllowedSelfSignedCertificate"); withClient(config().setMaxRequestRetry(0).setRequestTimeout(2000)).run(client -> { withServer(server).run(server -> { try { client.prepareGet(getTargetUrl()).execute().get(TIMEOUT, SECONDS); } catch (ExecutionException e) { throw e.getCause().getCause(); } }); }); logger.debug("<<< failInstantlyIfNotAllowedSelfSignedCertificate"); } @Test(groups = "standalone") public void testNormalEventsFired() throws Throwable { logger.debug(">>> testNormalEventsFired"); withClient(config().setSslEngineFactory(createSslEngineFactory())).run(client -> { withServer(server).run(server -> { EventCollectingHandler handler = new EventCollectingHandler(); server.enqueueEcho(); client.preparePost(getTargetUrl()).setBody("whatever").execute(handler).get(3, SECONDS); handler.waitForCompletion(3, SECONDS); Object[] expectedEvents = new Object[] { // CONNECTION_POOL_EVENT,// HOSTNAME_RESOLUTION_EVENT,// HOSTNAME_RESOLUTION_SUCCESS_EVENT,// CONNECTION_OPEN_EVENT,// CONNECTION_SUCCESS_EVENT,// TLS_HANDSHAKE_EVENT,// TLS_HANDSHAKE_SUCCESS_EVENT,// REQUEST_SEND_EVENT,// HEADERS_WRITTEN_EVENT,// STATUS_RECEIVED_EVENT,// HEADERS_RECEIVED_EVENT,// CONNECTION_OFFER_EVENT,// COMPLETED_EVENT }; assertEquals(handler.firedEvents.toArray(), expectedEvents, "Got " + Arrays.toString(handler.firedEvents.toArray())); }); }); logger.debug("<<< testNormalEventsFired"); } }