[英]Redirect a Popup and Post Message
I am stuck in a problem where i have to redirect from a popup window to a different domain and post a message to it. 我陷入了一个问题,我必须将其从弹出窗口重定向到另一个域并向其发布消息。 Here is the scenario :- 这是场景:-
I am able to receive messages if i open fresh popup and do post message but not in the case of redirection. 如果我打开新的弹出窗口并发布消息,但能够接收消息,但在重定向的情况下却不能。 Here is my code: 这是我的代码:
http://domain_one.com - http://domain_one.com-
function redirect(formData,popup) {
//popup=window ref object
popup.location.href="http://domain_two.com"
popup.postMessage(JSON.stringify(formData),
"http://domain_two.com");
}
http://domain_two.com - http://domain_two.com-
window.addEventListener("message", receiveMessage, false);
function receiveMessage(event)
{
if (event.origin !== "http://domain_one.com")
return;
let data=event.data;
//....
}
One issue with the code at the question is that .postMessage()
is called immediately following setting a new .location.href
at popup
without waiting for the load
event of window
at 与该问题的代码的一个问题是, .postMessage()
是直接调用下面设置一个新的.location.href
在popup
,而无需等待load
的事件window
在
popup.location.href="http://domain_two.com"
popup.postMessage(JSON.stringify(formData),
"http://domain_two.com");
To achieve the expected result you can control the process from the original window
('index.html'). 为了获得预期的结果,您可以从原始window
('index.html')控制该过程。 Each window.name
is set to a unique value. 每个window.name
均设置为唯一值。 When the <form>
is submitted at "http://domain_one.com"
the resulting FormData
can be converted to an ArrayBuffer
and transferred to index.html
, then popup
( a.html
) location.href
is set to "http://domain_two.com"
. 将<form>
提交到"http://domain_one.com"
,可以将生成的FormData
转换为ArrayBuffer
并传输到index.html
,然后popup
( a.html
) location.href
设置为"http://domain_two.com"
。 At load
event of b.html
.postMessage()
the name
of the window
to index.html
. 在b.html
.postMessage()
的load
事件发生时, index.html
的window
name
。 Then the FormData
is passed to .postMessage()
where b.html
gets the FormData
that was originally submitted at b.html
. 然后FormData
传递给.postMessage()
其中b.html
得到FormData
,最初在提交b.html
。
(The origin
checks might need to be adjusted at the below code. The code was tested at plnkr, where simulation of cross-domain messaging is not 1:1, though should provide a pattern for how to accomplish the requirement). (可能需要在下面的代码中调整origin
检查。该代码在plnkr上进行了测试,在该代码中,跨域消息传递的模拟不是1:1,尽管应该提供一种如何实现要求的模式)。
index.html ( opener
) index.html( opener
)
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<script>
// open `popup`
const popup = window.open('a.html');
// create random values to assign to `name` at `a.html` and `b.html`
const [firstName, lastName] = [...Array(2)].map(_ => new Uint32Array(16));
[firstName, lastName].forEach(buffer => window.crypto.getRandomValues(buffer));
const [decoder, encoder] = [new TextDecoder(), new TextEncoder()];
const [first, last] = [firstName, lastName].map(buffer => decoder.decode(buffer));
// set `name` of `popup` (`a.html`) to `first`
popup.name = first;
let data;
window.addEventListener("message", e => {
// check `name` of `source`
if (e.source.name === first) {
console.log(e.source.name);
// store `formData`
data = decoder.decode(e.data);
console.log(e, JSON.parse(decoder.decode(e.data)));
// set `name` of `popup` to `last`
popup.name = last;
// redirect `popup` to `b.html`
popup.location.href = "b.html";
}
// check if `name` of `source` (`b.html`) is `last`
if (e.source.name === last) {
// encode the stored `formData`
let curr = encoder.encode(data);
console.log(e.source.name, e.data);
// transfer `formData` to `b.html`
e.source.postMessage(curr.buffer, e.source.location.href, [curr.buffer]);
// data = void 0;
}
})
</script>
</body>
</html>
a.html ( popup
, "http://domain_one.com"
) a.html( popup
, "http://domain_one.com"
)
<!DOCTYPE html>
<html>
<head>
</head>
<body>
a
<form>
<input name="input">
<input type="submit">
</form>
<script>
document.forms[0].onsubmit = e => {
// prevent default `form` submission
e.preventDefault();
// pass `form` to `FormData`
const formData = new FormData(e.target);
// encode `formData` as a `Uint8Array`
const encoded = new TextEncoder().encode(JSON.stringify([...formData.entries()]));
console.log(encoded);
// transfer `encoded` to `opener` (`index.html`)
opener.postMessage(encoded.buffer, opener.location.href, [encoded.buffer]);
}
</script>
</body>
</html>
b.html ( popup
, "http://domain_two.com"
) b.html( popup
, "http://domain_two.com"
)
<!DOCTYPE html>
<html>
<head>
</head>
<body>
b
<script>
const decoder = new TextDecoder();
let data;
window.addEventListener("message", receiveMessage, false);
function receiveMessage(event) {
// check `origin` of `event`
if (event.origin !== opener.location.origin)
return;
console.log(event);
// process `formData` from `popup`
data = JSON.parse(decoder.decode(event.data));
// do stuff with `formData`
p.textContent = JSON.stringify(data, null, 2);
}
// wait for `load` event to be dispatched before posting message to `opener`
onload = () => {
opener.postMessage("ok", opener.location.href);
}
</script>
<pre id="p"></pre>
</body>
</html>
您可以使用查询字符串参数将表单数据传递到"http://domain_two.com"
然后在第二个域的load
事件时解析location.href
的查询字符串
popup.location.href = `http://domain_two.com?${new URLSearchParams(formData.entries()).toString()}`
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.