2009년 8월 22일 토요일

Apache HttpClient 4.0 InputStreamBody content length가 항상 -1인 문제

Apache HttpClient 4.0 GA가 나와서 Commons에 있던 3.x을 버리고 적용을 해보았다. 처음에는 FileBody를 이용하여 파일 업로드 기능을 구현하니 큰 문제가 없었는데 spring MultipartFile을 이용하여 delegate하는 형식으로 파일 업로드를 하다보니 InputStream 밖에 없어서 InputStreamBody를 이용하니 Y모사 서버에서 content length가 정의되지 않았다며 불평을 늘어놓았다.

 

분석을 해보니 InputStreamBody의 getContentLength 함수는 항상 -1을 반환하는게 문제였다. 그리하여.. InputStreamBody를 상속하여 content length를 제대로 반환하는 모듈을 하나 만들었다.

   1: import java.io.IOException;
   2:  
   3: import org.apache.http.entity.mime.content.InputStreamBody;
   4: import org.springframework.web.multipart.MultipartFile;
   5:  
   6: public class MultipartFileBody extends InputStreamBody {
   7:  
   8:     private MultipartFile file;
   9:  
  10:     public MultipartFileBody(MultipartFile file) throws IOException {
  11:         super(file.getInputStream(), file.getContentType(), file.getOriginalFilename());
  12:  
  13:         this.file = file;
  14:     }
  15:  
  16:     public long getContentLength() {
  17:         return this.file.getSize();
  18:     }
  19:  
  20: }

상위 모듈은 InputStreamBody를 상속받아서 getContentLength 부분만 override하여 제대로된 파일 크기를 반환하도록 하였다. 상속하니까 참 쉽죠잉?

2009년 8월 21일 금요일

Tomcat에서 static 파일들을 제공하는 방법

Spring 3.0의 새로운 REST 방식 컨트롤러를 이용하기 위해서 가장 간단한 방법으로는 dispatcher servlet을 다음과 같이 맵핑을 하는 방식을 택하였다.

   1: <servlet>
   2:     <servlet-name>dispatcher</servlet-name>
   3:     <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
   4: </servlet>
   5: <servlet-mapping>
   6:     <servlet-name>dispatcher</servlet-name>
   7:     <url-pattern>/</url-pattern>
   8: </servlet-mapping>

이 맵핑의 큰 문제점 중 하나는 개발할 당시에는 보통 apache + tomcat 형태를 이용하지 않고 tomcat만으로 구성하여 개발을 하는데 static한 파일들을 모두 dispatcher servlet이 가져간다는 문제가 있다. 그래서 검색을 좀 해보니 다음과 같은 해결책이 있었다.

   1: <servlet-mapping>
   2:     <servlet-name>default</servlet-name>
   3:     <url-pattern>*.css</url-pattern>
   4: </servlet-mapping>
   5: <servlet-mapping>
   6:     <servlet-name>default</servlet-name>
   7:     <url-pattern>*.js</url-pattern>
   8: </servlet-mapping>
   9: <servlet-mapping>
  10:     <servlet-name>default</servlet-name>
  11:     <url-pattern>*.jpg</url-pattern>
  12: </servlet-mapping>
  13: <servlet-mapping>
  14:     <servlet-name>default</servlet-name>
  15:     <url-pattern>*.png</url-pattern>
  16: </servlet-mapping>

이런 식으로 필요한 확장자에 대해서 default servlet으로 처리하도록 하면 된다. 혹시나 default servlet의 존재에 대해서 궁금하다면 default servlet의 정의는 %TOMCAT_HOME%\conf\web.xml에 정의되어 있다.

2009년 8월 16일 일요일

as3seed

Reflexion 다닐 당시 암호화 모듈 관련하여 만든다고 SEED만 as3으로 컨버전을 했었는데 지금 이 코드가 상당히 오랜 기간 사용이 되질 않아서 아까운 마음도 있고 다른 사람들이 활용할 수 있으면 좋겠다 생각하여 무단으로 오픈소스화 하였다. 문제가 될 소지가 있다면 곧바로 내리겠으나.. 크게 문제는 없을 듯.

 

http://code.google.com/p/as3seed/

HTTP Proxy with Virtual Hosts using Apache

HTTP Proxy는 어디에 쓸까 많이 과거에 의문이 들었었는데 막상 회사를 그만두고 엄청난 인프라가 없는 조그마한 작업실을 꾸리다보니 우리처럼 IP가 하나 밖에 없고 여러 플랫폼의 웹서버가 돌아가는 경우 이를 외부에 제공을 할 때 유용하게 쓰일 수 있을 것 같다.

 

기존의 구성에서 변경될 사항을 최소한으로 하기 위해서 우리는 HTTP 포트가 열린 Apache 서버 하나만을 추가를 했다. 오히려 이런 식으로 구성하는 편이 다른 서버들은 외부로 직접적으로 공개시키지 않아서 보안적으로도 조금은 신경 쓸 것이 사라져서 좋다.

 

HTTP Proxy를 사용하기 위해서는 2가지 모듈이 필요하다.

  • mod_proxy
  • mod_proxy_http
  • mod_vhost_alias

 

이를 구성한 http.conf 내용을 보도록 하자.

   1: LoadModule proxy_module modules/mod_proxy.so
   2: LoadModule proxy_http_module modules/mod_proxy_http.so
   3: #LoadModule rewrite_module modules/mod_rewrite.so
   4: LoadModule vhost_alias_module modules/mod_vhost_alias.so
   5:  
   6: NameVirtualHost *:80
   7:  
   8: <VirtualHost *:80>
   9:     ServerName proxy.source.com
  10:  
  11:     <Proxy *>
  12:         Order deny,allow
  13:         Allow from all
  14:     </Proxy>
  15:  
  16:     ProxyRequests Off
  17:     ProxyPreserveHost On
  18:     ProxyPassMatch ^(/.*)$ http://proxy.target.com$1
  19: </VirtualHost>

이처럼 VirtualHost를 필요에 의해서 여러 개로 생성할 경우 플랫폼에 구애받지 않고 IP 한개로 여러 서비스를 외부로 노출 시킬 수 있다.