I am having trouble catching errors when using window.postMessage().
I want to be able to capture the error I am getting -
"Unable to post message to . Recipient has origin
Simple example code ( should error ):
try {
window.postMessage('1','');
}
catch (e) {
alert('error');
}
More detailed process flow: I am adding a cross domain iframe to the document with jQuery and then posting to it. This shouldn't error because the target origins should match - they are both set by the proxyDomain variable.
var $iframeProxy = $('<iframe id="myIFrame" src="' + proxyDomain + '"></iframe>').appendTo('body');
window.storageProxy = $iframeProxy[0].contentWindow;
try {
window.storageProxy.postMessage(message, proxyDomain);
}
catch (e) {
alert('error');
}
I am having trouble catching errors when using window.postMessage().
I want to be able to capture the error I am getting -
"Unable to post message to http://www.that-domain.com. Recipient has origin http://www.this-domain.com
Simple example code ( should error ):
try {
window.postMessage('1','http://www.differentDomain.com');
}
catch (e) {
alert('error');
}
More detailed process flow: I am adding a cross domain iframe to the document with jQuery and then posting to it. This shouldn't error because the target origins should match - they are both set by the proxyDomain variable.
var $iframeProxy = $('<iframe id="myIFrame" src="' + proxyDomain + '"></iframe>').appendTo('body');
window.storageProxy = $iframeProxy[0].contentWindow;
try {
window.storageProxy.postMessage(message, proxyDomain);
}
catch (e) {
alert('error');
}
Share
Improve this question
edited Jun 13, 2013 at 6:43
Kevin M
asked Jun 13, 2013 at 6:19
Kevin MKevin M
1,57417 silver badges38 bronze badges
3
- 3 did you ever get a solution to this? – andy mccullough Commented Aug 31, 2016 at 9:31
- 1 Sadly, I have not yet. – Kevin M Commented Sep 1, 2016 at 14:34
- no problem, thanks for getting back – andy mccullough Commented Sep 1, 2016 at 14:59
3 Answers
Reset to default 8No way to catch the error, but usually the error happens if the target origin is different, the case is test vs production scenario.
So you can check what is the parent domain and change the target origin accordingly:
function getTargetOrigin()
{
try {
var url = (window.location != window.parent.location) ? document.referrer : document.location.href;
if (url.indexOf('www.myproduction-website.com')!=-1)
return document.location.protocol + '//www.myproduction-website.com'
else //set the alternative target
return document.location.protocol + '//' + url.split('/')[2];
}
catch(e) //falback to production
{
return document.location.protocol + '//www.myproduction-website.com'
}
}
and use it inside the postMessage function:
function postMessage(message){
window.top.postMessage( message,getTargetOrigin());
}
With this solution you can use the same code in multiple server configuration without hard coding the targetOrigin url.
This solution fails if you navigate inside the frame and you recheck the document.referrer, in that case it will contain not the parent url but the previous frame url. In that case consider to use the '*' as targetOrigin url, it's the only working solution to send messages to other domains.
Hope it helps!
Looks like it is outlined in the HTML5 spec that if the domain origins do not match then no error is thrown and it should abort silently.
http://www.whatwg.org/specs/web-apps/current-work/multipage/web-messaging.html#web-messaging
10.4.3 Posting messages - Part #9
"...if the targetOrigin argument is an absolute URL, and the Document of the Window object on which the method was invoked does not have the same origin as targetOrigin, then abort these steps silently."
I would add to matteo-conta
's solution improved security, to prevent fake domains like www.myproduction-website.com.fakedomain.com
from receiving messages:
function getTargetOrigin() {
const domainDev = 'mydev-website.com';
const domainProd = 'myproduction-website.com';
try {
var url = (window.location !== window.parent.location) ? document.referrer : document.location.href;
const domain = url.split('/')[2];
if (domain.endsWith(domainDev) || domain.endsWith(domainProd))
return document.location.protocol + domain;
else return '';
} catch(e) {
return ''
}
}
const targetOrigin = getTargetOrigin();
try{
if (targetOrigin) window.parent.postMessage(${msg}, targetOrigin);
} catch(e) {
window.parent.postMessage(e, '*')
}
I also added posting the error message to any targetOrigin so that you would be able to capture it on your website's end using:
window.addEventListener("message", onResponse, false);
onResponse(res) {
const data = _.get(res, 'data');
if (res.origin === 'iframe-url-goes-here') {
console.log('message from iframe', data)
}
}