Как назначить кнопку UrlFetchApp с базовой авторизацией?

Я создал функцию в Google Apps Script, которая хорошо работает, когда я запускаю ее в Google Apps Script. Выходные данные возвращаются в Google Таблицы.

function testFunction11() {
  var rng = SpreadsheetApp.getActiveRange();
  var encodedAuthInformation = Utilities.base64Encode("username:key");
  var headers = {"Authorization" : "Basic " + encodedAuthInformation};
  var params = {
    'method': 'GET',
    'muteHttpExceptions': true,
    'headers': headers
  };
  var res = UrlFetchApp.fetch("https://api.apiservice.com/api/v1/xxx?fields=somefields", params);
  Logger.log(res.getContentText());
  rng.setValue(res);
}

Вывод в ячейке:

[
  {
    "id": xxx,
    "createdDate": "2019-02-01T04:54:00Z",
    "reference": "XXX"
  },
etc

Затем я назначаю скрипт кнопке testFunction11. И когда я нажимаю кнопку, она возвращается

{
  "message": "An error has occurred."
}

Похоже, ответ от сервера API.

Моя единственная гипотеза заключается в том, что кнопка листа Google добавляет некоторые заголовки, User-Agent или тип содержимого для запроса, что не разрешено на сервере API. И после некоторого поиска, я думаю, я не могу переназначить User-Agent в запросе. Это что-то правильно или я делаю неправильно?

ИЗМЕНИТЬ 1:

Заголовки для каждого случая console.log(UrlFetchApp.getRequest(url, params)): При нажатии кнопки в электронной таблице:

{headers={Authorization=Basic XXXXXXXXQVU6MWVhODlmZmFkN2U3NGNjOGJkOTc1YTE1ZjVhNTE3MzE=, X-Forwarded-For=178.xx.my.ip}, method=get, payload=, followRedirects=true, validateHttpsCertificates=true, useIntranet=false, contentType=null, url=https://api.apisite.com/api/v1/SalesOrders?fields=Id,Createddate,Reference&where=Createddate%3E2019-02-01T00:00:00Z}

А для скрипта:

{headers={Authorization=Basic XXXXXXXXQVU6MWVhODlmZmFkN2U3NGNjOGJkOTc1YTE1ZjVhNTE3MzE=}, method=get, payload=, followRedirects=true, validateHttpsCertificates=true, useIntranet=false, contentType=null, url=https://api.apisite.com/api/v1/SalesOrders?fields=Id,Createddate,Reference&where=Createddate%3E2019-02-01T00:00:00Z}

Так что кнопка добавляет только X-Forwarded-For.

Когда я попытался вручную добавить X-Forwarded-For: 'unknown', возникла такая ошибка

There are attribute with impossible value: Header:X-Forwarded-For

Текст ошибки на русском языке, извините за неточный перевод. Это весело, потому что, когда я добавил Test: unknown таким же образом, ошибок нет, но явно не работает. Похоже, Google не позволяет изменить это значение.

Попробует разные заголовки в почтальоне и, возможно, подтвердит, что этот заголовок является причиной ошибки. Спасибо @TheMaster

ИЗМЕНИТЬ 2:

Я пробовал разные заголовки через Postman. Итак, когда я добавляю в заголовки X-Forwarded-For ключ с любым значением, он возвращает "message": "An error has occurred.". Когда я не добавляю этот ключ, он работает хорошо.

Итак, вопрос в том, как отключить добавление этого заголовка через Google Apps Script. Вроде нет.


person imnotyourguru    schedule 10.02.2019    source источник
comment
Покажите свои заголовки в каждом случае: console.log(UrlFetchApp.getRequest(url, params))   -  person TheMaster    schedule 10.02.2019
comment
@TheMaster и для скрипта: {headers={Authorization=Basic XXXXXXXXQVU6MWVhODlmZmFkN2U3NGNjOGJkOTc1YTE1ZjVhNTE3MzE=}, method=get, payload=, followRedirects=true, validateHttpsCertificates=true, useIntranet=false, contentType=null, url=https://api.apisite.com/api/v1/SalesOrders?fields=Id,Createddate,Reference&where=Createddate%3E2019-02-01T00:00:00Z}   -  person imnotyourguru    schedule 10.02.2019
comment
Значит, кнопка добавляет только X-Forwarded-For заголовок вашего IP-адреса? И это приводит к сбою вашего API?   -  person TheMaster    schedule 10.02.2019
comment
О, похоже это. Но когда я получаю данные из api через браузер (тот же ip), он работает хорошо.   -  person imnotyourguru    schedule 10.02.2019
comment
Попробуйте вручную добавить заголовок в свой сценарий и запустить его из редактора сценариев. X-Forwarded-For: 'unknown'   -  person TheMaster    schedule 10.02.2019
comment
@TheMaster, когда я добавил это в заголовки, наверху страницы появилась ошибка с красным фоном: There are attribute with impossible value: Header:X-Forwarded-For На самом деле этот текст ошибки написан на русском языке, извините за, возможно, неточный перевод   -  person imnotyourguru    schedule 10.02.2019
comment
Это весело, потому что, когда я добавил Test: unknown таким же образом, ошибок нет, но явно не работает. Похоже, Google не позволяет изменить это значение.   -  person imnotyourguru    schedule 10.02.2019
comment
Измените свой вопрос со всей этой информацией в комментариях для более широкой аудитории. Если этот заголовок является проблемой, то, вероятно, вы ничего не можете сделать, чтобы исправить это, AFAIK. Но также возможно, что ошибка где-то еще. Попробуйте установить эти заголовки в curl / postman / other api testers и убедитесь, что этот заголовок является причиной ошибки.   -  person TheMaster    schedule 10.02.2019
comment
@TheMaster спасибо за помощь! Скоро отредактирую вопрос и попробую разные заголовки в почтальоне.   -  person imnotyourguru    schedule 10.02.2019
comment
@imnotyourguru Я предложил обходной путь. Не могли бы вы это подтвердить? Если это не тот результат, который вам нужен, прошу прощения.   -  person Tanaike    schedule 11.02.2019


Ответы (2)


  • В вашей ситуации, когда UrlFetchApp.fetch() запускается с помощью кнопки в электронной таблице, X-Forwarded-For автоматически добавляется в заголовок.
  • При добавлении X-Forwarded-For в шапку возникает ошибка An error has occurred..
  • С другой стороны, X-Forwarded-For не используется в заголовке, ошибки не возникает.

Если я правильно понимаю, как насчет этого обходного пути? Думаю, есть несколько обходных путей. Поэтому, пожалуйста, думайте об этом как об одном из них. В этом обходном пути веб-приложения используются как функция-оболочка.

Пример сценария:

Сначала скопируйте и вставьте следующий скрипт. И установите testFunction11() на кнопку. При запуске testFunction11() testFunction11() запросы к веб-приложениям (doGet()) и веб-приложениям к https://api.apiservice.com/api/v1/xxx?fields=somefields. Таким образом, X-Forwarded-For не используется в заголовке запроса. Затем возвращается результат веб-приложений и помещается значение в электронную таблицу. Перед запуском скрипта разверните веб-приложения.

function testFunction11() {
  var rng = SpreadsheetApp.getActiveRange();
  var url = ScriptApp.getService().getUrl();
  var params = {method: "get", headers: {Authorization: "Bearer " + ScriptApp.getOAuthToken()}};
  var res = UrlFetchApp.fetch(url, params);
  Logger.log(res.getContentText());
  rng.setValue(res);
}

function doGet() {
  var url = "https://api.apiservice.com/api/v1/xxx?fields=somefields";
  var encodedAuthInformation = Utilities.base64Encode("username:key");
  var headers = {"Authorization" : "Basic " + encodedAuthInformation};
  var params = {
    'method': 'GET',
    'muteHttpExceptions': true,
    'headers': headers
  };
  var res = UrlFetchApp.fetch(url, params);
  return ContentService.createTextOutput(res.getContentText());
}

Развернуть веб-приложения:

Перед запуском этого сценария разверните веб-приложения.

  • В редакторе скриптов
  • Publish -> Deploy as Web App
    1. Create new Project version
    2. В разделе «Выполнить приложение a» выберите «Я».
    3. At "Who has access to the app",
      • if the function is used by only you, select "Only myself".
      • если функцией пользуются несколько пользователей, выберите «Любой».
    4. Нажмите "Развернуть".
    5. Скопируйте "Текущий URL-адрес веб-приложения"
    6. Нажмите "ОК".

Примечание:

  • После изменения скрипта повторно разверните веб-приложения как новую версию. Таким образом, последний скрипт отражается в веб-приложениях. Это важный момент.
  • Это простой пример сценария. Поэтому, пожалуйста, измените свою ситуацию.

Использованная литература:

person Tanaike    schedule 10.02.2019
comment
благодарю вас! в var params = {method: "get", headers: {Authorization: "Bearer " + ScriptApp.getOAuthToken()}}; На предъявителя должен быть адрес электронной почты моей учетной записи Google? Если да, то есть ошибка Your input contains more than the maximum of 50000 characters in a single cell.. Если я продолжу Bearer, будет ошибка: 401. <HTML> <HEAD> <TITLE>Unauthorized</TITLE> </HEAD> <BODY BGCOLOR="#FFFFFF" TEXT="#000000"> <H1>Unauthorized</H1> <H2>Error 401</H2> </BODY> </HTML> - person imnotyourguru; 11.02.2019
comment
На самом деле это работает после того, как я изменил «У кого есть доступ к приложению» на «Любой, даже анонимный». Большое спасибо! Один вопрос, потому что я немного запутался в коде. Могу ли я изменить имя функции doGet? Потому что я хотел бы иметь несколько кнопок для разных запросов. - person imnotyourguru; 11.02.2019
comment
Я думаю, вам также следует предоставить свой github. Воспользуйтесь преимуществами веб-приложений в качестве ссылки во всех ваших ответах веб-приложений :) Хороший обходной путь. - person TheMaster; 11.02.2019
comment
@imnotyourguru Спасибо за ответ. Я рад, что ваша проблема решена. doGet используется для метода запроса GET. Таким образом, имя функции не может быть изменено. Но если вы хотите запускать несколько функций по запросу GET, используйте параметры запроса. Используя параметры запроса, можно вызывать несколько функций из doGet. - person Tanaike; 12.02.2019
comment
@TheMaster Спасибо за ваш комментарий. Я добавил это. - person Tanaike; 12.02.2019

Для будущих поисков по этой теме: у меня была проблема с тем же сообщением об ошибке, когда я использовал UrlFetchApp#getRequest в качестве утилиты для создания объекта запроса, а затем отправлял его с помощью UrlFetchApp#fetchAll.

Решение заключалось в том, чтобы избежать использования getRequest и вместо этого создать запрос самостоятельно без использования какого-либо заголовка X-Forwarded-For, что позволило успешно выполнить запрос.

Я не могу найти никакой документации, подтверждающей это, но я предполагаю, что возникла следующая проблема: когда Google вводит заголовок X-Forwarded-For перед отправкой запроса, вводимый IP-адрес зависит от контекста, в котором выполняется сценарий. Я думаю, что Google проверяет что если этот заголовок установлен вручную, то IP-адрес должен совпадать либо с IP-адресом их GAS-прокси, либо с IP-адресом браузера пользователя; какой из них использовать, кажется, меняется в зависимости от контекста, в котором выполняется скрипт.

person David Bodow    schedule 17.06.2020