简体   繁体   English

重定向弹出窗口并发布消息

[英]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 :- 这是场景:-

  1. User opens a new popup window which stays in same domain.(ex: http://doamin_one.com ) 用户打开一个位于相同域中的新弹出窗口。(例如: http : //doamin_one.com
  2. User fills the form in the popup window and clicks submit. 用户在弹出窗口中填写表格,然后单击提交。 This should redirect the window to http://doamin_two.com and domain_two.com should receive form data via post message. 这应该将窗口重定向到http: //doamin_two.com,domain_two.com应该通过发布消息接收表单数据。

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.hrefpopup ,而无需等待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 ,然后popupa.htmllocation.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.htmlwindow 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>

plnkr nk

您可以使用查询字符串参数将表单数据传递到"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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM