본문 바로가기
프로그래밍/PC

Delphi XE2 에서 DataSnap REST Application Cross Domain 처리

by 사악신 2012. 6. 20.

기껏 REST 서버를 구축하여도 만약 해당 서버 어플리케이션의 API를 또 다른 서버에서 호출하여 사용할 경우, 접근 권한 문제가 발생한다.(대충 그려보았다.)

 

 

 

 

이를 해결하는 다양한 방법들이 존재하는데... 익스플로러 및 어지간한 예전 웹브라우저들까지 모두 지원하려면 JSONP 를 사용하여야 한다.(서버에서 access-control-allow-origin:* 을 헤더에 싣는 방법도 있지만, 최신 웹브라우저에서만 올바르게 동작하며 익스플로러에선 제대로 동작하지 않는다.)

 

일단, JSONP 에서 요구하는 형태로 결과를 반환하여야하는데 XE2 에 추가된 TDSHTTPWebDispatcher 의 FormatResult 이벤트 메소드를 아래와 같이 만지작거려야한다.

procedure TWebModule1.DSHTTPWebDispatcher1FormatResult(Sender: TObject;
  var ResultVal: TJSONValue; const Command: TDBXCommand; var Handled: Boolean);
var
  JSONValue: TJSONValue;
begin
  if Command.Text = 'TServerMethodsPost.ZipcodeData' then
  begin
    if GetInvocationMetadata.QueryParams.IndexOfName('callback') > -1 then
    begin
      Handled := True;
      JSONValue := ResultVal;
      ResultVal := TJSONArray(JSONValue).Get(0);
      TJSONArray(JSONValue).Remove(0);
      JSONValue.Free;
    end;
  end;
end;

 

6: 해당 요청 메소드인 경우에 한하여 처리한다.

8: JSONP 요청인 지 여부를 callback 파라미터가 있는가로 구분한다.

10 이하: 결과 반환시 result: 어쩌구 부분을 날려버린다.

 

일단, 단순한 형태로 구성하였고... 해당 서버 어플리케이션의 상황에 따라 보강하면 되겠다. 헌데, 아웃 파라미터인 ResultVal 의 타입이 TJSONValue 인지라 JSONP 가 원하는 결과를 위하여 또 다른 추가 작업을 해줘야한다.

 

TWebModule 의 AfterDispatch 이벤트 메소드를 다음과 같이 작업한다.

procedure TWebModule1.WebModuleAfterDispatch(Sender: TObject;
  Request: TWebRequest; Response: TWebResponse; var Handled: Boolean);
var
  Callback: String;
begin
  if Request.QueryFields.IndexOfName('callback') > -1 then
  begin
    Callback := Request.QueryFields.Values['callback'];
    Response.Content := Callback + '(' + Response.Content + ')';
  end;
end;

 

6: JSONP 의 callback 요청인지 판단한다.

8: callback 으로 지정되는 함수의 이름이 랜덤하게 변경되어 요청될 수 있으므로 파라미터 값을 가져와 처리한다.

9: JSONP 가 요구하는 형태로 callback 에서 지정한 함수를 호출하는 형태로 결과값을 반환한다.

 

마찬가지로 해당 서버의 상황에 따라 보강하면 된다. 클라이언트측 자바스크립트는 jquery 를 사용하여 다음과 같이 호출한다.

(모업체의 우편번호 검색 기능을 REST API 로 호출해보는 샘플이다.)

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>JSONP TEST</title>
     
    <script type="text/javascript" src="http://192.168.0.178:9090/rest/js/jquery-1.7.2.min.js"></script>
    <script>
        $(document).ready(function(){
            $("#testBtn").click(function(){
                $.ajax({
                    url : "http://192.168.0.178:9090/rest/ILPREST.dll/datasnap/rest/TServerMethodsPost/ZipcodeData/구로/1/2",
                    dataType : "jsonp",
                    jsonp : "callback",
                    success : function(d){
                        $.each(d, function(k, v){
                          $("#ajax").append("<div>" + k + ": ----------------------------------------</div>");
                          $("#ajax").append("<div>" + v.SEQ_NUM + "</div>");
                          $("#ajax").append("<div>" + v.NEW_YN + "</div>");
                          $("#ajax").append("<div>" + v.ZIPCODE + "</div>");
                          $("#ajax").append("<div>" + v.SIDO + "</div>");
                          $("#ajax").append("<div>" + v.SIGUNGU + "</div>");
                          $("#ajax").append("<div>" + v.EUPMYUNDONG + "</div>");
                          $("#ajax").append("<div>" + v.BUNJI + "</div>");
                          $("#ajax").append("<div>" + v.BD_NAME + "</div>");
                          $("#ajax").append("<div>" + v.SADDRESS + "</div>");
                        });
                        $("#ajax").show();
                    },
                    error: function() {
                        alert('error');
                    }
                });
            });
        });
    </script>
    
    <style>
        div{margin-bottom:10px;padding:2px;}
        #ajax{border:1px solid blue;display:none;}
    </style>
</head>

<body>
    <button id="testBtn">테스트</button>
    <div id="ajax"></div>
</body>

</html>

물론, 해당 html 파일은 다른 서버에 위치하고 있다.

 

반응형

'프로그래밍 > PC' 카테고리의 다른 글

Delphi XE2 에서 DataSnap REST Application Client  (0) 2012.07.13
dbExpress MySQL 5.1 한글 테이블명 사용  (0) 2012.06.26
Delphi XE2, dbExpress Oracle 10g 연동  (1) 2012.05.30
Interface 요약 #7  (0) 2012.04.19
Interface 요약 #6  (0) 2012.04.19

댓글