문제점
GIS개발을 진행할 때 클라이언트에서 GeoServer로 다이렉트로 연결하지 못하는 경우가 있다.
통상적으로는 GeoServer로 다이렉트로 연결하여 요청 및 응답을 받는게 맞지만 보안상 불가능한 경우가 있다.
WAS를 통해서 우회하게 된다면 약간?의 트래픽이 더 발생할 수 있고 WAS의 부하가 발생할 수 있지만 큰 문제는 없을 것으로 보인다. 다만, 관리 포인트가 하나 더 늘어나게 된다는 문제점이 있다.
해결
우회하여 GeoServer를 이용해야 하는데 WAS의 proxy소스를 이용하여 우회하도록 처리하여야 한다. 결국 요청은 클라이언트 -> WAS -> GeoServer형태로 이루어져야 하고, 응답은 GeoServer -> WAS -> 클라이언트로 이루어지게 된다.
물론, WAS까지 도달하지 않고 특정 URL 요청시 WEB 서버의 프록시에서 GeoServer로 연결할 수 있지만 이번에는 WAS를 통해서 GeoServer로 요청 및 응답할 수 있도록 구현하였다.
WAS에서 구현한 proxy 소스를 첨부한다.
아래 소스는 /proxy.do를 호출하면 GeoServer로 요청하고 응답을 받아 결과를 내려준다.
소스
/**
* 프록시
*/
@RequestMapping(value = "/proxy.do")
public void proxy(HttpServletRequest request, HttpServletResponse response, ModelMap model) {
CommonVO vo = new CommonVO(request);
String result = "";
try {
String geoServerUrl = GEOSERVER_URL;
String geoUrl = geoServerUrl + vo.get("geoServerUrl").toString();
URL url = new URL(geoUrl);
URLConnection urlConn = url.openConnection();
BufferedReader in = new BufferedReader(new InputStreamReader(urlConn.getInputStream(), "UTF-8"));
String inputLine;
StringBuffer sb = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
sb.append(inputLine);
}
in.close();
result = sb.toString();
response.setContentType("application/json");
response.getOutputStream().write(result.getBytes("UTF-8"));
} catch (Exception e) {
e.printStackTrace();
}
}
웹 브라우져에서 WAS로 /proxy.do 호출하게 되면 관련 정보를 안고 GeoServer로 call을 하게 되며 응답을 받게 된다.
WFS만 사용하기에는 위 소스도 문제는 없으나 WMS도 함께 사용하기 위해서 소스를 추가 수정하였다.
아래의 소스는 WFS, WMS 2가지 타입으로 요청 및 응답할 수 있도록 추가 수정 및 개발하였다.
/**
* GeoServer Proxy WFS/WMS
*/
@RequestMapping(value = "/proxy.do")
public void proxy(HttpServletRequest request, HttpServletResponse response) throws Exception{
CommonVO vo = new CommonVO(request);
String service = vo.get("service").toString();
String geoServerUrl = GEOSERVER_URL;
if(service.equals("WFS")){
BufferedReader in = null;
try{
geoServerUrl += "/ows?service=WFS&version=1.0.0&request=GetFeature&outputFormat=application/json&srsName=EPSG:5179";
geoServerUrl += "&";
geoServerUrl += "typeName="+vo.get("typeName").toString();
geoServerUrl += "&";
geoServerUrl += vo.get("viewParams").toString();
String geoUrl = geoServerUrl;
URL url = new URL(geoUrl);
URLConnection urlConn = url.openConnection();
in = new BufferedReader(new InputStreamReader(urlConn.getInputStream(), "UTF-8"));
String inputLine;
StringBuffer sb = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
sb.append(inputLine);
}
response.setContentType("application/json");
response.getOutputStream().write((sb.toString()).getBytes("UTF-8"));
response.getOutputStream().close();
}catch(NullPointerException | MemoryLimitException | IllegalArgumentException e){
LOGGER.error(e.toString());
}finally{
if(in != null)
in.close();
}
}else if(service.equals("WMS")){
String geoUrl = geoServerUrl+"/wms?";
if(vo.get("service") != null) geoUrl += "service="+vo.get("service").toString();
if(vo.get("version") != null) geoUrl += "&version="+vo.get("version").toString();
if(vo.get("request") != null) geoUrl += "&request="+vo.get("request").toString();
if(vo.get("layers") != null) geoUrl += "&layers="+vo.get("layers").toString();
if(vo.get("bbox") != null) geoUrl += "&bbox="+vo.get("bbox").toString();
if(vo.get("width") != null) geoUrl += "&width="+vo.get("width").toString();
if(vo.get("height") != null) geoUrl += "&height="+vo.get("height").toString();
if(vo.get("srs") != null) geoUrl += "&srs="+vo.get("srs").toString();
if(vo.get("format") != null) geoUrl += "&format="+vo.get("format").toString();
if(vo.get("transparent") != null) geoUrl += "&TRANSPARENT="+vo.get("transparent").toString();
if(vo.get("sld_body") != null) geoUrl += "&sld_body="+vo.get("sld_body").toString();
if(vo.get("viewparams") != null) geoUrl += "&viewparams="+vo.get("viewparams").toString();
RestTemplate rt = new RestTemplate();
DefaultUriTemplateHandler uriTemplateHandler = (DefaultUriTemplateHandler) rt.getUriTemplateHandler();
uriTemplateHandler.setStrictEncoding(true);
rt.setUriTemplateHandler(uriTemplateHandler);
byte[] result = rt.getForObject(geoUrl, byte[].class);
response.setContentType("image/png");
response.getOutputStream().write(result);
response.getOutputStream().close();
}
}
결국 클라이언트에서 파라미터로 담아서 요청하는 service 값에 따라서 WFS 혹은 WMS 요청이 이루어 진다.