尝试发送POST请求时,App脚本会发送405响应

时间:2017-07-04 15:57:18

标签: google-apps-script axios

我已经使用doPost方法公开发布了一个应用程序脚本(任何人,甚至是匿名的),如下所示,

 function doPost(e){
    var sheet = SpreadsheetApp.getActiveSheet();
    var length = e.contentLength;
    var body = e.postData.contents;
    var jsonString = e.postData.getDataAsString();
    var jsonData = JSON.parse(jsonString);
    sheet.appendRow([jsonData.title, length]);
    var MyResponse = "works";
    return ContentService.createTextOutput(MyResponse).setMimeType(ContentService.MimeType.JAVASCRIPT);
}

当我使用带有Advanced Rest Client的JSON对象发送Post请求时,它都能正常工作并返回200 OK响应。但是当我尝试从本地托管的反应应用程序发送带有反应axios的发布请求时,它会发送405响应。

XMLHttpRequest cannot load https://script.google.com/macros/s/AKfycbzyc2CG9xLM-igL3zuslSmNY2GewL5seTWpMpDIQr_5eCod7_U/exec. Response for preflight has invalid HTTP status code 405

我也在浏览器中启用了跨源资源共享。发送POST请求的功能如下,

axios({
          method:'post',
          url:'https://script.google.com/macros/s/AKfycbzyc2CG9xLM-igL3zuslSmNY2GewL5seTWpMpDIQr_5eCod7_U/exec',
          data: {
            "title": 'Fred',
            "lastName": 'Flintstone'
          }
        }).then(function (response) {
            console.log(response);
          })
          .catch(function (error) {
            console.log(error);
          });

如果有人能指出我为什么收到405回复,那将是非常感激的。

3 个答案:

答案 0 :(得分:9)

你错过了重要部分:

  

预检的响应包含无效的HTTP状态代码405。

您的浏览器正在制作preflight request,它使用OPTIONS HTTP方法。这是为了检查服务器是否允许POST请求 - 在405请求的响应中发送了OPTIONS状态代码,而不是POST请求。

  

CORS预检请求是CORS请求,用于检查是否了解CORS协议。 Source   

<小时/>   此外,对于可能对服务器数据造成副作用的HTTP请求方法(特别是对于GET以外的HTTP方法,或对某些POST使用MIME types),规范要求浏览器“预检”请求,使用HTTP OPTIONS请求方法从服务器请求支持的方法,然后,在服务器“批准”时,使用实际的HTTP请求方法发送实际请求。 Source      有些请求不会触发CORS preflight。这些在本文中被称为“简单请求”[...] Source   本文章节详细说明了请求必须满足的条件才被视为“简单请求”。      [...]“预检”请求首先通过OPTIONS方法向另一个域上的资源发送HTTP请求,以确定实际请求是否可以安全发送。跨站点请求是这样预检的,因为它们可能对用户数据有影响。 Source
  本文章节详细说明了导致请求被预检的条件。

在这种情况下,以下情况导致请求被预检:

  

[...] 如果 Content-Type标头的值不是以下值:

     
      
  • application/x-www-form-urlencoded
  •   
  • multipart/form-data
  •   
  • text/plain
  •   

axios将Content-Type标头的值设置为application/json;charset=utf-8。使用text/plain;charset=utf-8text/plain修复了问题:

axios({
    method: 'post',
    url: 'https://script.google.com/macros/s/AKfycbzyc2CG9xLM-igL3zuslSmNY2GewL5seTWpMpDIQr_5eCod7_U/exec',
    data: {
        title: 'Fred',
        lastName: 'Flintstone',
    },
    headers: {
        'Content-Type': 'text/plain;charset=utf-8',
    },
}).then(function (response) {
    console.log(response);
}).catch(function (error) {
    console.log(error);
});

答案 1 :(得分:1)

对于将来遇到此问题的人的另一种方法:

(在我的情况下,使用'Content-Type': 'text/plain;charset=utf-8'无效)

根据该文档https://github.com/axios/axios#using-applicationx-www-form-urlencoded-format

您可以使用text/plain;charset=utf-8来代替接受application/x-www-form-urlencoded

const axios = require('axios')
const qs = require('qs')

const url = 'https://script.google.com/macros/s/AKfycbzyc2CG9xLM-igL3zuslSmNY2GewL5seTWpMpDIQr_5eCod7_U/exec'

const data = {
        "title": 'Fred',
        "lastName": 'Flintstone'
}

const options = {
  method: 'POST',
  headers: { 'content-type': 'application/x-www-form-urlencoded' },
  data: qs.stringify(data),
  url
}

axios(options)
  .then(function(response) {
    console.log(response.data)
  })
  .catch(function(error) {
    console.log(error)
  })

答案 2 :(得分:0)

我认为您需要返回JSON数据。您可能需要将JSONP返回给来自浏览器的请求,但我认为您需要这样做:

{{1}}

如果这不起作用,可能需要返回JSONP才能在浏览器中运行。以下是一些可以帮助您解决问题的文档:https://developers.google.com/apps-script/guides/content#serving_jsonp_in_web_pages