public void invoke()

in java/org/apache/catalina/valves/RemoteIpValve.java [568:746]


    public void invoke(Request request, Response response) throws IOException, ServletException {
        final String originalRemoteAddr = request.getRemoteAddr();
        final String originalRemoteHost = request.getRemoteHost();
        final String originalScheme = request.getScheme();
        final boolean originalSecure = request.isSecure();
        final String originalServerName = request.getServerName();
        final String originalLocalName = isChangeLocalName() ? request.getLocalName() : null;
        final int originalServerPort = request.getServerPort();
        final int originalLocalPort = request.getLocalPort();
        final String originalProxiesHeader = request.getHeader(proxiesHeader);
        final String originalRemoteIpHeader = request.getHeader(remoteIpHeader);
        boolean isInternal = internalProxies != null && internalProxies.matcher(originalRemoteAddr).matches();

        if (isInternal || (trustedProxies != null && trustedProxies.matcher(originalRemoteAddr).matches())) {
            String remoteIp = null;
            Deque<String> proxiesHeaderValue = new ArrayDeque<>();
            StringBuilder concatRemoteIpHeaderValue = new StringBuilder();

            for (Enumeration<String> e = request.getHeaders(remoteIpHeader); e.hasMoreElements();) {
                if (!concatRemoteIpHeaderValue.isEmpty()) {
                    concatRemoteIpHeaderValue.append(", ");
                }

                concatRemoteIpHeaderValue.append(e.nextElement());
            }

            String[] remoteIpHeaderValue = StringUtils.splitCommaSeparated(concatRemoteIpHeaderValue.toString());
            int idx;
            if (!isInternal) {
                proxiesHeaderValue.addFirst(originalRemoteAddr);
            }
            // loop on remoteIpHeaderValue to find the first trusted remote ip and to build the proxies chain
            for (idx = remoteIpHeaderValue.length - 1; idx >= 0; idx--) {
                String currentRemoteIp = remoteIpHeaderValue[idx];
                remoteIp = currentRemoteIp;
                if (internalProxies != null && internalProxies.matcher(currentRemoteIp).matches()) {
                    // do nothing, internalProxies IPs are not appended to the
                } else if (trustedProxies != null && trustedProxies.matcher(currentRemoteIp).matches()) {
                    proxiesHeaderValue.addFirst(currentRemoteIp);
                } else {
                    idx--; // decrement idx because break statement doesn't do it
                    break;
                }
            }
            // continue to loop on remoteIpHeaderValue to build the new value of the remoteIpHeader
            Deque<String> newRemoteIpHeaderValue = new ArrayDeque<>();
            for (; idx >= 0; idx--) {
                String currentRemoteIp = remoteIpHeaderValue[idx];
                newRemoteIpHeaderValue.addFirst(currentRemoteIp);
            }
            if (remoteIp != null) {

                request.setRemoteAddr(remoteIp);
                if (request.getConnector().getEnableLookups()) {
                    // This isn't a lazy lookup but that would be a little more
                    // invasive - mainly in Request.getRemoteHost() - and if
                    // enableLookups is true it seems reasonable that the
                    // hotsname will be required so look it up here.
                    try {
                        InetAddress inetAddress = InetAddress.getByName(remoteIp);
                        // We know we need a DNS look up so use getCanonicalHostName()
                        request.setRemoteHost(inetAddress.getCanonicalHostName());
                    } catch (UnknownHostException e) {
                        log.debug(sm.getString("remoteIpValve.invalidRemoteAddress", remoteIp), e);
                        request.setRemoteHost(remoteIp);
                    }
                } else {
                    request.setRemoteHost(remoteIp);
                }

                if (proxiesHeaderValue.isEmpty()) {
                    request.getCoyoteRequest().getMimeHeaders().removeHeader(proxiesHeader);
                } else {
                    String commaDelimitedListOfProxies = StringUtils.join(proxiesHeaderValue);
                    request.getCoyoteRequest().getMimeHeaders().setValue(proxiesHeader)
                            .setString(commaDelimitedListOfProxies);
                }
                if (newRemoteIpHeaderValue.isEmpty()) {
                    request.getCoyoteRequest().getMimeHeaders().removeHeader(remoteIpHeader);
                } else {
                    String commaDelimitedRemoteIpHeaderValue = StringUtils.join(newRemoteIpHeaderValue);
                    request.getCoyoteRequest().getMimeHeaders().setValue(remoteIpHeader)
                            .setString(commaDelimitedRemoteIpHeaderValue);
                }
            }

            if (protocolHeader != null) {
                String protocolHeaderValue = request.getHeader(protocolHeader);
                if (protocolHeaderValue == null) {
                    // Don't modify the secure, scheme and serverPort attributes
                    // of the request
                } else if (isForwardedProtoHeaderValueSecure(protocolHeaderValue)) {
                    request.setSecure(true);
                    request.getCoyoteRequest().scheme().setString("https");
                    setPorts(request, httpsServerPort);
                } else {
                    request.setSecure(false);
                    request.getCoyoteRequest().scheme().setString("http");
                    setPorts(request, httpServerPort);
                }
            }

            if (hostHeader != null) {
                String hostHeaderValue = request.getHeader(hostHeader);
                if (hostHeaderValue != null) {
                    try {
                        int portIndex = Host.parse(hostHeaderValue);
                        if (portIndex > -1) {
                            log.debug(sm.getString("remoteIpValve.invalidHostWithPort", hostHeaderValue, hostHeader));
                            hostHeaderValue = hostHeaderValue.substring(0, portIndex);
                        }

                        request.getCoyoteRequest().serverName().setString(hostHeaderValue);
                        if (isChangeLocalName()) {
                            request.getCoyoteRequest().localName().setString(hostHeaderValue);
                        }

                    } catch (IllegalArgumentException iae) {
                        log.debug(sm.getString("remoteIpValve.invalidHostHeader", hostHeaderValue, hostHeader));
                    }
                }
            }

            request.setAttribute(Globals.REQUEST_FORWARDED_ATTRIBUTE, Boolean.TRUE);

            if (log.isTraceEnabled()) {
                log.trace("Incoming request " + request.getRequestURI() + " with originalRemoteAddr [" +
                        originalRemoteAddr + "], originalRemoteHost=[" + originalRemoteHost + "], originalSecure=[" +
                        originalSecure + "], originalScheme=[" + originalScheme + "], originalServerName=[" +
                        originalServerName + "], originalServerPort=[" + originalServerPort +
                        "] will be seen as newRemoteAddr=[" + request.getRemoteAddr() + "], newRemoteHost=[" +
                        request.getRemoteHost() + "], newSecure=[" + request.isSecure() + "], newScheme=[" +
                        request.getScheme() + "], newServerName=[" + request.getServerName() + "], newServerPort=[" +
                        request.getServerPort() + "]");
            }
        } else {
            if (log.isTraceEnabled()) {
                log.trace("Skip RemoteIpValve for request " + request.getRequestURI() + " with originalRemoteAddr '" +
                        request.getRemoteAddr() + "'");
            }
        }
        if (requestAttributesEnabled) {
            request.setAttribute(AccessLog.REMOTE_ADDR_ATTRIBUTE, request.getRemoteAddr());
            request.setAttribute(Globals.REMOTE_ADDR_ATTRIBUTE, request.getRemoteAddr());
            request.setAttribute(AccessLog.REMOTE_HOST_ATTRIBUTE, request.getRemoteHost());
            request.setAttribute(AccessLog.PROTOCOL_ATTRIBUTE, request.getProtocol());
            request.setAttribute(AccessLog.SERVER_NAME_ATTRIBUTE, request.getServerName());
            request.setAttribute(AccessLog.SERVER_PORT_ATTRIBUTE, Integer.valueOf(request.getServerPort()));
        }
        try {
            getNext().invoke(request, response);
        } finally {
            if (!request.isAsync()) {
                request.setRemoteAddr(originalRemoteAddr);
                request.setRemoteHost(originalRemoteHost);
                request.setSecure(originalSecure);
                request.getCoyoteRequest().scheme().setString(originalScheme);
                request.getCoyoteRequest().serverName().setString(originalServerName);
                if (isChangeLocalName()) {
                    request.getCoyoteRequest().localName().setString(originalLocalName);
                }
                request.setServerPort(originalServerPort);
                request.setLocalPort(originalLocalPort);

                MimeHeaders headers = request.getCoyoteRequest().getMimeHeaders();
                if (originalProxiesHeader == null || originalProxiesHeader.isEmpty()) {
                    headers.removeHeader(proxiesHeader);
                } else {
                    headers.setValue(proxiesHeader).setString(originalProxiesHeader);
                }

                if (originalRemoteIpHeader == null || originalRemoteIpHeader.isEmpty()) {
                    headers.removeHeader(remoteIpHeader);
                } else {
                    headers.setValue(remoteIpHeader).setString(originalRemoteIpHeader);
                }
            }
        }
    }