Extjs 크로스 도메인 관련
Scripter/EXTJS / 2008. 2. 28. 10:53
서버없이 ExtJS를 사용하고 싶다면 아래 파일을 다운로드 받아 HTML에 넣고 사용한다.
사내솔루션(넥스트리)개발시 서버와 상관없이 작업을 하려다 찾은소스이다.
소스를 까(?)보면 Ext.lib.Ajax 부분을 오버라이드하고 있는데 기본적으로 크로스 도메인에서는 다른 프록시를 써서 해당 우회하는 방법으로 크로스도메인을 사용한다.
그러나 ExtJS에서는 로컬을 우회 프록시로 사용하는갑다..
중간에 XhrHeader값을 보면 "X-Requested-With"를 보면 커스텀헤더를 생성해서 사용하는것을 볼수 있는데 이것은 Prototype.js나 jQuery에서도 이와 같은 방법을 사용하고 있다.
제로보드에도 이러한 스크립트가 있던데 함 뜯어봐야겠다..
[실제 PHP로 헤더값만들기]
[사용법]
[실제 localXHR.js 소스]
사내솔루션(넥스트리)개발시 서버와 상관없이 작업을 하려다 찾은소스이다.
소스를 까(?)보면 Ext.lib.Ajax 부분을 오버라이드하고 있는데 기본적으로 크로스 도메인에서는 다른 프록시를 써서 해당 우회하는 방법으로 크로스도메인을 사용한다.
그러나 ExtJS에서는 로컬을 우회 프록시로 사용하는갑다..
중간에 XhrHeader값을 보면 "X-Requested-With"를 보면 커스텀헤더를 생성해서 사용하는것을 볼수 있는데 이것은 Prototype.js나 jQuery에서도 이와 같은 방법을 사용하고 있다.
제로보드에도 이러한 스크립트가 있던데 함 뜯어봐야겠다..
[실제 PHP로 헤더값만들기]
function isAjax() {
return isset($_SERVER['HTTP_X_REQUESTED_WITH']) &&
$_SERVER ['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest';
}
[사용법]
<script type="text/javascript" src="../extjs/adapter/ext/ext-base.js"></script>
<script type="text/javascript" src="../extjs/ext-all-debug.js"></script>
<script type="text/javascript" src="../extjs/adapter/ext/localXHR.js"></script>
<script type="text/javascript" src="../extjs/ext-all-debug.js"></script>
<script type="text/javascript" src="../extjs/adapter/ext/localXHR.js"></script>
[실제 localXHR.js 소스]
Ext.apply( Ext.lib.Ajax ,
{ forceActiveX:false,
createXhrObject:function(transactionId)
{
var obj={ status:{isError:false}
, tId:transactionId}, http;
try
{
if(Ext.isIE7 && !!this.forceActiveX){throw("IE7forceActiveX");}
obj.conn= new XMLHttpRequest();
}
catch(e)
{
for (var i = 0; i < this.activeX.length; ++i) {
try
{
obj.conn= new ActiveXObject(this.activeX[i]);
break;
}
catch(e) {
}
}
}
finally
{
obj.status.isError = typeof(obj.conn) === undefined;
}
return obj;
},
getHttpStatus: function(reqObj){
var statObj = { status:0
,statusText:''
,isError:false
,isLocal:false
,isOK:false
,error:null};
try {
if(!reqObj)throw('noobj');
statObj.status = reqObj.status;
statObj.isLocal = !reqObj.status && location.protocol == "file:" ||
Ext.isSafari && reqObj.status === undefined;
statObj.isOK = (statObj.isLocal || (statObj.status > 199 && statObj.status < 300));
statObj.statusText = reqObj.statusText || '';
} catch(e){ //지원하지 않는 status 혹은 너무 빨리 호출했을 경우
}
return statObj;
},
handleTransactionResponse:function(o, callback, isAbort)
{
callback = callback || {};
var responseObject=null;
if(!o.status.isError){
o.status = this.getHttpStatus(o.conn);
/* 필요하다면 적당한 status와 XMLDOM을 이용하여 생성하거나 향상시킨다.*/
responseObject = this.createResponseObject(o, callback.argument);
}
if(o.status.isError){
/* exception이 발생했을 경우 다시 체크한다.*/
responseObject = Ext.applyIf(responseObject||{},this.createExceptionObject(o.tId, callback.argument, (isAbort ? isAbort : false)));
}
responseObject.options = o.options;
responseObject.stat = o.status;
if (o.status.isOK && !o.status.isError) {
if (callback.success) {
if (!callback.scope) {
callback.success(responseObject);
}
else {
callback.success.apply(callback.scope, [responseObject]);
}
}
} else {
if (callback.failure) {
if (!callback.scope) {
callback.failure(responseObject);
}
else {
callback.failure.apply(callback.scope, [responseObject]);
}
}
}
if(o.options.async){
this.releaseObject(o);
responseObject = null;
}else{
this.releaseObject(o);
return responseObject;
}
},
createResponseObject:function(o, callbackArg)
{
var obj = {};
var headerObj = {},headerStr='';
try{ //잘못된 인코딩일경우
obj.responseText = o.conn.responseText;
}catch(e){obj.responseText ='';}
obj.responseXML = o.conn.responseXML;
try{
headerStr = o.conn.getAllResponseHeaders()||'';
} catch(e){}
if(o.status.isLocal){
o.status.isOK = ((o.status.status = (!!obj.responseText.length)?200:404) == 200);
if(o.status.isOK && (!obj.responseXML || obj.responseXML.childNodes.length == 0)){
var xdoc=null;
try{ //MS ActiveX가 작동하지 않을 경우
if(typeof(DOMParser) == 'undefined'){
xdoc=new ActiveXObject("Microsoft.XMLDOM");
xdoc.async="false";
xdoc.loadXML(obj.responseText);
}else{
try{ //Opera 9 가 xml contents 파싱에 실패할 경우
var domParser = new DOMParser();
xdoc = domParser.parseFromString(obj.responseText, 'application\/xml');
}catch(ex){}
finally{domParser = null;}
}
} catch(ex){
o.status.isError = true;
o.status.error = ex;
}
obj.responseXML = xdoc;
}
if(obj.responseXML){
var parseBad = (obj.responseXML.parseError || 0) != 0 || obj.responseXML.childNodes.length == 0;
if(!parseBad){
headerStr = 'Content-Type: ' + (obj.responseXML.contentType || 'text\/xml') + '\n' + headerStr ;
}
}
}
var header = headerStr.split('\n');
for (var i = 0; i < header.length; i++) {
var delimitPos = header[i].indexOf(':');
if (delimitPos != -1) {
headerObj[header[i].substring(0, delimitPos)] = header[i].substring(delimitPos + 2);
}
}
obj.tId = o.tId;
obj.status = o.status.status;
obj.statusText = o.status.statusText;
obj.getResponseHeader = headerObj;
obj.getAllResponseHeaders = headerStr;
obj.stat = o.status
if (typeof callbackArg !== undefined) {
obj.argument = callbackArg;
}
return obj;
},
request : function(method, uri, cb, data, options) {
options = Ext.apply({async:true,
headers:false,
userId:null,
password:null,
xmlData:null }, options||{});
var hs = options.headers;
if(hs){
for(var h in hs){
if(hs.hasOwnProperty(h)){
this.initHeader(h, hs[h], false);
}
}
}
if(options.xmlData){
this.initHeader('Content-Type', 'text/xml', false);
method = 'POST';
data = options.xmlData;
}
return this.makeRequest(method, uri, cb, data, options);
},
asyncRequest:function(method, uri, callback, postData)
{
var o = this.getConnectionObject();
if (!o || o.status.isError) {
return null;
}
else {
o.options = options;
try{
o.conn.open(method, uri, true);
} catch(ex){
o.status.isError = true;
o.status.error = ex;
return Ext.apply(o,this.handleTransactionResponse(o, callback));
}
if (this.useDefaultXhrHeader) {
if (!this.defaultHeaders['X-Requested-With']) {
this.initHeader('X-Requested-With', this.defaultXhrHeader, true);
}
}
if(postData && this.useDefaultHeader){
this.initHeader('Content-Type', this.defaultPostHeader);
}
if (this.hasDefaultHeaders || this.hasHeaders) {
this.setHeader(o);
}
this.handleReadyState(o, callback);
try{ o.conn.send(postData || null);
} catch(ex){
o.status.isError=true;
o.status.error = ex;
return Ext.apply(o,this.handleTransactionResponse(o, callback));
}
return o;
}
},
makeRequest:function(method, uri, callback, postData, options)
{
var o = this.getConnectionObject();
if (!o || o.status.isError) {
return null;
}
else {
o.options = options;
try{
o.conn.open(method, uri, options.async, options.userId, options.password);
} catch(ex){
o.status.isError = true;
o.status.error = ex;
var r=this.handleTransactionResponse(o, callback);
return Ext.apply(o,r);
}
if (this.useDefaultXhrHeader) {
if (!this.defaultHeaders['X-Requested-With']) {
this.initHeader('X-Requested-With', this.defaultXhrHeader, true);
}
}
if(postData && this.useDefaultHeader){
this.initHeader('Content-Type', this.defaultPostHeader);
}
if (this.hasDefaultHeaders || this.hasHeaders) {
this.setHeader(o);
}
if(o.options.async){ //blocking call때문에 Timer가 작동하지 않음
this.handleReadyState(o, callback);
}
try{ o.conn.send(postData || null);
} catch(ex){
//Ext.apply(o,this.handleTransactionResponse(o, callback));
}
return options.async?o:Ext.apply(o,this.handleTransactionResponse(o, callback));
}
}});
Ext.lib.Ajax.forceActiveX = (document.location.protocol == 'file:');
{ forceActiveX:false,
createXhrObject:function(transactionId)
{
var obj={ status:{isError:false}
, tId:transactionId}, http;
try
{
if(Ext.isIE7 && !!this.forceActiveX){throw("IE7forceActiveX");}
obj.conn= new XMLHttpRequest();
}
catch(e)
{
for (var i = 0; i < this.activeX.length; ++i) {
try
{
obj.conn= new ActiveXObject(this.activeX[i]);
break;
}
catch(e) {
}
}
}
finally
{
obj.status.isError = typeof(obj.conn) === undefined;
}
return obj;
},
getHttpStatus: function(reqObj){
var statObj = { status:0
,statusText:''
,isError:false
,isLocal:false
,isOK:false
,error:null};
try {
if(!reqObj)throw('noobj');
statObj.status = reqObj.status;
statObj.isLocal = !reqObj.status && location.protocol == "file:" ||
Ext.isSafari && reqObj.status === undefined;
statObj.isOK = (statObj.isLocal || (statObj.status > 199 && statObj.status < 300));
statObj.statusText = reqObj.statusText || '';
} catch(e){ //지원하지 않는 status 혹은 너무 빨리 호출했을 경우
}
return statObj;
},
handleTransactionResponse:function(o, callback, isAbort)
{
callback = callback || {};
var responseObject=null;
if(!o.status.isError){
o.status = this.getHttpStatus(o.conn);
/* 필요하다면 적당한 status와 XMLDOM을 이용하여 생성하거나 향상시킨다.*/
responseObject = this.createResponseObject(o, callback.argument);
}
if(o.status.isError){
/* exception이 발생했을 경우 다시 체크한다.*/
responseObject = Ext.applyIf(responseObject||{},this.createExceptionObject(o.tId, callback.argument, (isAbort ? isAbort : false)));
}
responseObject.options = o.options;
responseObject.stat = o.status;
if (o.status.isOK && !o.status.isError) {
if (callback.success) {
if (!callback.scope) {
callback.success(responseObject);
}
else {
callback.success.apply(callback.scope, [responseObject]);
}
}
} else {
if (callback.failure) {
if (!callback.scope) {
callback.failure(responseObject);
}
else {
callback.failure.apply(callback.scope, [responseObject]);
}
}
}
if(o.options.async){
this.releaseObject(o);
responseObject = null;
}else{
this.releaseObject(o);
return responseObject;
}
},
createResponseObject:function(o, callbackArg)
{
var obj = {};
var headerObj = {},headerStr='';
try{ //잘못된 인코딩일경우
obj.responseText = o.conn.responseText;
}catch(e){obj.responseText ='';}
obj.responseXML = o.conn.responseXML;
try{
headerStr = o.conn.getAllResponseHeaders()||'';
} catch(e){}
if(o.status.isLocal){
o.status.isOK = ((o.status.status = (!!obj.responseText.length)?200:404) == 200);
if(o.status.isOK && (!obj.responseXML || obj.responseXML.childNodes.length == 0)){
var xdoc=null;
try{ //MS ActiveX가 작동하지 않을 경우
if(typeof(DOMParser) == 'undefined'){
xdoc=new ActiveXObject("Microsoft.XMLDOM");
xdoc.async="false";
xdoc.loadXML(obj.responseText);
}else{
try{ //Opera 9 가 xml contents 파싱에 실패할 경우
var domParser = new DOMParser();
xdoc = domParser.parseFromString(obj.responseText, 'application\/xml');
}catch(ex){}
finally{domParser = null;}
}
} catch(ex){
o.status.isError = true;
o.status.error = ex;
}
obj.responseXML = xdoc;
}
if(obj.responseXML){
var parseBad = (obj.responseXML.parseError || 0) != 0 || obj.responseXML.childNodes.length == 0;
if(!parseBad){
headerStr = 'Content-Type: ' + (obj.responseXML.contentType || 'text\/xml') + '\n' + headerStr ;
}
}
}
var header = headerStr.split('\n');
for (var i = 0; i < header.length; i++) {
var delimitPos = header[i].indexOf(':');
if (delimitPos != -1) {
headerObj[header[i].substring(0, delimitPos)] = header[i].substring(delimitPos + 2);
}
}
obj.tId = o.tId;
obj.status = o.status.status;
obj.statusText = o.status.statusText;
obj.getResponseHeader = headerObj;
obj.getAllResponseHeaders = headerStr;
obj.stat = o.status
if (typeof callbackArg !== undefined) {
obj.argument = callbackArg;
}
return obj;
},
request : function(method, uri, cb, data, options) {
options = Ext.apply({async:true,
headers:false,
userId:null,
password:null,
xmlData:null }, options||{});
var hs = options.headers;
if(hs){
for(var h in hs){
if(hs.hasOwnProperty(h)){
this.initHeader(h, hs[h], false);
}
}
}
if(options.xmlData){
this.initHeader('Content-Type', 'text/xml', false);
method = 'POST';
data = options.xmlData;
}
return this.makeRequest(method, uri, cb, data, options);
},
asyncRequest:function(method, uri, callback, postData)
{
var o = this.getConnectionObject();
if (!o || o.status.isError) {
return null;
}
else {
o.options = options;
try{
o.conn.open(method, uri, true);
} catch(ex){
o.status.isError = true;
o.status.error = ex;
return Ext.apply(o,this.handleTransactionResponse(o, callback));
}
if (this.useDefaultXhrHeader) {
if (!this.defaultHeaders['X-Requested-With']) {
this.initHeader('X-Requested-With', this.defaultXhrHeader, true);
}
}
if(postData && this.useDefaultHeader){
this.initHeader('Content-Type', this.defaultPostHeader);
}
if (this.hasDefaultHeaders || this.hasHeaders) {
this.setHeader(o);
}
this.handleReadyState(o, callback);
try{ o.conn.send(postData || null);
} catch(ex){
o.status.isError=true;
o.status.error = ex;
return Ext.apply(o,this.handleTransactionResponse(o, callback));
}
return o;
}
},
makeRequest:function(method, uri, callback, postData, options)
{
var o = this.getConnectionObject();
if (!o || o.status.isError) {
return null;
}
else {
o.options = options;
try{
o.conn.open(method, uri, options.async, options.userId, options.password);
} catch(ex){
o.status.isError = true;
o.status.error = ex;
var r=this.handleTransactionResponse(o, callback);
return Ext.apply(o,r);
}
if (this.useDefaultXhrHeader) {
if (!this.defaultHeaders['X-Requested-With']) {
this.initHeader('X-Requested-With', this.defaultXhrHeader, true);
}
}
if(postData && this.useDefaultHeader){
this.initHeader('Content-Type', this.defaultPostHeader);
}
if (this.hasDefaultHeaders || this.hasHeaders) {
this.setHeader(o);
}
if(o.options.async){ //blocking call때문에 Timer가 작동하지 않음
this.handleReadyState(o, callback);
}
try{ o.conn.send(postData || null);
} catch(ex){
//Ext.apply(o,this.handleTransactionResponse(o, callback));
}
return options.async?o:Ext.apply(o,this.handleTransactionResponse(o, callback));
}
}});
Ext.lib.Ajax.forceActiveX = (document.location.protocol == 'file:');
'Scripter > EXTJS' 카테고리의 다른 글
Extjs를 이용한 ExtPHP, PHP-Ext 프로젝트 오픈 (0) | 2008.03.07 |
---|---|
Extjs Grouping Header Grid Plugins (13) | 2008.03.06 |
Extjs 한국어로 나타내기 (locale설정) (9) | 2008.02.27 |
ExtJS을 이용한 RestFul한 통신하기 (2) | 2008.02.26 |
GWT Ext 2.0 이 릴리즈됐다. (0) | 2008.02.26 |