/trunk/api/js/dojo1.0/dojox/io/proxy/xip_server.html |
---|
New file |
0,0 → 1,386 |
<!-- |
/* |
Copyright (c) 2004-2006, The Dojo Foundation |
All Rights Reserved. |
Licensed under the Academic Free License version 2.1 or above OR the |
modified BSD license. For more information on Dojo licensing, see: |
http://dojotoolkit.org/community/licensing.shtml |
*/ |
Pieces taken from Dojo source to make this file stand-alone |
--> |
<html> |
<head> |
<title></title> |
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta> |
<script type="text/javascript" src="isAllowed.js"></script> |
<!-- |
BY DEFAULT THIS FILE DOES NOT WORK SO THAT YOU DON'T ACCIDENTALLY EXPOSE |
ALL OF YOUR XHR-ENABLED SERVICES ON YOUR SITE. |
In order for this file to work, you need to uncomment the start and end script tags, |
and you should define a function with the following signature: |
function isAllowedRequest(request){ |
return false; |
} |
Return true out of the function if you want to allow the cross-domain request. |
DON'T DEFINE THIS FUNCTION IN THIS FILE! Define it in a separate file called isAllowed.js |
and include it in this page with a script tag that has a src attribute pointing to the file. |
See the very first script tag in this file for an example. You do not have to place the |
script file in the same directory as this file, just update the path above if you move it |
somewhere else. |
Customize the isAllowedRequest function to restrict what types of requests are allowed |
for this server. The request object has the following properties: |
- requestHeaders: an object with the request headers that are to be added to |
the XHR request. |
- method: the HTTP method (GET, POST, etc...) |
- uri: The URI for the request. |
- data: The URL-encoded data for the request. For a GET request, this would |
be the querystring parameters. For a POST request, it wll be the |
body data. |
See xip_client.html for more info on the xip fragment identifier protocol. |
--> |
<!-- Security protection: uncomment the script tag to enable. --> |
<!-- script type="text/javascript" --> |
// <!-- |
//Core XHR handling taken from Dojo IO code. |
dojo = {}; |
dojo.hostenv = {}; |
// These are in order of decreasing likelihood; this will change in time. |
dojo.hostenv._XMLHTTP_PROGIDS = ['Msxml2.XMLHTTP', 'Microsoft.XMLHTTP', 'Msxml2.XMLHTTP.4.0']; |
dojo.hostenv.getXmlhttpObject = function(){ |
var http = null; |
var last_e = null; |
try{ http = new XMLHttpRequest(); }catch(e){} |
if(!http){ |
for(var i=0; i<3; ++i){ |
var progid = dojo.hostenv._XMLHTTP_PROGIDS[i]; |
try{ |
http = new ActiveXObject(progid); |
}catch(e){ |
last_e = e; |
} |
if(http){ |
dojo.hostenv._XMLHTTP_PROGIDS = [progid]; // so faster next time |
break; |
} |
} |
/*if(http && !http.toString) { |
http.toString = function() { "[object XMLHttpRequest]"; } |
}*/ |
} |
if(!http){ |
throw "xip_server.html: XMLHTTP not available: " + last_e; |
} |
return http; |
} |
dojo.setHeaders = function(http, headers){ |
if(headers) { |
for(var header in headers) { |
var headerValue = headers[header]; |
http.setRequestHeader(header, headerValue); |
} |
} |
} |
//MSIE has the lowest limit for URLs with fragment identifiers, |
//at around 4K. Choosing a slightly smaller number for good measure. |
xipUrlLimit = 4000; |
xipIdCounter = 1; |
function xipServerInit(){ |
xipStateId = ""; |
xipCurrentHash = ""; |
xipRequestMessage = ""; |
xipResponseParts = []; |
xipPartIndex = 0; |
} |
function pollHash(){ |
//Can't use location.hash because at least Firefox does a decodeURIComponent on it. |
var urlParts = window.location.href.split("#"); |
if(urlParts.length == 2){ |
var newHash = urlParts[1]; |
if(newHash != xipCurrentHash){ |
try{ |
messageReceived(newHash); |
}catch(e){ |
//Make sure to not keep processing the error hash value. |
xipCurrentHash = newHash; |
throw e; |
} |
xipCurrentHash = newHash; |
} |
} |
} |
function messageReceived(encodedData){ |
var msg = unpackMessage(encodedData); |
switch(msg.command){ |
case "ok": |
sendResponsePart(); |
break; |
case "start": |
xipRequestMessage = ""; |
xipRequestMessage += msg.message; |
setClientUrl("ok"); |
break; |
case "part": |
xipRequestMessage += msg.message; |
setClientUrl("ok"); |
break; |
case "end": |
setClientUrl("ok"); |
xipRequestMessage += msg.message; |
sendXhr(); |
break; |
} |
} |
function sendResponse(encodedData){ |
//Break the message into parts, if necessary. |
xipResponseParts = []; |
var resData = encodedData; |
var urlLength = xipClientUrl.length; |
var partLength = xipUrlLimit - urlLength; |
var resIndex = 0; |
while((resData.length - resIndex) + urlLength > xipUrlLimit){ |
var part = resData.substring(resIndex, resIndex + partLength); |
//Safari will do some extra hex escaping unless we keep the original hex |
//escaping complete. |
var percentIndex = part.lastIndexOf("%"); |
if(percentIndex == part.length - 1 || percentIndex == part.length - 2){ |
part = part.substring(0, percentIndex); |
} |
xipResponseParts.push(part); |
resIndex += part.length; |
} |
xipResponseParts.push(resData.substring(resIndex, resData.length)); |
xipPartIndex = 0; |
sendResponsePart(); |
} |
function sendResponsePart(){ |
if(xipPartIndex < xipResponseParts.length){ |
//Get the message part. |
var partData = xipResponseParts[xipPartIndex]; |
//Get the command. |
var cmd = "part"; |
if(xipPartIndex + 1 == xipResponseParts.length){ |
cmd = "end"; |
}else if (xipPartIndex == 0){ |
cmd = "start"; |
} |
setClientUrl(cmd, partData); |
xipPartIndex++; |
}else{ |
xipServerInit(); |
} |
} |
function setClientUrl(cmd, message){ |
var clientUrl = makeClientUrl(cmd, message); |
//Safari won't let us replace across domains. |
if(navigator.userAgent.indexOf("Safari") == -1){ |
parent.location.replace(clientUrl); |
}else{ |
parent.location = clientUrl; |
} |
} |
function makeClientUrl(cmd, message){ |
var clientUrl = xipClientUrl + "#" + (xipIdCounter++) + ":" + cmd; |
if(message){ |
clientUrl += ":" + message; |
} |
return clientUrl |
} |
function xhrDone(xhr){ |
/* Need to pull off and return the following data: |
- responseHeaders |
- status |
- statusText |
- responseText |
*/ |
var response = {}; |
if(typeof(xhr.getAllResponseHeaders) != "undefined"){ |
var allHeaders = xhr.getAllResponseHeaders(); |
if(allHeaders){ |
response.responseHeaders = allHeaders; |
} |
} |
if(xhr.status == 0 || xhr.status){ |
response.status = xhr.status; |
} |
if(xhr.statusText){ |
response.statusText = xhr.statusText; |
} |
if(xhr.responseText){ |
response.responseText = xhr.responseText; |
} |
//Build a string of the response object. |
var result = ""; |
var isFirst = true; |
for (var param in response){ |
if(isFirst){ |
isFirst = false; |
}else{ |
result += "&"; |
} |
result += param + "=" + encodeURIComponent(response[param]); |
} |
sendResponse(result); |
} |
function sendXhr(){ |
var request = {}; |
var nvPairs = xipRequestMessage.split("&"); |
var i = 0; |
var nameValue = null; |
for(i = 0; i < nvPairs.length; i++){ |
if(nvPairs[i]){ |
var nameValue = nvPairs[i].split("="); |
request[decodeURIComponent(nameValue[0])] = decodeURIComponent(nameValue[1]); |
} |
} |
//Split up the request headers, if any. |
var headers = {}; |
if(request.requestHeaders){ |
nvPairs = request.requestHeaders.split("\r\n"); |
for(i = 0; i < nvPairs.length; i++){ |
if(nvPairs[i]){ |
nameValue = nvPairs[i].split(": "); |
headers[decodeURIComponent(nameValue[0])] = decodeURIComponent(nameValue[1]); |
} |
} |
request.requestHeaders = headers; |
} |
if(isAllowedRequest(request)){ |
//The request is allowed, so set up the XHR object. |
var xhr = dojo.hostenv.getXmlhttpObject(); |
//Start timer to look for readyState. |
var xhrIntervalId = setInterval(function(){ |
if(xhr.readyState == 4){ |
clearInterval(xhrIntervalId); |
xhrDone(xhr); |
} |
}, 10); |
//Actually start up the XHR request. |
xhr.open(request.method, request.uri, true); |
dojo.setHeaders(xhr, request.requestHeaders); |
var content = ""; |
if(request.data){ |
content = request.data; |
} |
try{ |
xhr.send(content); |
}catch(e){ |
if(typeof xhr.abort == "function"){ |
xhr.abort(); |
xhrDone({status: 404, statusText: "xip_server.html error: " + e}); |
} |
} |
} |
} |
function unpackMessage(encodedMessage){ |
var parts = encodedMessage.split(":"); |
var command = parts[1]; |
encodedMessage = parts[2] || ""; |
var config = null; |
if(command == "init"){ |
var configParts = encodedMessage.split("&"); |
config = {}; |
for(var i = 0; i < configParts.length; i++){ |
var nameValue = configParts[i].split("="); |
config[decodeURIComponent(nameValue[0])] = decodeURIComponent(nameValue[1]); |
} |
} |
return {command: command, message: encodedMessage, config: config}; |
} |
function onServerLoad(){ |
xipServerInit(); |
//Decode the init params |
var config = unpackMessage(window.location.href.split("#")[1]).config; |
xipStateId = config.id; |
xipClientUrl = config.client; |
//Make sure we don't have a javascript: url, just for good measure. |
if(xipClientUrl.split(":")[0].match(/javascript/i)){ |
throw "Invalid client URL"; |
} |
if(!xipStateId.match(/^XhrIframeProxy[0-9]+$/)){ |
throw "Invalid state ID"; |
} |
xipUseFrameRecursion = config["fr"]; |
setInterval(pollHash, 10); |
if(xipUseFrameRecursion == "true"){ |
var serverUrl = window.location.href.split("#")[0]; |
document.getElementById("iframeHolder").innerHTML = '<iframe name="' |
+ xipStateId + '_clientEndPoint' |
+ '" src="javascript:false">' |
+ '</iframe>'; |
var iframeNode = document.getElementsByTagName("iframe")[0]; |
iframeNode.src = makeClientUrl("init", 'id=' + xipStateId + '&server=' |
+ encodeURIComponent(serverUrl) + '&fr=endpoint'); |
}else{ |
setClientUrl("loaded"); |
} |
} |
if(typeof(window.addEventListener) == "undefined"){ |
window.attachEvent("onload", onServerLoad); |
}else{ |
window.addEventListener('load', onServerLoad, false); |
} |
// --> |
<!-- </script> --> |
</head> |
<body> |
<h4>The Dojo Toolkit -- xip_server.html</h4> |
<p>This file is used for Dojo's XMLHttpRequest Iframe Proxy. This is the the file |
that should go on the server that will actually be doing the XHR request.</p> |
<div id="iframeHolder"></div> |
</body> |
</html> |
/trunk/api/js/dojo1.0/dojox/io/proxy/xip.js |
---|
New file |
0,0 → 1,236 |
if(!dojo._hasResource["dojox.io.proxy.xip"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code. |
dojo._hasResource["dojox.io.proxy.xip"] = true; |
dojo.provide("dojox.io.proxy.xip"); |
dojo.require("dojo.io.iframe"); |
dojo.require("dojox.data.dom"); |
dojox.io.proxy.xip = { |
//summary: Object that implements the iframe handling for XMLHttpRequest |
//IFrame Proxying. |
//description: Do not use this object directly. See the Dojo Book page |
//on XMLHttpRequest IFrame Proxying: |
//http://dojotoolkit.org/book/dojo-book-0-4/part-5-connecting-pieces/i-o/cross-domain-xmlhttprequest-using-iframe-proxy |
//Usage of XHR IFrame Proxying does not work from local disk in Safari. |
xipClientUrl: djConfig["xipClientUrl"] || dojo.moduleUrl("dojox.io.proxy", "xip_client.html"), |
_state: {}, |
_stateIdCounter: 0, |
needFrameRecursion: function(){ |
return (dojo.isIE >= 7); |
}, |
send: function(facade){ |
var stateId = "XhrIframeProxy" + (this._stateIdCounter++); |
facade._stateId = stateId; |
var frameUrl = this.xipClientUrl + "#0:init:id=" + stateId + "&server=" |
+ encodeURIComponent(facade._ifpServerUrl) + "&fr=false"; |
if(this.needFrameRecursion()){ |
//IE7 hack. Need to load server URL, and have that load the xip_client.html. |
//Also, this server URL needs to different from the one eventually loaded by xip_client.html |
//Otherwise, IE7 will not load it. Funky. |
var fullClientUrl = window.location.href.split("#")[0].split("?")[0]; |
if((this.xipClientUrl + "").charAt(0) == "/"){ |
var endIndex = fullClientUrl.indexOf("://"); |
endIndex = fullClientUrl.indexOf("/", endIndex + 3); |
fullClientUrl = fullClientUrl.substring(0, endIndex); |
}else{ |
fullClientUrl = fullClientUrl.substring(0, fullClientUrl.lastIndexOf("/") + 1); |
} |
fullClientUrl += this.xipClientUrl; |
var serverUrl = facade._ifpServerUrl |
+ (facade._ifpServerUrl.indexOf("?") == -1 ? "?" : "&") + "dojo.fr=1"; |
frameUrl = serverUrl + "#0:init:id=" + stateId + "&client=" |
+ encodeURIComponent(fullClientUrl) + "&fr=" + this.needFrameRecursion(); //fr is for Frame Recursion |
} |
this._state[stateId] = { |
facade: facade, |
stateId: stateId, |
clientFrame: dojo.io.iframe.create(stateId, "", frameUrl) |
}; |
return stateId; |
}, |
receive: function(/*String*/stateId, /*String*/urlEncodedData){ |
/* urlEncodedData should have the following params: |
- responseHeaders |
- status |
- statusText |
- responseText |
*/ |
//Decode response data. |
var response = {}; |
var nvPairs = urlEncodedData.split("&"); |
for(var i = 0; i < nvPairs.length; i++){ |
if(nvPairs[i]){ |
var nameValue = nvPairs[i].split("="); |
response[decodeURIComponent(nameValue[0])] = decodeURIComponent(nameValue[1]); |
} |
} |
//Set data on facade object. |
var state = this._state[stateId]; |
var facade = state.facade; |
facade._setResponseHeaders(response.responseHeaders); |
if(response.status == 0 || response.status){ |
facade.status = parseInt(response.status, 10); |
} |
if(response.statusText){ |
facade.statusText = response.statusText; |
} |
if(response.responseText){ |
facade.responseText = response.responseText; |
//Fix responseXML. |
var contentType = facade.getResponseHeader("Content-Type"); |
if(contentType && (contentType == "application/xml" || contentType == "text/xml")){ |
facade.responseXML = dojox.data.dom.createDocument(response.responseText, contentType); |
} |
} |
facade.readyState = 4; |
this.destroyState(stateId); |
}, |
clientFrameLoaded: function(/*String*/stateId){ |
var state = this._state[stateId]; |
var facade = state.facade; |
if(this.needFrameRecursion()){ |
var clientWindow = window.open("", state.stateId + "_clientEndPoint"); |
}else{ |
var clientWindow = state.clientFrame.contentWindow; |
} |
var reqHeaders = []; |
for(var param in facade._requestHeaders){ |
reqHeaders.push(param + ": " + facade._requestHeaders[param]); |
} |
var requestData = { |
uri: facade._uri |
}; |
if(reqHeaders.length > 0){ |
requestData.requestHeaders = reqHeaders.join("\r\n"); |
} |
if(facade._method){ |
requestData.method = facade._method; |
} |
if(facade._bodyData){ |
requestData.data = facade._bodyData; |
} |
clientWindow.send(dojo.objectToQuery(requestData)); |
}, |
destroyState: function(/*String*/stateId){ |
var state = this._state[stateId]; |
if(state){ |
delete this._state[stateId]; |
var parentNode = state.clientFrame.parentNode; |
parentNode.removeChild(state.clientFrame); |
state.clientFrame = null; |
state = null; |
} |
}, |
createFacade: function(){ |
if(arguments && arguments[0] && arguments[0].iframeProxyUrl){ |
return new dojox.io.proxy.xip.XhrIframeFacade(arguments[0].iframeProxyUrl); |
}else{ |
return dojox.io.proxy.xip._xhrObjOld.apply(dojo, arguments); |
} |
} |
} |
//Replace the normal XHR factory with the proxy one. |
dojox.io.proxy.xip._xhrObjOld = dojo._xhrObj; |
dojo._xhrObj = dojox.io.proxy.xip.createFacade; |
/** |
Using this a reference: http://www.w3.org/TR/XMLHttpRequest/ |
Does not implement the onreadystate callback since dojo.xhr* does |
not use it. |
*/ |
dojox.io.proxy.xip.XhrIframeFacade = function(ifpServerUrl){ |
//summary: XMLHttpRequest facade object used by dojox.io.proxy.xip. |
//description: Do not use this object directly. See the Dojo Book page |
//on XMLHttpRequest IFrame Proxying: |
//http://dojotoolkit.org/book/dojo-book-0-4/part-5-connecting-pieces/i-o/cross-domain-xmlhttprequest-using-iframe-proxy |
this._requestHeaders = {}; |
this._allResponseHeaders = null; |
this._responseHeaders = {}; |
this._method = null; |
this._uri = null; |
this._bodyData = null; |
this.responseText = null; |
this.responseXML = null; |
this.status = null; |
this.statusText = null; |
this.readyState = 0; |
this._ifpServerUrl = ifpServerUrl; |
this._stateId = null; |
} |
dojo.extend(dojox.io.proxy.xip.XhrIframeFacade, { |
//The open method does not properly reset since Dojo does not reuse XHR objects. |
open: function(/*String*/method, /*String*/uri){ |
this._method = method; |
this._uri = uri; |
this.readyState = 1; |
}, |
setRequestHeader: function(/*String*/header, /*String*/value){ |
this._requestHeaders[header] = value; |
}, |
send: function(/*String*/stringData){ |
this._bodyData = stringData; |
this._stateId = dojox.io.proxy.xip.send(this); |
this.readyState = 2; |
}, |
abort: function(){ |
dojox.io.proxy.xip.destroyState(this._stateId); |
}, |
getAllResponseHeaders: function(){ |
return this._allResponseHeaders; //String |
}, |
getResponseHeader: function(/*String*/header){ |
return this._responseHeaders[header]; //String |
}, |
_setResponseHeaders: function(/*String*/allHeaders){ |
if(allHeaders){ |
this._allResponseHeaders = allHeaders; |
//Make sure ther are now CR characters in the headers. |
allHeaders = allHeaders.replace(/\r/g, ""); |
var nvPairs = allHeaders.split("\n"); |
for(var i = 0; i < nvPairs.length; i++){ |
if(nvPairs[i]){ |
var nameValue = nvPairs[i].split(": "); |
this._responseHeaders[nameValue[0]] = nameValue[1]; |
} |
} |
} |
} |
}); |
} |
/trunk/api/js/dojo1.0/dojox/io/proxy/README |
---|
New file |
0,0 → 1,82 |
------------------------------------------------------------------------------- |
Project Name |
------------------------------------------------------------------------------- |
Version 0.5 |
Release date: MM/DD/YYYY (in progres, porting) |
------------------------------------------------------------------------------- |
Project state: |
experimental |
------------------------------------------------------------------------------- |
Credits |
James Burke (jburke@dojotoolkit.org) |
------------------------------------------------------------------------------- |
Project description |
The XHR IFrame Proxy (xip) allows you to do cross-domain XMLHttpRequests (XHRs). |
It works by using two iframes, one your domain (xip_client.html), one on the |
other domain (xip_server.html). They use fragment IDs in the iframe URLs to pass |
messages to each other. The xip.js file defines dojox.io.proxy.xip. This module |
intercepts XHR calls made by the Dojo XHR methods (dojo.xhr* methods). The module |
returns a facade object that acts like an XHR object. Once send is called on the |
facade, the facade's data is serialized, given to xip_client.html. xip_client.html |
then passes the serialized data to xip_server.html by changing xip_server.html's |
URL fragment ID (the #xxxx part of an URL). xip_server.html deserializes the |
message fragments, and does an XHR call, gets the response, and serializes the |
data. The serialized data is then passed back to xip_client.html by changing |
xip_client.html's fragment ID. Then the response is deserialized and used as |
the response inside the facade XHR object that was created by dojox.io.proxy.xip. |
------------------------------------------------------------------------------- |
Dependencies: |
xip.js: Dojo Core, dojox.data.dom |
xip_client.html: none |
xip_server.html: none (but see Additional Notes section) |
------------------------------------------------------------------------------- |
Documentation |
There is some documentation that applies to the Dojo 0.4.x version of these files: |
http://dojotoolkit.org/book/dojo-book-0-4/part-5-connecting-pieces/i-o/cross-domain-xmlhttprequest-using-iframe-proxy |
The general theory still applies to this code, but the specifics are different |
for the Dojo 0.9+ codebase. Doc updates hopefully after the basic code is ported. |
The current implementation destroys the iframes used for a request after the request |
completes. This seems to cause a memory leak, particularly in IE. So, it is not |
suited for doing polling cross-domain requests. |
------------------------------------------------------------------------------- |
Installation instructions |
Grab the following from the Dojox SVN Repository: |
http://svn.dojotoolkit.org/var/src/dojo/dojox/trunk/io/proxy/xip.js |
http://svn.dojotoolkit.org/var/src/dojo/dojox/trunk/io/proxy/xip_client.html |
Install into the following directory structure: |
/dojox/io/proxy/ |
...which should be at the same level as your Dojo checkout. |
Grab the following from the Dojox SVN Repository: |
http://svn.dojotoolkit.org/var/src/dojo/dojox/trunk/io/proxy/xip_server.html |
and install it on the domain that you want to allow receiving cross-domain |
requests. Be sure to read the documentation, the Additional Notes below, and |
the in-file comments. |
------------------------------------------------------------------------------- |
Additional Notes |
xip_client.html and xip_server.html do not work right away. You need to uncomment |
out the script tags in the files. Additionally, xip_server.html requires a JS file, |
isAllowed.js, to be defined. See the notes in xip_server.html for more informaiton. |
XDOMAIN BUILD INSTRUCTIONS: |
The dojox.io.proxy module requires some setup to use with an xdomain build. |
The xip_client.html file has to be served from the same domain as your web page. |
It cannot be served from the domain that has the xdomain build. Download xip_client.html |
and install it on your server. Then set djConfig.xipClientUrl to the local path |
of xip_client.html (just use a path, not a whole URL, since it will be on the same |
domain as the page). The path to the file should be the path relative to the web |
page that is using dojox.io.proxy. |
/trunk/api/js/dojo1.0/dojox/io/proxy/xip_client.html |
---|
New file |
0,0 → 1,267 |
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" |
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> |
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> |
<head> |
<title></title> |
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta> |
<!-- Security protection: uncomment the start and end script tags to enable. --> |
<!-- script type="text/javascript" --> |
// <!-- |
/* |
This file is really focused on just sending one message to the server, and |
receiving one response. The code does not expect to be re-used for multiple messages. |
This might be reworked later if performance indicates a need for it. |
xip fragment identifier/hash values have the form: |
#id:cmd:realEncodedMessage |
id: some ID that should be unique among messages. No inherent meaning, |
just something to make sure the hash value is unique so the message |
receiver knows a new message is available. |
cmd: command to the receiver. Valid values are: |
- init: message used to init the frame. Sent as the first URL when loading |
the page. Contains some config parameters. |
- loaded: the remote frame is loaded. Only sent from server to client. |
- ok: the message that this page sent was received OK. The next message may |
now be sent. |
- start: the start message of a block of messages (a complete message may |
need to be segmented into many messages to get around the limitiations |
of the size of an URL that a browser accepts. |
- part: indicates this is a part of a message. |
- end: the end message of a block of messages. The message can now be acted upon. |
If the message is small enough that it doesn't need to be segmented, then |
just one hash value message can be sent with "end" as the command. |
To reassemble a segmented message, the realEncodedMessage parts just have to be concatenated |
together. |
*/ |
//MSIE has the lowest limit for URLs with fragment identifiers, |
//at around 4K. Choosing a slightly smaller number for good measure. |
xipUrlLimit = 4000; |
xipIdCounter = 1; |
function xipInit(){ |
xipStateId = ""; |
xipIsSending = false; |
xipServerUrl = null; |
xipStateId = null; |
xipRequestData = null; |
xipCurrentHash = ""; |
xipResponseMessage = ""; |
xipRequestParts = []; |
xipPartIndex = 0; |
xipServerWindow = null; |
xipUseFrameRecursion = false; |
} |
xipInit(); |
function send(encodedData){ |
if(xipUseFrameRecursion == "true"){ |
var clientEndPoint = window.open(xipStateId + "_clientEndPoint"); |
clientEndPoint.send(encodedData); |
}else{ |
if(!xipIsSending){ |
xipIsSending = true; |
xipRequestData = encodedData || ""; |
//Get a handle to the server iframe. |
xipServerWindow = frames[xipStateId + "_frame"]; |
if (!xipServerWindow){ |
xipServerWindow = document.getElementById(xipStateId + "_frame").contentWindow; |
} |
sendRequestStart(); |
} |
} |
} |
//Modify the server URL if it is a local path and |
//This is done for local/same domain testing. |
function fixServerUrl(ifpServerUrl){ |
if(ifpServerUrl.indexOf("..") == 0){ |
var parts = ifpServerUrl.split("/"); |
ifpServerUrl = parts[parts.length - 1]; |
} |
return ifpServerUrl; |
} |
function pollHash(){ |
//Can't use location.hash because at least Firefox does a decodeURIComponent on it. |
var urlParts = window.location.href.split("#"); |
if(urlParts.length == 2){ |
var newHash = urlParts[1]; |
if(newHash != xipCurrentHash){ |
try{ |
messageReceived(newHash); |
}catch(e){ |
//Make sure to not keep processing the error hash value. |
xipCurrentHash = newHash; |
throw e; |
} |
xipCurrentHash = newHash; |
} |
} |
} |
function messageReceived(encodedData){ |
var msg = unpackMessage(encodedData); |
switch(msg.command){ |
case "loaded": |
xipMasterFrame.dojox.io.proxy.xip.clientFrameLoaded(xipStateId); |
break; |
case "ok": |
sendRequestPart(); |
break; |
case "start": |
xipResponseMessage = ""; |
xipResponseMessage += msg.message; |
setServerUrl("ok"); |
break; |
case "part": |
xipResponseMessage += msg.message; |
setServerUrl("ok"); |
break; |
case "end": |
setServerUrl("ok"); |
xipResponseMessage += msg.message; |
xipMasterFrame.dojox.io.proxy.xip.receive(xipStateId, xipResponseMessage); |
break; |
} |
} |
function sendRequestStart(){ |
//Break the message into parts, if necessary. |
xipRequestParts = []; |
var reqData = xipRequestData; |
var urlLength = xipServerUrl.length; |
var partLength = xipUrlLimit - urlLength; |
var reqIndex = 0; |
while((reqData.length - reqIndex) + urlLength > xipUrlLimit){ |
var part = reqData.substring(reqIndex, reqIndex + partLength); |
//Safari will do some extra hex escaping unless we keep the original hex |
//escaping complete. |
var percentIndex = part.lastIndexOf("%"); |
if(percentIndex == part.length - 1 || percentIndex == part.length - 2){ |
part = part.substring(0, percentIndex); |
} |
xipRequestParts.push(part); |
reqIndex += part.length; |
} |
xipRequestParts.push(reqData.substring(reqIndex, reqData.length)); |
xipPartIndex = 0; |
sendRequestPart(); |
} |
function sendRequestPart(){ |
if(xipPartIndex < xipRequestParts.length){ |
//Get the message part. |
var partData = xipRequestParts[xipPartIndex]; |
//Get the command. |
var cmd = "part"; |
if(xipPartIndex + 1 == xipRequestParts.length){ |
cmd = "end"; |
}else if (xipPartIndex == 0){ |
cmd = "start"; |
} |
setServerUrl(cmd, partData); |
xipPartIndex++; |
} |
} |
function setServerUrl(cmd, message){ |
var serverUrl = makeServerUrl(cmd, message); |
//Safari won't let us replace across domains. |
if(navigator.userAgent.indexOf("Safari") == -1){ |
xipServerWindow.location.replace(serverUrl); |
}else{ |
xipServerWindow.location = serverUrl; |
} |
} |
function makeServerUrl(cmd, message){ |
var serverUrl = xipServerUrl + "#" + (xipIdCounter++) + ":" + cmd; |
if(message){ |
serverUrl += ":" + message; |
} |
return serverUrl; |
} |
function unpackMessage(encodedMessage){ |
var parts = encodedMessage.split(":"); |
var command = parts[1]; |
encodedMessage = parts[2] || ""; |
var config = null; |
if(command == "init"){ |
var configParts = encodedMessage.split("&"); |
config = {}; |
for(var i = 0; i < configParts.length; i++){ |
var nameValue = configParts[i].split("="); |
config[decodeURIComponent(nameValue[0])] = decodeURIComponent(nameValue[1]); |
} |
} |
return {command: command, message: encodedMessage, config: config}; |
} |
function onClientLoad(){ |
//Decode the init params |
var config = unpackMessage(window.location.href.split("#")[1]).config; |
xipStateId = config.id; |
//Remove the query param for the IE7 recursive case. |
xipServerUrl = fixServerUrl(config.server).replace(/(\?|\&)dojo\.fr\=1/, ""); |
//Make sure we don't have a javascript: url, just for good measure. |
if(xipServerUrl.split(":")[0].match(/javascript/i)){ |
throw "Invalid server URL"; |
} |
xipUseFrameRecursion = config["fr"]; |
if(xipUseFrameRecursion == "endpoint"){ |
xipMasterFrame = parent.parent; |
}else{ |
xipMasterFrame = parent; |
} |
//Start counter to inspect hash value. |
setInterval(pollHash, 10); |
var clientUrl = window.location.href.split("#")[0]; |
var iframeNode = document.getElementsByTagName("iframe")[0]; |
iframeNode.id = xipStateId + "_frame"; |
iframeNode.src = makeServerUrl("init", 'id=' + xipStateId + '&client=' |
+ encodeURIComponent(clientUrl) + '&fr=' + xipUseFrameRecursion); |
} |
if(typeof(window.addEventListener) == "undefined"){ |
window.attachEvent("onload", onClientLoad); |
}else{ |
window.addEventListener('load', onClientLoad, false); |
} |
// --> |
<!-- </script> --> |
</head> |
<body> |
<h4>The Dojo Toolkit -- xip_client.html</h4> |
<p>This file is used for Dojo's XMLHttpRequest Iframe Proxy. This is the "client" file used |
internally by dojox.io.proxy.xip.</p> |
<iframe src="javascript:false"></iframe> |
</body> |
</html> |
/trunk/api/js/dojo1.0/dojox/io/proxy/tests/xip.html |
---|
New file |
0,0 → 1,62 |
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" |
"http://www.w3.org/TR/html4/strict.dtd"> |
<html> |
<head> |
<title>XHR IFrame Proxy Tests</title> |
<style type="text/css"> |
@import "../../../../dojo/resources/dojo.css"; |
@import "../../../../dijit/themes/tundra/tundra.css"; |
@import "../../../../dijit/themes/dijit.css"; |
</style> |
<script type="text/javascript" src="../../../../dojo/dojo.js" |
djConfig="isDebug:true"></script> |
<script type="text/javascript" src="../xip.js"></script> |
<script type="text/javascript"> |
dojo.require("dojox.io.proxy.xip"); |
function testXmlGet(){ |
/* |
//Normal xhrGet call. |
dojo.xhrGet({ |
url: "frag.xml", |
handleAs: "xml", |
load: function(result, ioArgs){ |
var foo = result.getElementsByTagName("foo").item(0); |
dojo.byId("xmlGetOut").innerHTML = "Success: First foobar value is: " + foo.firstChild.nodeValue; |
} |
}); |
*/ |
//xip xhrGet call. |
dojo.xhrGet({ |
iframeProxyUrl: "../xip_server.html", |
url: "tests/frag.xml", |
handleAs: "xml", |
load: function(result, ioArgs){ |
var foo = result.getElementsByTagName("foo").item(0); |
dojo.byId("xmlGetOut").innerHTML = "Success: First foobar value is: " + foo.firstChild.nodeValue; |
} |
}); |
} |
dojo.addOnLoad(function(){ |
}); |
</script> |
</head> |
<body class="tundra"> |
<h1>XHR IFrame Proxy Tests</h1> |
<p>Run this test from a web server, not from local disk.</p> |
<p> |
<button onclick="testXmlGet()">Test XML GET</button> |
</p> |
<div id="xmlGetOut"></div> |
</body> |
</html> |
/trunk/api/js/dojo1.0/dojox/io/proxy/tests/frag.xml |
---|
New file |
0,0 → 1,4 |
<response> |
<foo>This is the foo text node value</foo> |
<bar>This is the bar text node value</bar> |
</response> |