Proxy나 LB처럼 L7 스위칭을 하는 장치를 통과한 HTTP 헤더는 host가 L7 스위치의 주소로 덮어써진다.

L7 스위치를 지날 때마다 이전 주소는 X-FORWARDED-FOR에 차곡차곡 기록되는데,

최초 HTTP request를 한 host의 주소를 알기 위해서는 이 정보를 이용해야 한다.

아래는 Java로 구현된 Controller의 소스 코드이다.


public final class HttpUtils {

    private static final String HEADER_X_FORWARDED_FOR = "X-FORWARDED-FOR";


    /**

     * Returns the original host's IP address of the HTTP request.

     * It ignores any L7 switches.

     * 

     * @param request

     * @return

     */

    public static String getFirstRemoteAddr(HttpServletRequest request) {

        String remoteAddr = request.getRemoteAddr();

        String x;

        if ((x = request.getHeader(HEADER_X_FORWARDED_FOR)) != null) {

            remoteAddr = x;

            int idx = remoteAddr.indexOf(',');

            if (idx > -1) {

                remoteAddr = remoteAddr.substring(0, idx);

            }

        }

        return remoteAddr;

    }

}



출처: http://johannburkard.de/blog/programming/java/x-forwarded-for-http-header.html

Posted by 배트
,
This code is based on Apache common library.
If you are able to use the library, I recommend it. :-)

private boolean contentEquals(File file1, File file2) throws IOException {

    boolean file1Exists = file1.exists();

    if (file1Exists != file2.exists()) {

        return false;

    }


    if (!file1Exists) {

        // two not existing files are equal

        return true;

    }


    if (file1.isDirectory() || file2.isDirectory()) {

        // don't want to compare directory contents

        throw new IOException("Can't compare directories, only files");

    }


    if (file1.length() != file2.length()) {

        // lengths differ, cannot be equal

        return false;

    }


    if (file1.getCanonicalFile().equals(file2.getCanonicalFile())) {

        // same file

        return true;

    }


    FileInputStream fileStream1 = new FileInputStream(file1);

    FileInputStream fileStream2 = new FileInputStream(file2);


    BufferedInputStream bufferedStream1 = new BufferedInputStream(fileStream1);

    BufferedInputStream bufferedStream2 = new BufferedInputStream(fileStream2);


    int ch = bufferedStream1.read();

    while (-1 != ch) {

        int ch2 = bufferedStream2.read();

        if (ch != ch2) {

            return false;

        }

        ch = bufferedStream1.read();

    }


    int ch2 = bufferedStream2.read();


    bufferedStream1.close();

    bufferedStream2.close();


    return (ch2 == -1);

}



Posted by 배트
,
성능은 보장 못해도 완전 심플하다 ㅋㅋㅋ

출처: Simple Implementation of Wildcard (*) Text Matching using Java
http://www.adarshr.com/papers/wildcard

/**
 * Performs a wildcard matching for the text and pattern 
 * provided.
 * 
 * @param text the text to be tested for matches.
 * 
 * @param pattern the pattern to be matched for.
 * This can contain the wildcard character '*' (asterisk).
 * 
 * @return <tt>true</tt> if a match is found, <tt>false</tt> 
 * otherwise.
 */

public static boolean wildCardMatch(String text, String pattern)
{
    // Create the cards by splitting using a RegEx. If more speed 
    // is desired, a simpler character based splitting can be done.
    String [] cards = pattern.split("\\*");

    // Iterate over the cards.
    for (String card : cards)
    {
        int idx = text.indexOf(card);
        
        // Card not detected in the text.
        if(idx == -1)
        {
            return false;
        }
        
        // Move ahead, towards the right of the text.
        text = text.substring(idx + card.length());
    }
    
    return true;
}

Posted by 배트
,
public static void printCurrentStackTrace() {
    try {
        StackTraceElement[] cause = Thread.currentThread().getStackTrace();
        if(cause==null || cause.length==0)
            return;

        // 1st stack is skipped
        for( int i=0 ; i<cause.length ; i++ ) {
            if(i==1)
                continue;
            System.err.println(cause[i].toString());
        }
    } catch(SecurityException e) {
        e.printStackTrace();
        return;
    }
}

public static void printErrorAndStackTrace(String err) {
    System.err.println(err);
    
    try {
        StackTraceElement[] cause = Thread.currentThread().getStackTrace();
        if(cause==null || cause.length==0)
            return;

        // 1st stack is skipped
        for( int i=0 ; i<cause.length ; i++ ) {
            if(i==1)
                continue;
            System.err.println(cause[i].toString());
        }
    } catch(SecurityException e) {
        e.printStackTrace();
        return;
    }
}
Posted by 배트
,

Rules of JAVA Exception

