/* * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All 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://aws.amazon.com/apache2.0 * * This file 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 com.amazonaws.http; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; import com.amazonaws.ClientConfiguration; import com.amazonaws.SDKGlobalConfiguration; import com.amazonaws.util.StringUtils; import org.junit.Before; import org.junit.Test; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.ProtocolException; import java.net.URI; import java.net.URISyntaxException; import java.net.URL; import java.security.cert.Certificate; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLPeerUnverifiedException; public class UrlHttpClientTest { private ClientConfiguration conf; private MockUrlHttpClient client; @Before public void setup() { conf = new ClientConfiguration(); client = new MockUrlHttpClient(conf); } // @Test public void testBasicCurlBuilder() throws URISyntaxException, IOException { conf.setCurlLogging(true); final HttpRequest request = new HttpRequest("POST", new URI("https://www.test.com")); client.execute(request); assertEquals(1, client.getLogList().size()); assertEquals("curl -X POST https://www.test.com", client.getLogList().get(0)); } // @Test public void testCurlBuilderWithHeaders() throws URISyntaxException, IOException { conf.setCurlLogging(true); final Map<String, String> headers = new HashMap<String, String>(); headers.put("key1", "value1"); headers.put("key2", "value2"); final HashSet<String> expectedCurlHeaders = new HashSet<String>(); for (final Map.Entry<String, String> entry : headers.entrySet()) { expectedCurlHeaders.add("\"" + entry.getKey() + ":" + entry.getValue() + "\""); } final HttpRequest request = new HttpRequest("POST", new URI("https://www.test.com"), headers, null /* stream */); client.execute(request); assertEquals(client.getLogList().size(), 1); final String[] parts = client.getLogList().get(0).split(" "); assertEquals(8, parts.length); assertEquals("curl", parts[0]); assertEquals("-X", parts[1]); assertEquals("POST", parts[2]); assertEquals("-H", parts[3]); assertTrue(expectedCurlHeaders.contains(parts[4])); expectedCurlHeaders.remove(parts[4]); assertEquals("-H", parts[5]); assertTrue(expectedCurlHeaders.contains(parts[6])); expectedCurlHeaders.remove(parts[6]); assertTrue(expectedCurlHeaders.isEmpty()); assertEquals("https://www.test.com", parts[7]); } // @Test public void testCurlBuilderWithData() throws URISyntaxException, IOException { conf.setCurlLogging(true); final String dataString = "content"; final byte[] data = dataString.getBytes("UTF-8"); final Map<String, String> headers = new HashMap<String, String>(); headers.put(HttpHeader.CONTENT_LENGTH, String.valueOf(data.length)); final InputStream stream = new ByteArrayInputStream(data); final HttpRequest request = new HttpRequest("POST", new URI("https://www.test.com"), headers, stream); client.execute(request); assertEquals(1, client.getLogList().size()); assertEquals( "curl -X POST -H \"Content-Length:" + String.valueOf(data.length) + "\" -d '" + dataString + "' https://www.test.com", client.getLogList().get(0)); } // @Test public void testOverflowInCurl() throws URISyntaxException, IOException { conf.setCurlLogging(true); final long tooManyBytes = Integer.MAX_VALUE + 1L; final InputStream stream = new ByteArrayInputStream("content".getBytes("UTF-8")); final Map<String, String> headers = new HashMap<String, String>(); headers.put(HttpHeader.CONTENT_LENGTH, String.valueOf(tooManyBytes)); final HttpRequest request = new HttpRequest("POST", new URI("https://www.test.com"), headers, stream); request.setStreaming(true); client.execute(request); assertEquals(1,client.getLogList().size()); assertEquals( "Failed to create curl, content too long", client.getLogList().get(0)); } @Test public void testApplyHeaders() throws ProtocolException, MalformedURLException, URISyntaxException { final Map<String, String> headers = new HashMap<String, String>(); headers.put("testKey", "testValue"); headers.put(HttpHeader.CONTENT_LENGTH, "I should not be added"); headers.put(HttpHeader.HOST, "I should not be added"); final HttpRequest request = new HttpRequest("POST", new URI("https://www.test.com"), headers, null); final HttpsURLConnection conn = (HttpsURLConnection) client.applyHeadersAndMethod(request, new MockHttpURLConnection(new URL("https://www.test.com"))); assertEquals(conn.getRequestProperty("testKey"), "testValue"); assertNull(conn.getRequestProperty(HttpHeader.CONTENT_LENGTH)); assertNull(conn.getRequestProperty(HttpHeader.HOST)); assertEquals(conn.getRequestMethod(), "POST"); } @Test public void testConfigureConnection() throws MalformedURLException, URISyntaxException { final Map<String, String> headers = new HashMap<String, String>(); final HttpRequest request = new HttpRequest("POST", new URI("https://www.test.com"), headers, null); final HttpsURLConnection conn = new MockHttpURLConnection(new URL("https://www.test.com")); client.configureConnection(request, conn); assertEquals(conn.getConnectTimeout(), conf.getConnectionTimeout()); assertEquals(conn.getReadTimeout(), conf.getSocketTimeout()); assertSame(conn.getHostnameVerifier(), HttpsURLConnection.getDefaultHostnameVerifier()); assertFalse(conn.getInstanceFollowRedirects()); assertFalse("disable cache", conn.getUseCaches()); } //commenting as we donot support this. See https://support.google.com/faqs/answer/6346016 //@Test public void testConfigureConnectionWithCertCheckingDisabled() throws MalformedURLException, URISyntaxException { final Map<String, String> headers = new HashMap<String, String>(); final HttpRequest request = new HttpRequest("POST", new URI("https://www.test.com"), headers, null); final HttpsURLConnection conn = new MockHttpURLConnection(new URL("https://www.test.com")); System.setProperty(SDKGlobalConfiguration.DISABLE_CERT_CHECKING_SYSTEM_PROPERTY, "true"); client.configureConnection(request, conn); assertEquals(conn.getConnectTimeout(), conf.getConnectionTimeout()); assertEquals(conn.getReadTimeout(), conf.getSocketTimeout()); assertFalse(conn.getInstanceFollowRedirects()); assertFalse("disable cache", conn.getUseCaches()); assertTrue(conn.getHostnameVerifier().verify("https://some.bogus.com", null)); assertTrue(conn.getHostnameVerifier() .verify("https://bucket.withdot.s3.amazonaws.com", null)); System.clearProperty(SDKGlobalConfiguration.DISABLE_CERT_CHECKING_SYSTEM_PROPERTY); } @Test public void testCreateResponse() throws URISyntaxException, IOException { final HttpRequest request = new HttpRequest("PUT", new URI("https://www.test.com")); final MockHttpURLConnection conn = new MockHttpURLConnection(new URL("https://www.test.com")); final Map<String, List<String>> headerFields = new HashMap<String, List<String>>(); final List<String> header1 = new ArrayList<String>(); header1.add("value1"); header1.add("ExtraValue"); headerFields.put("key1", header1); final List<String> header2 = new ArrayList<String>(); header2.add("value2"); headerFields.put("key2", header2); final List<String> nullHeader = new ArrayList<String>(); headerFields.put(null, nullHeader); conn.setHeaderFields(headerFields); conn.setResponseCode(200); conn.setErrorStream(null); final ByteArrayInputStream bais = new ByteArrayInputStream("test".getBytes(StringUtils.UTF8)); conn.setInputStream(bais); conn.setResponseMessage("TestMessage"); final HttpResponse response = client.createHttpResponse(request, conn); assertEquals(response.getHeaders().get("key1"), "value1"); assertEquals(response.getHeaders().get("key2"), "value2"); assertEquals(response.getHeaders().size(), 2); assertEquals(response.getStatusCode(), 200); assertEquals(response.getStatusText(), "TestMessage"); assertSame(response.getContent(), bais); } @Test public void testWriteContentToConnection() throws URISyntaxException, IOException { final ByteArrayInputStream bais = new ByteArrayInputStream("Content".getBytes(StringUtils.UTF8)); final Map<String, String> headers = new HashMap<String, String>(); headers.put(HttpHeader.CONTENT_LENGTH, String.valueOf("Content".getBytes(StringUtils.UTF8).length)); final HttpRequest request = new HttpRequest("POST", new URI("https://www.test.com"), headers, bais); final MockHttpURLConnection connection = new MockHttpURLConnection( new URL("https://www.test.com")); final ByteArrayOutputStream baos = new ByteArrayOutputStream(); connection.setOutputStream(baos); client.writeContentToConnection(request, connection); final ByteArrayOutputStream connOs = (ByteArrayOutputStream) connection.getOutputStream(); assertEquals(new String(connOs.toByteArray(), StringUtils.UTF8), "Content"); } } class MockHttpURLConnection extends HttpsURLConnection { String responseMessage; int responseCode; InputStream errorStream; InputStream inputStream; OutputStream outputStream; Map<String, List<String>> headerFields; protected MockHttpURLConnection(URL u) { super(u); } public void setOutputStream(OutputStream os) { outputStream = os; } @Override public OutputStream getOutputStream() { return outputStream; } @Override public String getResponseMessage() { return responseMessage; } public void setResponseMessage(String responseMessage) { this.responseMessage = responseMessage; } @Override public int getResponseCode() { return responseCode; } public void setResponseCode(int responseCode) { this.responseCode = responseCode; } @Override public InputStream getErrorStream() { return errorStream; } public void setErrorStream(InputStream errorStream) { this.errorStream = errorStream; } @Override public InputStream getInputStream() { return inputStream; } public void setInputStream(InputStream inputStream) { this.inputStream = inputStream; } @Override public Map<String, List<String>> getHeaderFields() { return headerFields; } public void setHeaderFields(Map<String, List<String>> headerFields) { this.headerFields = headerFields; } @Override public void disconnect() { } @Override public boolean usingProxy() { return false; } @Override public void connect() throws IOException { } @Override public String getCipherSuite() { return null; } @Override public Certificate[] getLocalCertificates() { return null; } @Override public Certificate[] getServerCertificates() throws SSLPeerUnverifiedException { return null; } } class MockUrlHttpClient extends UrlHttpClient { private final ArrayList<String> mLogList = new ArrayList<String>(); public MockUrlHttpClient(ClientConfiguration config) { super(config); } public ArrayList<String> getLogList() { return mLogList; } @Override protected void printToLog(String message) { mLogList.add(message); } @Override protected HttpURLConnection getUrlConnection(URL url) throws IOException { final MockHttpURLConnection connection = new MockHttpURLConnection(url); connection.setOutputStream(new ByteArrayOutputStream()); return connection; } }