package org.zalando.stups.fullstop.jobs.common;

import org.apache.http.Header;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.net.URI;
import java.util.Optional;
import java.util.concurrent.Callable;

/**
 * Created by mrandi.
 */
public class HttpGetRootCall implements Callable<HttpCallResult> {

    private static final String EMPTY_STRING = "";
    private final Logger log = LoggerFactory.getLogger(HttpGetRootCall.class);

    private final CloseableHttpClient httpclient;

    private final String host;

    private final Integer allowedPort;

    public HttpGetRootCall(final CloseableHttpClient httpclient,
                           final String host, final Integer allowedPort) {
        this.httpclient = httpclient;
        this.host = host;
        this.allowedPort = allowedPort;
    }

    @Override
    public HttpCallResult call() throws Exception {
        final HttpCallResult callResult = new HttpCallResult(false, "");
        final String scheme = allowedPort == 443 ? "https" : "http";
        final URI uri = new URIBuilder()
                .setScheme(scheme)
                .setHost(host)
                .setPort(allowedPort)
                .build();

        log.debug("Checking URL: {}", uri);
        final HttpGet httpget = new HttpGet(uri);
        try (final CloseableHttpResponse response = httpclient.execute(httpget)) {
            final String location = Optional.ofNullable(response.getFirstHeader("Location"))
                    .map(Header::getValue)
                    .orElse(EMPTY_STRING);

            final int statusCode = response.getStatusLine().getStatusCode();
            if (statusCode == 401 || statusCode == 403) {
                log.debug("URI {} is secured GET / returned {}", uri, statusCode);
            } else if (String.valueOf(statusCode).startsWith("3")) {
                if (location.startsWith("https")) {
                    log.debug("URI {} redirects to an https location: {}", uri, location);
                } else {
                    log.debug("Call to {} redirects (status {}) to location with unsafe protocol ({})", uri, statusCode, location);
                    callResult.setIsOpen();
                    callResult.setMessage(String.format("Call to %s redirects (status %d) to location with unsafe protocol (%s)", uri, statusCode, location));
                }

            } else if (String.valueOf(statusCode).startsWith("5")) {
                log.info("URI {} is SECURE. GET / returned {}", uri, response);

            } else {
                log.info("URI {} is reachable. GET / returned {}", uri, response);
                callResult.setIsOpen();
                callResult.setMessage(String.format("%s returned status code %d, which means it is unsecured", uri, statusCode));
            }


        } catch (final IOException e) {
            log.debug("URI {} threw exception {}", uri, e.toString());
        }
        return callResult;
    }
}

@@ -2081,16 +2081,41 @@
 ith(%223%22)
+ && scheme.equals(%22http%22)
 ) %7B%0A    

handle redirect correctly