When HttpServletRequest getHeader return unknown?

3.2k views Asked by At

I am using the below code (Copied from another post - How do I get the remote address of a client in servlet?) to get the client IP address along with the proxy server (SpringBoot Appln deployed in PCF).

  public static String getClientIpAddr(HttpServletRequest request)
  {
    String ip = request.getHeader("X-Forwarded-For");
    if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip))
    {
      ip = request.getHeader("Proxy-Client-IP");
    }
    if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip))
    {
      ip = request.getHeader("WL-Proxy-Client-IP");
    }
    if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip))
    {
      ip = request.getHeader("HTTP_CLIENT_IP");
    }
    if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip))
    {
      ip = request.getHeader("HTTP_X_FORWARDED_FOR");
    }
    if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip))
    {
      ip = request.getRemoteAddr();
    }
    return ip;
  }

request.getHeader("X-Forwarded-For"); /request.getRemoteAddr(); (when run from local) gives the expected result. I really didn't understand the uses of other conditions.

  1. In all conditions I see "unknown".equalsIgnoreCase(IP) is used. But when I try to access request.getHeader("Proxy-Client-IP") or any junk string, I am getting null. When HttpServletRequest getHeader return unknown? Can this be ignored?
  2. What is the use of Proxy-Client-IP/HTTP_CLIENT_IP. I guess it is used to get client IP alone (without proxy server IP). Is it specific to a particular server? if so which server. Can this be ignored in Spring boot application
  3. I guess 'WL-Proxy-Client-IP' is specific to WebLogic. Can this be ignored as well?
  4. I believe the HTTP_ prefix is specific to PHP (HTTP_X_FORWARDED_FOR and HTTP_CLIENT_IP.) Is it necessary in the SpringBoot application?
  5. I feel the below code is more than enough to get the client IP address along with the proxy server (provided I use spring boot with embedded tomcat and deploy the code in PCF). Could you please confirm?

    private static String getClientIpAddr(HttpServletRequest httpRequest)
    {
      String clientIp = httpRequest.getHeader("X-Forwarded-For");
    
      if (clientIp == null || clientIp.length() == 0)
      {
        clientIp = httpRequest.getRemoteAddr();
      }
      return clientIp;
    }
    
1

There are 1 answers

2
M. Deinum On

You probably want something like this.

public class HttpRequestHelper {

    private static final String[] HEADERS= {"X-Forwarded-For", "Proxy-Client-IP", "WL-Proxy-Client-IP", "HTTP_CLIENT_IP", "HTTP_X_FORWARDED_FOR"};

    public static String getClientIpAddr(HttpServletRequest request) {
        for (String header : HEADERS) {
            String ip = request.getHeader(header);
            if (ip != null && ip.length() > 0) {                    
                return StringUtils.commaDelimitedListToStringArray(ip)[0];
            }
        }
        return request.getRemoteAddr();
    }    
}

This will try al headers (in the given order) and if one exists return that. Else it will fallback to the request.getRemoteAddr(). Achieves the same with a lot less if statements.

I also factored in the case for potential multiple ip-addresses in the X-Forwarded-For header. It will always return the first element in the parsed array.