by Junseok Oh

 

1.     간단한 기능을 하는 메소드는 굳이 예외를 발생시키지 않고, C와 유사하게 boolean 형 또는 에러코드를 의미하는 int 형을 반환한다. (하지만 에러코드를 정의하는 게 비효율적일 수 있다.)

2.     boolean/int 반환 메소드에서 Exception이 발생 시, error stack을 출력하고 해당 Exception에 해당하는 적절한 값을 리턴한다. (C 스타일)

3.     Exception은 메소드의 기능과 문맥에 맞는 다른 Exception으로 변환/추상화한다.
발생한 Exception에 해당하는 기능이 메소드에 암시되어 있다면, 그대로 bypass한다.

4.     제작하는 메소드가 다른 메소드의 기능을 얇게 추상화한다면, 모든 Exception bypass하게 throws Exception으로 정의할 수 있다.
boolean
을 반환할지, bypass 할 지는 메소드의 기능이 critical한지 trivial한지에 따라 달라진다. 발생할 수 있는 Exception의 종류를 기준으로 삼지 않는다.

5.     파일 입출력을 암시하는 메소드 안에서 발생하는 IOException bypass한다.
하지만 메소드의 문맥에 따라 IOException을 다른 Exception으로 변환한다.

6.     Exception을 던지는 경우, 되도록 Java에 정의되어 있는 표준 Exception을 사용한다.

7.     비록 귀찮더라도 너무 많은 코드를 try문으로 감싸는 것은 지양한다.
비록 귀찮더라도 구체적인 하위 Exception catch한다.

8.     되도록 Exception에 구체적인 에러 메시지를 포함시킨다.

9.     catch 블록에서 할 수 있는 작업은 복구/트레이스/ Exception 발생/종료뿐이다. 그냥 지나치는 것은 지양한다.
finally
블록에서 할 수 있는 작업은 try/catch 블록에서의 작업에 대한 공통 마무리이다. finally 블록에서 메소드를 종료하는 것은 지양한다.
(try/catch
블록에 return이 있다면, finally 블록 코드를 실행 후에 메소드를 종료하기 때문.)

10.   (임시) 부모/자식 예외를 모두 catch하는 블록이 연속되는 경우, 반드시 자식 예외에 해당하는 catch 블록이 앞에 위치해야 한다.


will be continuously updated...
Posted by 배트
,
오랜만에 자바하니까 귀찮긔...

public String getHTTPDocuement(String urlString, String [] postParameterNames, String [] postParameterValues) {
        String resultDocument = "";

        try {
            URL url = new URL(urlString);
            HttpURLConnection http = null;
           
            HttpURLConnection.setFollowRedirects(false);
           
            // Redirects HTTP documents at most 5 times
            int numRedirects = 0;
            while( true ) {
                // Opens the URL
                http = (HttpURLConnection)url.openConnection();

                // Sets the parameters
                // This logic should be only executed at first time
                if(numRedirects==0 && postParameterNames!=null && postParameterValues!=null) {
                    String postParameterData = "";

                    http.setDoOutput(true);
                    http.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
                    http.setRequestMethod("POST"); // can be skipped

                    for (int j = 0; j < postParameterNames.length; j++) {
                        postParameterData += postParameterNames[j] + "=" + URLEncoder.encode(postParameterValues[j]) + "&";
                    }

                    OutputStream outputStream = http.getOutputStream();

                    outputStream.write( postParameterData.getBytes("UTF-8") );
                    outputStream.flush();
                    outputStream.close();
                }

                // Checks whether the HTTP document want to redirect
                int responseCode = http.getResponseCode();
                if (responseCode >= 300 && responseCode <= 307 && responseCode != 306 && responseCode != HttpURLConnection.HTTP_NOT_MODIFIED ) {
                    URL base = http.getURL();
                    String loc = http.getHeaderField("Location");
                    if (loc != null)
                    {
                        url = new URL(base, loc);
                    }
                    http.disconnect();
                    if (url == null
                            // Allows a redirection from unsecure protocol to secure protocol or vice versa
                            //|| !(target.getProtocol().equals("http")
                            //|| target.getProtocol().equals("https"))
                            || numRedirects >= 5)
                    {
                        throw new SecurityException("illegal URL redirect");
                    }
                    numRedirects++;
                    continue;
                }
               
                // No more redirections
                break;
            }

            // Gets the HTTP response
            BufferedReader inputBufferReader = new BufferedReader(new InputStreamReader(http.getInputStream()));
            StringBuffer buffer = new StringBuffer();

            int c;
            while((c=inputBufferReader.read()) != -1){
                buffer.append((char)c);
            }

            resultDocument = buffer.toString().trim();

        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return resultDocument;
    }
Posted by 배트
,