All Downloads are FREE. Search and download functionalities are using the official Maven repository.

restx.AbstractRequest Maven / Gradle / Ivy

There is a newer version: 1.2.0-rc2
Show newest version
package restx;

import com.google.common.base.Joiner;
import com.google.common.base.Optional;
import com.google.common.base.Splitter;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Iterables;
import com.google.common.collect.Iterators;

import java.util.Collection;
import java.util.List;
import java.util.Locale;
import java.util.Map;

/**
 * Date: 15/11/13
 * Time: 18:38
 */
public abstract class AbstractRequest implements RestxRequest {
    protected final HttpSettings httpSettings;

    protected AbstractRequest(HttpSettings httpSettings) {
        this.httpSettings = httpSettings;
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder("[RESTX REQUEST] ");
        sb.append(getHttpMethod()).append(" ").append(getRestxPath());
        dumpParameters(sb);
        return sb.toString();
    }

    private void dumpParameters(StringBuilder sb) {
        ImmutableMap> queryParams = getQueryParams();
        if (queryParams.isEmpty()) {
            return;
        }
        sb.append(" ? ");
        for (Map.Entry> entry : queryParams.entrySet()) {
            String key = entry.getKey();
            List values = entry.getValue();
            sb.append(key).append("=").append(
                    values.size() == 1
                            ? values.get(0)
                            : Joiner.on("&" + key + "=").join(values));
            sb.append("&");
        }
        sb.setLength(sb.length() - 1);
    }

    @Override
    public String getBaseUri() {
        return getScheme() + ":" + getBaseNetworkPath();
    }

    @Override
    public String getBaseNetworkPath() {
        checkProxyRequest();
        return "//" + getHost() + getBaseApiPath();
    }

    protected String getHost() {
        Optional host = httpSettings.host();
        if (host.isPresent()) {
            return host.get();
        }

        Optional forwardedHost = getHeader("X-Forwarded-Host");
        if (forwardedHost.isPresent()) {
            return Iterables.getFirst(Splitter.on(",").trimResults().split(forwardedHost.get()),
                    getHeader("Host").or(""));
        } else {
            return getHeader("Host").or("");
        }
    }

    @Override
    public boolean isSecured() {
        checkProxyRequest();
        return getScheme().equalsIgnoreCase("https");
    }

    protected String getScheme() {
        Optional proto = httpSettings.scheme().or(getHeader("X-Forwarded-Proto"));
        if (proto.isPresent()) {
            return proto.get();
        }
        Optional via = getHeader("Via");
        if (via.isPresent()) {
            boolean secured = via.get().toUpperCase(Locale.ENGLISH).startsWith("HTTPS");
            return secured ? "https" : "http";
        } else {
            return getLocalScheme();
        }
    }

    @Override
    public String getClientAddress() {
        // see http://en.wikipedia.org/wiki/X-Forwarded-For
        checkProxyRequest();
        Optional xff = getHeader("X-Forwarded-For");
        if (xff.isPresent()) {
            return Iterables.getFirst(Splitter.on(",").trimResults().split(xff.get()),
                    getLocalClientAddress());
        } else {
            return getLocalClientAddress();
        }
    }

    protected void checkProxyRequest() {
        if (getHeader("X-Forwarded-Proto").isPresent()) {
            String localClientAddress = getLocalClientAddress();
            Collection forwardedSupport = httpSettings.forwardedSupport();
            if (!forwardedSupport.contains("all")
                    && !forwardedSupport.contains(localClientAddress)) {
                throw new IllegalArgumentException(
                        "Unauthorized proxy request from " + localClientAddress + "\n" +
                                "If you are the application developer or operator, you can set `restx.http.XForwardedSupport`\n" +
                                "system property to allow proxy requests from this proxy IP with:\n" +
                                "  -Drestx.http.XForwardedSupport=" + localClientAddress + "\n" +
                                "Or if you want to allow any proxy request:\n" +
                                "  -Drestx.http.XForwardedSupport=all");
            }
        }
    }

    /**
     * Returns the client address of this request, without taking proxy into account
     * @return the client address of this request, without taking proxy into account
     */
    protected abstract String getLocalClientAddress();


    /**
     * The path on which restx is mounted.
     * Eg /api
     *
     * @return the path on which restx is mounted.
     */
    protected abstract String getBaseApiPath();

    /**
     * The URL scheme used for this request, without taking proxy into account.
     * Eg: http, https
     *
     * @return URL scheme used for this request, without taking proxy into account.
     */
    protected abstract String getLocalScheme();

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy