001/** 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018 019package org.apache.hadoop.lib.servlet; 020 021 022import org.apache.hadoop.classification.InterfaceAudience; 023 024import javax.servlet.Filter; 025import javax.servlet.FilterChain; 026import javax.servlet.FilterConfig; 027import javax.servlet.ServletException; 028import javax.servlet.ServletRequest; 029import javax.servlet.ServletResponse; 030import java.io.IOException; 031import java.net.InetAddress; 032import java.net.UnknownHostException; 033import org.slf4j.Logger; 034import org.slf4j.LoggerFactory; 035 036/** 037 * Filter that resolves the requester hostname. 038 */ 039@InterfaceAudience.Private 040public class HostnameFilter implements Filter { 041 static final ThreadLocal<String> HOSTNAME_TL = new ThreadLocal<String>(); 042 private static final Logger log = LoggerFactory.getLogger(HostnameFilter.class); 043 044 /** 045 * Initializes the filter. 046 * <p/> 047 * This implementation is a NOP. 048 * 049 * @param config filter configuration. 050 * 051 * @throws ServletException thrown if the filter could not be initialized. 052 */ 053 @Override 054 public void init(FilterConfig config) throws ServletException { 055 } 056 057 /** 058 * Resolves the requester hostname and delegates the request to the chain. 059 * <p/> 060 * The requester hostname is available via the {@link #get} method. 061 * 062 * @param request servlet request. 063 * @param response servlet response. 064 * @param chain filter chain. 065 * 066 * @throws IOException thrown if an IO error occurrs. 067 * @throws ServletException thrown if a servet error occurrs. 068 */ 069 @Override 070 public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) 071 throws IOException, ServletException { 072 try { 073 String hostname; 074 try { 075 String address = request.getRemoteAddr(); 076 if (address != null) { 077 hostname = InetAddress.getByName(address).getCanonicalHostName(); 078 } else { 079 log.warn("Request remote address is NULL"); 080 hostname = "???"; 081 } 082 } catch (UnknownHostException ex) { 083 log.warn("Request remote address could not be resolved, {0}", ex.toString(), ex); 084 hostname = "???"; 085 } 086 HOSTNAME_TL.set(hostname); 087 chain.doFilter(request, response); 088 } finally { 089 HOSTNAME_TL.remove(); 090 } 091 } 092 093 /** 094 * Returns the requester hostname. 095 * 096 * @return the requester hostname. 097 */ 098 public static String get() { 099 return HOSTNAME_TL.get(); 100 } 101 102 /** 103 * Destroys the filter. 104 * <p/> 105 * This implementation is a NOP. 106 */ 107 @Override 108 public void destroy() { 109 } 110}