在对话框中托管一个网站并确保与Google Sheet和后端的通信

问题描述 投票:0回答:1

我正在制作一个 Google 表格插件。该插件打开一个无模式对话框,其中托管 www.myfrontend.com,它使用 www.mybackend.com 作为后端。

1.使用 createHtmlOutput 和 iframe

要实现这一点,一种方法是使用

iframe
,如下所示:

var htmlOutput = HtmlService
    .createHtmlOutput('<iframe src="https://www.myfrontend.com/#/home" style="width: 100%; height: 800px; border: none;"></iframe>'
    .setWidth(600)
    .setHeight(800);
SpreadsheetApp.getUi().showModelessDialog(htmlOutput, 'My add-on');

通过这种方法,myfrontend.com 可以显示在对话框中,并且调用 mybackend.com 没有任何问题。然而,myfrontend.com 中似乎没有

google
;我无法在 myfrontend.com 中拨打
google.script.run.withSuccessHandler(res).withFailureHandler(rej)...
。因此,myfrontend.com 无法与 Google Sheet 通信。

2.使用createHtmlOutputFromFile

另一种方法是在 Apps 脚本中拥有另一个类似

production.html
的文件,并按如下方式使用它:

var htmlOutput = HtmlService
    .createHtmlOutputFromFile('production')
    .setWidth(600)
    .setHeight(800);
SpreadsheetApp.getUi().showModelessDialog(htmlOutput, 'My add-on');

production.html
复制自 myfrontend.com 的
build/index.html
,并稍作修改:

<!doctype html>
  <html lang="en">
    <head>
      <meta charset="utf-8"/>
      <base href="https://www.myfrontend.com/">
      <link rel="icon" href="/favicon.ico"/>
      <meta name="viewport" content="width=device-width,initial-scale=1"/>
      <meta name="theme-color" content="#ffffff"/>
      <meta name="description" content="Web site created using create-react-app"/>
      <link rel="apple-touch-icon" href="/logo192.png"/><link rel="manifest" href="/manifest.json"/>
      <meta charset="utf-8"/><meta charset="UTF-8"/><meta http-equiv="X-UA-Compatible" content="IE=Edge"/>
      <title>myApp</title>
      <script>window.location.hash = "#/home"</script>
      ... ...

通过这种方法,myfrontend.com 可以显示在对话框中,并且看起来

google
google.script.run
在 myfrontend.com 中可用。但是,当我们登录 myfrontend.com 时,浏览器返回 CORS 错误:

[Error] Origin https://n-5fydpzckmar5yncflnjytuyfcusdcfogmgc2eti-1lu-script.googleusercontent.com is not allowed by Access-Control-Allow-Origin. Status code: 204
[Error] XMLHttpRequest cannot load https://www.mybackend.com/httpOnly/signin due to access control checks.

www.backend.com
app.js中,我已经启用了CORS,如下,但错误仍然存在:

app.use(cors({
  origin: [/\.mybackend\.com$/, /\.myfrontend\.com$/, /localhost(:[0-9]*)?$/, /\.live\.com$/, "https://onedrive.live.com", /https:\/\/[\w-]+\.script\.googleusercontent\.com/],
  credentials: true,
}));

那么有谁知道在无模式对话框中托管网站的正确方法是什么,确保通过

google.script.run
与谷歌表格进行通信并与后端进行通信?

google-apps-script google-sheets iframe cors add-on
1个回答
0
投票

您可以使用

window.postMessage
进行交流。

示例片段:

modal.html
<script>
window.addEventListener('message',e =>{
  if(e.origin !== "https://www.myfrontend.com") return;
  const frontEndWindow = e.source;
  const data = JSON.parse(e.data);
  const {funcToRun, args} = data;
  //TODO: SECURITY: 
  // Check syntax of funcToRun, args
  // Check funcToRun against list of available functions 
  // Check args are as expected 

  //TODO Add failureHandler
  google.script.run.withSuccessHandler(res => {
    console.log(res);
    const iframeWindow = document.querySelector('#myFrame').contentWindow;
    iframeWindow.postMessage(({type:'success',response:res}),"https://www.myfrontend.com")
  })[funcToRun](...args)
  },false)
</script>
<iframe 
  id="myFrame"
  src="https://www.myfrontend.com/#/home"
  style="width: 100%; height: 800px; border: none"
</iframe>
模态.gs
var htmlOutput = HtmlService
    .createHtmlOutputFromFile('modal.html'
    .setWidth(600)
    .setHeight(800);
SpreadsheetApp.getUi().showModelessDialog(htmlOutput, 'My add-on');
frontEnd.com/index.html
window.parent.postMessage(
  (JSON.stringify({funcToRun: 'getData', args:[1,2]})), 
  'https://n-5fydpzckmar5yncflnjytuyfcusdcfogmgc2eti-1lu-script.googleusercontent.com')
© www.soinside.com 2019 - 2024. All rights reserved.