Google Apps Script UrlFetchApp returning Unauthori

2020-02-15 05:54发布

问题:

This is the code I'm using.

function doc_to_html(id)
{
  var url = "https://docs.google.com/feeds/download/documents/export/Export?id="+id+"&exportFormat=html";
var param = 
    {
      method      : "get",
      headers     : {"Authorization": "Bearer " + ScriptApp.getOAuthToken()},
      muteHttpExceptions:true,
    };
 var html = UrlFetchApp.fetch(url,param).getContentText();
  Logger.log(html);
}

It worked several times for testing, but now it's returning "Unauthorized Error 401." More accurately, it is returning:

<html>
<head>
<TITLE>Unauthorized</TITLE>
</HEAD>
<BODY BGCOLOR="#FFFFFF" TEXT="#000000">
<H1>Unauthorized</H1>
<H2>Error 401</H2>
</BODY>
</HTML>

I've looked into all the documentation I could find about UrlFetchApp and didn't see any quota or restrictions. I checked the script scope and https://www.googleapis.com/auth/script.external_request is authorized.

回答1:

The scopes provided are insufficient to access the document. To access it, you'd need documents scope as well. Edit the manifest file to have these scopes:

"oauthScopes": ["https://www.googleapis.com/auth/script.external_request","https://www.googleapis.com/auth/documents"],

Or add a dummy call to Document App in your script:

DocumentApp.getActiveDocument();

Based on comments from Tanaike, It seems that Documents scope wasn't enough, but Spreadsheet scope is also needed, even though we don't access spreadsheets. Alternatively, Drive's readonly scope is required.

Spreadsheet+Document scope:

Manifest:

"oauthScopes": ["https://www.googleapis.com/auth/script.external_request",
    "https://www.googleapis.com/auth/documents"
    "https://www.googleapis.com/auth/spreadsheets"],

Or add a dummy call to Document App+SpreadsheetApp in your script:

//DocumentApp.getActiveDocument();
//SpreadsheetApp.getActive();

Drive scope:

Manifest:

"oauthScopes": ["https://www.googleapis.com/auth/script.external_request",
    "https://www.googleapis.com/auth/drive.readonly"],

Or add a dummy call to DriveApp in your script:

//DriveApp.getFiles()