Сценарий приложения отправляет 405 ответ при попытке отправить запрос POST
Я публично опубликовал сценарий приложения (любой, даже анонимный) с помощью метода 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);
}
Когда я отправляю запрос Post с объектом JSON с помощью Advanced Rest Client, все это работает и возвращает ответ 200 OK. Но когда я пытаюсь отправить почтовый запрос с помощью axio реагирования из локально размещенного приложения реакции, он отправляет ответ 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, был бы благодарен.
4 ответа
Вы пропустили важную часть:
Ответ на предпечатную проверку имеет недопустимый код состояния HTTP 405.
Ваш браузер выполняет предварительный запрос, который использует OPTIONS
HTTP метод. Это делается для того, чтобы проверить, разрешит ли сервер POST
запрос - 405
код состояния отправляется в ответ на OPTIONS
запрос, а не ваш POST
запрос.
Предварительный запрос CORS - это запрос CORS, который проверяет, понятен ли протокол CORS. Источник
Кроме того, для методов HTTP-запроса, которые могут вызывать побочные эффекты на данных сервера (в частности, для методов HTTP, отличных отGET
или дляPOST
использование с определенными типами MIME), спецификация требует, чтобы браузеры "предварительно отправляли" запрос, запрашивая поддерживаемые методы с сервера с HTTPOPTIONS
метод запроса, а затем, после "одобрения" с сервера, отправка фактического запроса с фактическим методом HTTP-запроса. Источник
Некоторые запросы не запускают предварительную проверку CORS. Это так называемые "простые запросы" в этой статье [...] Source
В этом разделе статьи подробно описываются условия, которым должен соответствовать запрос, чтобы он считался "простым запросом".
[...] "предварительные" запросы сначала отправляют HTTP-запросOPTIONS
метод для ресурса в другом домене, чтобы определить, является ли фактический запрос безопасным для отправки. Межсайтовые запросы предварительно просматриваются следующим образом, так как они могут иметь значение для пользовательских данных. Источник
В этом разделе статьи подробно описываются условия, которые вызывают предварительную проверку запроса.
В этом случае следующий запрос вызывает предварительную проверку запроса:
[...] если
Content-Type
заголовок имеет значение, отличное от следующего:
application/x-www-form-urlencoded
multipart/form-data
text/plain
Значение для 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);
});
Другой способ для тех, кто столкнется с этой проблемой в будущем:
(в моем случае, используя '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)
})
Я думаю, что вам нужно вернуть данные JSON. Возможно, вам нужно вернуть JSONP к запросу из браузера, но я думаю, что вам нужно сделать следующее:
return ContentService.createTextOutput(JSON.stringify({message: MyResponse})).setMimeType(ContentService.MimeType.JSON);
Если это не сработает, возможно, вам нужно вернуть JSONP для запуска в браузере. Вот некоторая документация, чтобы помочь вам: https://developers.google.com/apps-script/guides/content
ПРОВЕРЬТЕ НАЗВАНИЯ МЕТОДА ЗАПРОСА API И КОНЕЧНОЙ ТОЧКИ API!
Я отправлял запрос POST на конечную точку GET. Это возвращает ошибку HTTP 405.