2013년 12월 20일 금요일

jQuery Ajax 관련 간단 정리, same-origin policy, JSONP, CORS

이전 블로그에서 이전 함 (원본 글 2013/12/20 작성)

[Ajax, Asynchronous JavaScript and XML]

 : client-server간 asynchronous web application을 만들기 위한 방법으로 웹페이지의 조작, 변동 없이 background에서 asynchronous하게 server로 부터 data를 받아 오는 것.
 : 일반적으로 data 수신을 위해서는 지속적인 polling을 사용 함.

By Gengns-Genesis - Own work, CC BY-SA 4.0,
https://commons.wikimedia.org/w/index.php?curid=41186925

[Same-origin policy, 동일 도메인 참조 정책?]

JavaScript 같이 browser-side programming 언어에서는 보안상의 이유로 스크립트가 실행되는 페이지와 다른 도메인(protocol[http,https], Host[x.x.x.x], port[:y] 가 모두 같아야 함.)의 페이지를 참조할 수 없게 하는 정책

: 도메인 비교 예시
 To illustrate, the following table gives an overview of typical outcomes for checks against the URL"http://www.example.com/dir/page.html".
Compared URL
Outcome
Reason
httpː//www.example.com/dir/page2.html
Success
Same protocol and host
httpː//www.example.com/dir2/other.html
Success
Same protocol and host
httpː//username:password@www.example.com/dir2/other.html
Success
Same protocol and host
httpː//www.example.com:81/dir/other.html
Failure
Same protocol and host but different port
Failure
Different protocol
http://en.example.com/dir/other.html
Failure
Different host
http://example.com/dir/other.html
Failure
Different host (exact match required)
http://v2.www.example.com/dir/other.html
Failure
Different host (exact match required)
httpː//www.example.com:80/dir/other.html
Don't use
Port explicit. Depends on implementation in browser.

이를 해결하는 방법으로는 여러 방법들(document.domain property, Cross-Origin Resource Sharing, Cross-document messaging, JSONP)이 있다고 함. 그외에는 서버의 도움을 빌려 Proxy를 만들고 Proxy를 사용하여 타 도메인의 페이지들을 참조하는 방법도 있음.

자세한것은 위 링크를..

[JSONP, JSON-P, JSON with Padding]

간단히 말하면 JSONP는 client단에서는 서버의 JSONP 주소를 script로 추가하고 서버에서는 처리를 한 뒤 client에서 지정된 callback을 결과값과 함께 호출해주는 방법.

client단에서는 아래와 같이 JSONP 주소로 script를 추가하고
<script type="application/javascript" src="http://server2.example.com/Users/1234?jsonp=parseResponse"> </script>
서버단에서는 처리를 마친 뒤 client단에서 지정한 callback(=parseResponse)을 결과값과 호출 하여 전달함.
parseResponse({"Name": "Foo", "Id": 1234, "Rank": 7});

jQuery를 사용하여 twitter의 글들을 가져오는 예제 

 <html>
<head> <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js"></script> <script> $(document).ready(function(){ $.ajax({ url: 'http://twitter.com/status/user_timeline/padraicb.json?count=10', dataType: 'jsonp', success: function(dataWeGotViaJsonp){ var text = ''; var len = dataWeGotViaJsonp.length; for(var i=0;i<len;i++){ twitterEntry = dataWeGotViaJsonp[i]; text += '<p><img src = "' + twitterEntry.user.profile_image_url_https +'"/>' + twitterEntry['text'] + '</p>' } $('#twitterFeed').html(text); } }); }) </script> </head> <body> <div id = 'twitterFeed'></div> </body> </html>

JSONP 관련 jQuery ajax method의 property
- dataType : 'jsonp' 지정
- jsonp : 일반적으로 client에서 지정한 'callback' argument (http:host:port/jsonp_uri?callback=jquery function)를 서버에서는 호출할 function으로 지정한다. 하지만 arguemnt명이 callback이 아니라면 jsonp 속성으로 지정하면 변경됨. 
- jsonpCallback : jsonp 결과값이 전달될 function을 지정할 수 있음. 기본적으로는 jquery에서 알아서 지정한다.

