我已经使用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回复,那将是非常感激的。
答案 0 :(得分:9)
你错过了重要部分:
预检的响应包含无效的HTTP状态代码405。
您的浏览器正在制作preflight request,它使用OPTIONS
HTTP方法。这是为了检查服务器是否允许POST
请求 - 在405
请求的响应中发送了OPTIONS
状态代码,而不是POST
请求。
CORS预检请求是CORS请求,用于检查是否了解CORS协议。 Source
<小时/> 此外,对于可能对服务器数据造成副作用的HTTP请求方法(特别是对于GET
以外的HTTP方法,或对某些POST
使用MIME types),规范要求浏览器“预检”请求,使用HTTPOPTIONS
请求方法从服务器请求支持的方法,然后,在服务器“批准”时,使用实际的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-8
或text/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