class ProxyFilter implements ContainerRequestFilter {

    @Override
    public void filter(ContainerRequestContext ctx) throws IOException {
        String host = getValue(ctx.getHeaders(), HOST_PROXY_HEADER);
        String scheme = getValue(ctx.getHeaders(), PROTO_PROXY_HEADER);

        // if our request does not have neither headers end right here
        if (scheme == null && host == null) {
            return;
        }

        UriInfo uriInfo = ctx.getUriInfo();
        URI requestUri = uriInfo.getRequestUri();

        UriBuilder baseBuilder = uriInfo.getBaseUriBuilder();
        UriBuilder requestBuilder = uriInfo.getRequestUriBuilder();

        // if only one of our headers is missing replace it with default value
        if (scheme == null) {
            scheme = requestUri.getScheme();
        }

        if (host == null) {
            host = requestUri.getHost();

            int port = requestUri.getPort();
            if (port != -1) {
                host += (":" + port);
            }
        }

        // create a new URI from the current scheme + host in order to validate
        // it
        String uriString = scheme + "://" + host;

        URI newBaseUri = null;
        try {
            newBaseUri = new URI(uriString);
        } catch (URISyntaxException e) {
            logger.error("Invalid X-Forwarded-Proto + X-Forwarded-Host header combination: {}", uriString, e);
            return;
        }

        // URI is valid replace base and request builder parts with ones
        // obtained from the given headers
        host = newBaseUri.getHost();
        if (host != null) {
            baseBuilder.host(host);
            requestBuilder.host(host);
        }

        int port = newBaseUri.getPort();
        baseBuilder.port(port);
        requestBuilder.port(port);

        scheme = newBaseUri.getScheme();
        if (scheme != null) {
            baseBuilder.scheme(scheme);
            requestBuilder.scheme(scheme);
        }

        ctx.setRequestUri(baseBuilder.build(), requestBuilder.build());
    }

}