[JSONP의 단점]
하지만 GET 방법만을 지원하고 보안상 이슈로 인해 CORS (Cross-Origin Resource Sharing, http://www.w3.org/TR/cors/http://en.wikipedia.org/wiki/Cross-origin_resource_sharing) 방법을 추천하는 분위기 같음.

JSONP의 단점 및 대안을 소개한 JSONP 사이트의 본문
 The problem

Thus far, JSON-P has essentially just been a loose definition by convention, when in reality the browser accepts any abitrary JavaScript in the response. This means that authors who rely on JSON-P for cross-domain Ajax are in fact opening themselves up to potentially just as much mayhem as was attempted to be avoided by implementing the same-origin policy in the first place. For instance, a malicious web service could return a function call for the JSON-P portion, but slip in another set of JavaScript logic that hacks the page into sending back private user's data, etc.

JSON-P is, for that reason, seen by many as an unsafe and hacky approach to cross-domain Ajax, and for good reason. Authors must be diligent to only make such calls to remote web services that they either control or implicitly trust, so as not to subject their users to harm.

Alternatives

There are many alternatives to JSON-P, but each of them has their own drawbacks or challenges. These techniques will not be covered in detail here, except for one: CORS (aka, "Cross-Origin Resource Sharing") -- the most recent addition to browser JavaScript for making cross-domain Ajax calls. Put simply, CORS is an extension to the standard XMLHttpRequest (aka, "XHR") object, which allows the browser to make calls across domains (despite the same-origin restriction). But it does so by first "preflighting" a request to the target server to ask it for permission.

[CORS]
브라우저 별 CORS 지원 여부 : http://caniuse.com/cors

앞서 말한 cross-domain request를 허용하게 하기 위한 표준적인 방법으로 다른 same-origin policy를 회피하기 위한 방법들 보다 다소 안전하다라고 소개하고 있음.

flow 는 다음과 같고 Javascript에서 XMLHttpRequest에 대해서 아래 옵션을 제공해 주면 
xhr.withCredentials = "true";
xhr.setRequestHeader("Content-Type", "text/plain;charset=UTF-8");

jQuery에서는
$.support.cors = true;

Browser에서는 Origin, Access-Control-Request-Headers header들과 함께 다른 도메인으로 request를 보내서 preflight 절차를 지나 response를 전달 받게 됨.


근데 난 mobile web app을 개발하기 위해서 localhost상에서 개발중인데 서버에서 localhost origin은 허용을 하지 않는 것 같고 계속 Chrome에서는 "Access-Control-Request-Headers" 헤더가 입력되어 전달되지 않는 것으로 보인다. 결국 서버 사이드에서 동작하는 JavaScript 상에서만 가능한건가?
나중에 Hybrid framework 상에서도 확인을 해봐야 겠음.

암튼 다음 링크들은 CORS 관련 링크들

 : http://www.html5rocks.com/en/tutorials/cors/
  => 전반적인 설명이 잘 되어 있음.
  => MDN documentation은 언제나 잘 되어 있음.
  => Server side, Client side에서 처리해야할 것들에 대해서 정리
  => 초반부에서 JSONP와 CORS의 제약에 대해서 설명해주고 있음.


[jQuery Ajax methods]

뭐 설명이 필요없고 링크의 API reference를 참고하시라.
 jQuery.ajax()
 : Perform an asynchronous HTTP (Ajax) request.

jQuery.ajaxPrefilter()
 : Handle custom Ajax options or modify existing options before each request is sent and before they are processed by $.ajax().

jQuery.ajaxSetup()
 : Set default values for future Ajax requests. Its use is not recommended.

jQuery.ajaxTransport()
 : Creates an object that handles the actual transmission of Ajax data.

jQuery.get()
 : Load data from the server using a HTTP GET request.

jQuery.getJSON()
 : Load JSON-encoded data from the server using a GET HTTP request.

jQuery.getScript()
 : Load a JavaScript file from the server using a GET HTTP request, then execute it.

jQuery.param()
 : Create a serialized representation of an array or object, suitable for use in a URL query string or Ajax request.

jQuery.post()
 : Load data from the server using a HTTP POST request.


[jQuery.ajax Examples]
Example: Save some data to the server and notify the user once it's complete.
1
2
3
4
5
6
7
8
$.ajax({
type: "POST",
url: "some.php",
data: { name: "John", location: "Boston" }
})
.done(function( msg ) {
alert( "Data Saved: " + msg );
});

Example: Retrieve the latest version of an HTML page.

1
2
3
4
5
6
7
$.ajax({
url: "test.html",
cache: false
})
.done(function( html ) {
$( "#results" ).append( html );
});

Example: Send an xml document as data to the server. By setting the processData option to false, the automatic conversion of data to strings is prevented.

1
2
3
4
5
6
7
8
var xmlDocument = [create xml document];
var xmlRequest = $.ajax({
url: "page.php",
processData: false,
data: xmlDocument
});
xmlRequest.done( handleResponse );

Example: Send an id as data to the server, save some data to the server, and notify the user once it's complete. If the request fails, alert the user.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var menuId = $( "ul.nav" ).first().attr( "id" );
var request = $.ajax({
url: "script.php",
type: "POST",
data: { id : menuId },
dataType: "html"
});
request.done(function( msg ) {
$( "#log" ).html( msg );
});
request.fail(function( jqXHR, textStatus ) {
alert( "Request failed: " + textStatus );
});

Example: Load and execute a JavaScript file.

1
2
3
4
5
$.ajax({
type: "GET",
url: "test.js",
dataType: "script"
});

댓글 없음:

댓글 쓰기