代码之家  ›  专栏  ›  技术社区  ›  Cooper

为什么我不能让UrlFetchApp.fetch使用doGet()?

  •  0
  • Cooper  · 技术社区  · 5 年前

    如果我使用两个相同的表单,但其中一个表单有GET方法,另一个在运行它们时有POST方法,则一个使用doGet,另一个使用doPost()。但是,当我通过从提示符提供输入来对UrlFetch()命令执行相同的操作时,不会发生这种情况。

    html:

    上表是GET,下表是POST。

    <!DOCTYPE html>
    <html>
      <head>
        <base target="_top">
      </head>
      <body>
      <h3>GET</h3>
        <form action="https://script.google.com/a/cooper/macros/s/AKfycbzlYgw2cw8q7u9qTxM/exec" enctype="application/x-www-form-urlencoded" method="GET">
          <input type="text" name="one" value="" />
          <br /><input type="text" name="two" value="" />
          <br /><textarea rows="2" cols="25" name="three" placeholder="Enter Text Here"></textarea>
          <br /><input type="submit" value="Submit" />
        </form>
     <h3>POST</h3>   
        <form action="https://script.google.com/a/cooper/macros/s/AKfycbzlYgw2cw8q7u9qTxM/exec" enctype="application/x-www-form-urlencoded" method="POST">
          <input type="text" name="one" value="" />
          <br /><input type="text" name="two" value="" />
          <br /><textarea rows="2" cols="25" name="three" placeholder="Enter Text Here"></textarea>
          <br /><input type="submit" value="Submit" />
        </form>
      </body>
    </html>
    

    function doGet(e){
      Logger.log('doGet: %s',JSON.stringify(e));
      if(e.parameter) {
        var data=e.parameter;
        handleFunction(data,'get');//This hardwires the term get to the ouput
      }
      return HtmlService.createHtmlOutputFromFile('testing');
    }
    
    function doPost(e){
      console.log('doPost Entry',JSON.stringify(e));
      if(e.postData.length!=-1) {
        var data=e.parameter;
        handleFunction(data,'post');//This hardwires the term post to the ouput
      }
      return ContentService.createTextOutput('doPost Return:' + JSON.stringify(e.postData.contents));
    }
    
    function handleFunction(data,source){
      console.log('handleFunction Entry: %s',JSON.stringify(data));
      var one=data.one;
      var two=data.two;
      var three=data.three;
      var ss=SpreadsheetApp.getActive();
      var sheet=ss.getActiveSheet();
      sheet.appendRow([source,one,two,three]);
    }
    
    function postit() {
      // DriveApp.getFiles() //I copied this from a Tanaike example.  I don't know if I need it still
      var ask=SpreadsheetApp.getUi().prompt("Enter first/second/third/method", SpreadsheetApp.getUi().ButtonSet.OK) 
      if(ask.getSelectedButton()==SpreadsheetApp.getUi().Button.OK) {
        var dA=ask.getResponseText().split('/');//Just an easy way to get 4 pieces of data at one time
        if(dA.length==4) {
          var url=ScriptApp.getService().getUrl();
          var data={"one":dA[0],"two":dA[1],"three":dA[2]};
          //the method is provide from the last term of the above prompt
          var options={"method":dA[3],"payload":data,"headers":{"Authorization":"Bearer " + ScriptApp.getOAuthToken()},"muteHttpExceptions": true};
          var resp=UrlFetchApp.fetch(url, options);
          Logger.log('UrlFetch Response: %s',resp);
        }
      }
    }
    

    动画:

    enter image description here

    我最后用的是

    function postit() {
      // DriveApp.getFiles() 
      var ask=SpreadsheetApp.getUi().prompt("Enter first/second/third/method", SpreadsheetApp.getUi().ButtonSet.OK) 
      if(ask.getSelectedButton()==SpreadsheetApp.getUi().Button.OK) {
        var dA=ask.getResponseText().split('/');
        if(dA.length==4) {
          var url=ScriptApp.getService().getUrl();
          var options = {};//correct spelling for potions to options
          var data={"one":dA[0],"two":dA[1],"three":dA[2]};//moved this data declaration since it is used in both the if and the else.
          if (dA[3] == "POST") {
            options={"method":dA[3],"payload":data,"headers":{"Authorization":"Bearer " + ScriptApp.getOAuthToken()},"muteHttpExceptions": true};
          } else if (dA[3] == "GET") {
            options={"method":dA[3],"payload":data,"headers":{"x-http-method-override": "POST", "Authorization":"Bearer " + ScriptApp.getOAuthToken()},"muteHttpExceptions": true};
          }
          var resp=UrlFetchApp.fetch(url, options);
          Logger.log('UrlFetch Response: %s',resp);
        }
      }
    }
    
    1 回复  |  直到 5 年前
        1
  •  2
  •   Tanaike    5 年前

    这个答案怎么样?请把这当作几个可能的答案之一。

    问题和解决方法:

    我认为你的问题是由于 payload 对于 POST GET 方法。在UrlFetchApp中,当数据用作 有效载荷 ,即使在 method 得到 . 为了将数据作为GET方法发送,请将它们添加到查询参数中。

    有效载荷 使用GET方法,数据可以作为 得到 以前。但关于这件事,我只有一点模糊的记忆。对此我深表歉意。)

    模式1:

    在此模式中,查询参数用于GET方法。

    function postit() {
      // DriveApp.getFiles() //I copied this from a Tanaike example.  I don't know if I need it still
      var ask=SpreadsheetApp.getUi().prompt("Enter first/second/third/method", SpreadsheetApp.getUi().ButtonSet.OK) 
      if(ask.getSelectedButton()==SpreadsheetApp.getUi().Button.OK) {
        var dA=ask.getResponseText().split('/');//Just an easy way to get 4 pieces of data at one time
        if(dA.length==4) {
          var url=ScriptApp.getService().getUrl();
    
          // --- I modified below script.
          var potions = {};
          if (dA[3] == "POST") {
            var data={"one":dA[0],"two":dA[1],"three":dA[2]};
            //the method is provide from the last term of the above prompt
            options={"method":dA[3],"payload":data,"headers":{"Authorization":"Bearer " + ScriptApp.getOAuthToken()},"muteHttpExceptions": true};
          } else if (dA[3] == "GET") {
            options={"method":dA[3],"headers":{"Authorization":"Bearer " + ScriptApp.getOAuthToken()},"muteHttpExceptions": true};
            url += `?one=${dA[0]}&two=${dA[1]}&three=${dA[2]}`;
          }
          // ---
    
          var resp=UrlFetchApp.fetch(url, options);
          Logger.log('UrlFetch Response: %s',resp);
        }
      }
    }
    

    模式2:

    在这种模式下,作为另一种解决办法, x-http-method-override x-http-method-override 在这种情况下,POST方法可以转换为GET方法。所以 "payload":data 也可以使用。

    修改脚本:

    function postit() {
      // DriveApp.getFiles() //I copied this from a Tanaike example.  I don't know if I need it still
      var ask=SpreadsheetApp.getUi().prompt("Enter first/second/third/method", SpreadsheetApp.getUi().ButtonSet.OK) 
      if(ask.getSelectedButton()==SpreadsheetApp.getUi().Button.OK) {
        var dA=ask.getResponseText().split('/');//Just an easy way to get 4 pieces of data at one time
        if(dA.length==4) {
          var url=ScriptApp.getService().getUrl();
    
          // --- I modified below script.
          var potions = {};
          if (dA[3] == "POST") {
            var data={"one":dA[0],"two":dA[1],"three":dA[2]};
            //the method is provide from the last term of the above prompt
            options={"method":dA[3],"payload":data,"headers":{"Authorization":"Bearer " + ScriptApp.getOAuthToken()},"muteHttpExceptions": true};
          } else if (dA[3] == "GET") {
            options={"method":dA[3],"payload":data,"headers":{"x-http-method-override": "POST", "Authorization":"Bearer " + ScriptApp.getOAuthToken()},"muteHttpExceptions": true};
          }
          // ---
    
          var resp=UrlFetchApp.fetch(url, options);
          Logger.log('UrlFetch Response: %s',resp);
        }
      }
    }
    

    注:

    • 请启用V8。
    • // DriveApp.getFiles() https://www.googleapis.com/auth/drive.readonly 使用脚本编辑器。这用于使用访问令牌访问Web应用程序。

    参考文献:

    如果我误解了你的观点,这不是你想要的方向,我道歉。