Package org.mapfish.print.http

Source Code of org.mapfish.print.http.HttpProxyTest

/*
* Copyright (C) 2014  Camptocamp
*
* This file is part of MapFish Print
*
* MapFish Print is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* MapFish Print is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with MapFish Print.  If not, see <http://www.gnu.org/licenses/>.
*/

package org.mapfish.print.http;

import com.google.common.collect.Lists;
import com.google.common.io.ByteStreams;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpServer;
import com.sun.net.httpserver.HttpsConfigurator;
import com.sun.net.httpserver.HttpsParameters;
import com.sun.net.httpserver.HttpsServer;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mapfish.print.AbstractMapfishSpringTest;
import org.mapfish.print.Constants;
import org.mapfish.print.config.Configuration;
import org.mapfish.print.config.ConfigurationFactory;
import org.mapfish.print.processor.http.matcher.DnsHostMatcher;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.client.ClientHttpRequest;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.URI;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.util.Collections;
import java.util.List;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.TrustManagerFactory;

import static org.junit.Assert.assertEquals;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {
        AbstractMapfishSpringTest.DEFAULT_SPRING_XML,
        "classpath:/org/mapfish/print/http/proxy/application-context-proxy-test.xml"
})
public class HttpProxyTest {
    private static final int PROXY_PORT = 23434;
    static final int HTTPS_PROXY_PORT = 23433;
    static final String LOCALHOST = "localhost";
    private static final String MESSAGE_FROM_PROXY = "Message From Proxy";
    private static final int TARGET_PORT = 22434;
    private static HttpServer targetServer;
    private static HttpServer proxyServer;
    private static HttpsServer httpsServer;

    @Autowired
    ConfigurationFactory configurationFactory;
    @Autowired
    private MfClientHttpRequestFactoryImpl requestFactory;

    @BeforeClass
    public static void setUp() throws Exception {
        proxyServer = HttpServer.create(new InetSocketAddress(LOCALHOST, PROXY_PORT), 0);
        proxyServer.start();

        targetServer = HttpServer.create(new InetSocketAddress(LOCALHOST, TARGET_PORT), 0);
        targetServer.start();

        httpsServer = createHttpsServer(HTTPS_PROXY_PORT);
    }

    @AfterClass
    public static void tearDown() throws Exception {
        proxyServer.stop(0);
        targetServer.stop(0);
        httpsServer.stop(0);
    }

    @Test
    public void testValidate() throws Exception {
        final HttpProxy httpProxy = new HttpProxy();

        List<Throwable> errors = Lists.newArrayList();

        Configuration configuration = new Configuration();
        httpProxy.validate(errors, configuration);
        assertEquals(1, errors.size());

        httpProxy.setHost(LOCALHOST);
        httpProxy.setPort(PROXY_PORT);

        errors.clear();
        httpProxy.validate(errors, configuration);
        assertEquals(0, errors.size());

    }

    @Test
    public void testExecuteProxy() throws Exception {
        final HttpProxy httpProxy = new HttpProxy();
        httpProxy.setHost(LOCALHOST);
        httpProxy.setPort(PROXY_PORT);

        final String path = "/request";
        proxyServer.createContext(path, new HttpHandler() {
            @Override
            public void handle(HttpExchange httpExchange) throws IOException {
                respond(httpExchange, MESSAGE_FROM_PROXY, 200);
            }
        });

        assertCorrectResponse(httpProxy, MESSAGE_FROM_PROXY, "http://" + LOCALHOST + ":" + TARGET_PORT, path);
    }

    @Test
    public void testExecuteProxyWithUsername() throws Exception {
        final HttpProxy httpProxy = new HttpProxy();
        httpProxy.setHost(LOCALHOST);
        httpProxy.setPort(HTTPS_PROXY_PORT);
        httpProxy.setUsername("username");

        final String path = "/username";
        httpsServer.createContext(path, new HttpHandler() {
            @Override
            public void handle(HttpExchange httpExchange) throws IOException {
                final String authorization = httpExchange.getRequestHeaders().getFirst("Authorization");
                if (authorization == null) {
                    httpExchange.getResponseHeaders().add("WWW-Authenticate", "Basic realm=\"Test Site\"");
                    httpExchange.sendResponseHeaders(401, 0);
                    httpExchange.close();
                } else {
                    final String expectedAuth = "Basic dXNlcm5hbWU6bnVsbA==";
                    if (authorization.equals(expectedAuth)) {
                        respond(httpExchange, MESSAGE_FROM_PROXY, 200);
                    } else {
                        final String errorMessage = "Expected authorization:\n'" + expectedAuth + "' but got:\n'" + authorization + "'";
                        respond(httpExchange, errorMessage, 500);
                    }
                }
            }
        });

        assertCorrectResponse(httpProxy, MESSAGE_FROM_PROXY, "http://" + LOCALHOST + ":" + TARGET_PORT, path);
    }

    @Test
    public void testExecuteProxyWithUsernameAndPassword() throws Exception {
        final HttpProxy httpProxy = new HttpProxy();
        httpProxy.setHost(LOCALHOST);
        httpProxy.setPort(HTTPS_PROXY_PORT);
        httpProxy.setUsername("username");
        httpProxy.setPassword("password");

        final String path = "/usernameAndPassword";
        httpsServer.createContext(path, new HttpHandler() {
            @Override
            public void handle(HttpExchange httpExchange) throws IOException {
                final String authorization = httpExchange.getRequestHeaders().getFirst("Authorization");
                if (authorization == null) {
                    httpExchange.getResponseHeaders().add("WWW-Authenticate", "Basic realm=\"Test Site\"");
                    httpExchange.sendResponseHeaders(401, 0);
                    httpExchange.close();
                } else {
                    final String expectedAuth = "Basic dXNlcm5hbWU6cGFzc3dvcmQ=";
                    if (authorization.equals(expectedAuth)) {
                        respond(httpExchange, MESSAGE_FROM_PROXY, 200);
                    } else {
                        final String errorMessage = "Expected authorization:\n'" + expectedAuth + "' but got:\n'" + authorization + "'";
                        respond(httpExchange, errorMessage, 500);
                    }
                }
            }
        });

        assertCorrectResponse(httpProxy, MESSAGE_FROM_PROXY, "http://" + LOCALHOST + ":" + TARGET_PORT, path);
    }

    @Test
    public void testExecuteProxyNoMatcher() throws Exception {
        final HttpProxy httpProxy = new HttpProxy();
        httpProxy.setHost(LOCALHOST);
        httpProxy.setPort(PROXY_PORT);
        final DnsHostMatcher dnsHostMatcher = new DnsHostMatcher();
        dnsHostMatcher.setHost("google.com");
        httpProxy.setMatchers(Lists.newArrayList(dnsHostMatcher));
        final String message = "Target was reached without proxy";

        final String path = "/nomatch";
        targetServer.createContext(path, new HttpHandler() {
            @Override
            public void handle(HttpExchange httpExchange) throws IOException {
                respond(httpExchange, message, 200);
            }
        });
        proxyServer.createContext(path, new HttpHandler() {
            @Override
            public void handle(HttpExchange httpExchange) throws IOException {
                String msg = "Proxy was reached but in this test the proxy should not have been used.";
                respond(httpExchange, msg, 500);
            }
        });

        assertCorrectResponse(httpProxy, message, "http://" + LOCALHOST + ":" + TARGET_PORT, path);
    }

    private void assertCorrectResponse(HttpProxy httpProxy, String expected, String target, String path) throws Exception {
        assertCorrectResponse(configurationFactory, requestFactory, httpProxy, expected, target, path);
    }

    static void assertCorrectResponse(ConfigurationFactory configurationFactory, MfClientHttpRequestFactoryImpl requestFactory,
                                             HttpCredential httpCredential, String expected, String target, String path) throws Exception {
        final File configFile = AbstractMapfishSpringTest.getFile(HttpProxyTest.class, "proxy/config.yaml");
        configurationFactory.setDoValidation(false);
        final Configuration config = configurationFactory.getConfig(configFile);
        final CertificateStore certificateStore = new CertificateStore();
        certificateStore.setConfiguration(config);
        certificateStore.setPassword("password");
        certificateStore.setUri(getKeystoreFile().toURI());

        config.setCertificateStore(certificateStore);
        if (httpCredential instanceof HttpProxy) {
            config.setProxies(Collections.singletonList((HttpProxy)httpCredential));
        } else {
            config.setCredentials(Collections.singletonList(httpCredential));
        }

        ConfigFileResolvingHttpRequestFactory clientHttpRequestFactory = new ConfigFileResolvingHttpRequestFactory(requestFactory,
                config);

        URI uri = new URI(target + path);
        final ClientHttpRequest request = clientHttpRequestFactory.createRequest(uri, HttpMethod.GET);
        final ClientHttpResponse response = request.execute();

        final String message = new String(ByteStreams.toByteArray(response.getBody()), Constants.DEFAULT_CHARSET);
        assertEquals(message, HttpStatus.OK, response.getStatusCode());

        assertEquals(expected, message);
    }

    private static SSLContext getSslContext() throws NoSuchAlgorithmException, KeyStoreException, IOException, CertificateException,
            UnrecoverableKeyException, KeyManagementException {
        SSLContext sslContext = SSLContext.getInstance("TLS");

        char[] password = "password".toCharArray();

        KeyStore ks = KeyStore.getInstance("JKS");
        final File keystoreFile = getKeystoreFile();
        FileInputStream fis = new FileInputStream(keystoreFile);
        ks.load(fis, password);

        KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
        kmf.init(ks, password);

        TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
        tmf.init(ks);

        sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
        return sslContext;
    }

    private static File getKeystoreFile() {
        return AbstractMapfishSpringTest.getFile(HttpProxyTest.class, "proxy/keystore.jks");
    }

    public static void respond(HttpExchange httpExchange, String errorMessage, int responseCode) throws IOException {
        final byte[] bytes = errorMessage.getBytes(Constants.DEFAULT_CHARSET);
        httpExchange.sendResponseHeaders(responseCode, bytes.length);
        httpExchange.getResponseBody().write(bytes);
        httpExchange.close();
    }

    public static HttpsServer createHttpsServer(int httpsProxyPort) throws Exception {
        HttpsServer httpsServer = HttpsServer.create(new InetSocketAddress(httpsProxyPort), 0);
        SSLContext sslContext = getSslContext();

        final SSLEngine m_engine = sslContext.createSSLEngine();

        httpsServer.setHttpsConfigurator(new HttpsConfigurator(sslContext) {
            public void configure(HttpsParameters params) {
                params.setCipherSuites(m_engine.getEnabledCipherSuites());
                params.setProtocols(m_engine.getEnabledProtocols());
            }
        });
        httpsServer.start();

        return httpsServer;
    }
}
TOP

Related Classes of org.mapfish.print.http.HttpProxyTest

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.