Golang中如何调用Google Apps Script

Golang中如何调用Google Apps Script 我有以下Google Apps脚本:

function doGet(request) {
  var events = CalendarApp.getEvents(
    new Date(Number(request.parameters.start) * 1000),
    new Date(Number(request.parameters.end) * 1000));
  var result = {
    available: events.length == 0
  };
  return ContentService.createTextOutput(JSON.stringify(result))
    .setMimeType(ContentService.MimeType.JSON);
}

当我在浏览器中打开以下URL时:

https://script.google.com/macros/s/AKfycbwNGgAO-p4TrbKLdGj_blwm5nI9nD5i_0EtlnS42-PuVsrxrM3Ovvwfdw/exec?end=1325439000&start=1325437200

我得到了正确的响应:

{"available":true}

我尝试通过Go语言进行调用,代码如下:

package main

import (
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"net/url"
)

func main() {
	site := "https://script.google.com/macros/s/AKfycbwNGgAO-p4TrbKLdGj_blwm5nI9nD5i_0EtlnS42-PuVsrxrM3Ovvwfdw/exec"
	base, err := url.Parse(site)
	if err != nil {
		return
	}

	// Path params
	//	base.Path += "this will get automatically encoded"

	// Query params
	params := url.Values{}

	params.Add("start", "1325437200")
	params.Add("end", "1325439000")
	base.RawQuery = params.Encode()

	fmt.Printf("Encoded URL is %q\n", base.String())

	// make a sample HTTP GET request
	res, err := http.Get(base.String())
	// check for response error
	if err != nil {
		log.Fatal(err)
	}

	// read all response body
	data, _ := ioutil.ReadAll(res.Body)

	// close response body
	res.Body.Close()

	// print `data` as a string
	fmt.Printf("%s\n", data)
}

但我没有得到相同的输出,而是得到了一个非常长的文本,看起来像是提取了包含多种语言的Google登录界面(无论输出是什么,都不是预期的结果)。我期望的输出与我在浏览器中得到的相同,即:

{"available":true}

更多关于Golang中如何调用Google Apps Script的实战教程也可以访问 https://www.itying.com/category-94-b0.html

2 回复

我发现错误出在Web应用的发布设置上。通过将Execute asWho has access的设置分别从MeAnyone with Google account更改为MeAnyone,问题得以解决。

此解决方案归功于stackoverflow上的Tanaike

更多关于Golang中如何调用Google Apps Script的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


在Go中调用Google Apps Script时,需要处理重定向和Cookies。Google Apps Script的Web应用在未授权访问时会重定向到登录页面。以下是修正后的代码:

package main

import (
	"fmt"
	"io"
	"log"
	"net/http"
	"net/http/cookiejar"
	"net/url"
	"time"
)

func main() {
	// 创建带Cookie的HTTP客户端
	jar, err := cookiejar.New(nil)
	if err != nil {
		log.Fatal(err)
	}

	client := &http.Client{
		Jar: jar,
		CheckRedirect: func(req *http.Request, via []*http.Request) error {
			// 允许重定向
			return nil
		},
		Timeout: 30 * time.Second,
	}

	// 构建URL
	baseURL := "https://script.google.com/macros/s/AKfycbwNGgAO-p4TrbKLdGj_blwm5nI9nD5i_0EtlnS42-PuVsrxrM3Ovvwfdw/exec"
	
	params := url.Values{}
	params.Add("start", "1325437200")
	params.Add("end", "1325439000")
	
	fullURL := baseURL + "?" + params.Encode()
	fmt.Printf("请求URL: %s\n", fullURL)

	// 创建请求
	req, err := http.NewRequest("GET", fullURL, nil)
	if err != nil {
		log.Fatal(err)
	}

	// 设置User-Agent头,模拟浏览器
	req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36")

	// 发送请求
	resp, err := client.Do(req)
	if err != nil {
		log.Fatal(err)
	}
	defer resp.Body.Close()

	// 读取响应
	body, err := io.ReadAll(resp.Body)
	if err != nil {
		log.Fatal(err)
	}

	fmt.Printf("状态码: %d\n", resp.StatusCode)
	fmt.Printf("响应体: %s\n", body)
}

如果Web应用需要授权,需要先获取OAuth2令牌。以下是使用OAuth2的示例:

package main

import (
	"context"
	"encoding/json"
	"fmt"
	"log"
	"net/http"
	"net/url"
	"os"

	"golang.org/x/oauth2"
	"golang.org/x/oauth2/google"
)

func main() {
	ctx := context.Background()
	
	// 从JSON文件加载凭据
	b, err := os.ReadFile("credentials.json")
	if err != nil {
		log.Fatal(err)
	}

	config, err := google.ConfigFromJSON(b, "https://www.googleapis.com/auth/calendar.readonly")
	if err != nil {
		log.Fatal(err)
	}

	// 获取令牌(需要先完成OAuth2流程)
	tok, err := getTokenFromFile("token.json")
	if err != nil {
		log.Fatal(err)
	}

	client := config.Client(ctx, tok)

	// 调用Google Apps Script
	baseURL := "https://script.google.com/macros/s/AKfycbwNGgAO-p4TrbKLdGj_blwm5nI9nD5i_0EtlnS42-PuVsrxrM3Ovvwfdw/exec"
	
	params := url.Values{}
	params.Add("start", "1325437200")
	params.Add("end", "1325439000")
	
	fullURL := baseURL + "?" + params.Encode()

	resp, err := client.Get(fullURL)
	if err != nil {
		log.Fatal(err)
	}
	defer resp.Body.Close()

	var result map[string]bool
	if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
		log.Fatal(err)
	}

	fmt.Printf("响应: %v\n", result)
}

func getTokenFromFile(file string) (*oauth2.Token, error) {
	f, err := os.Open(file)
	if err != nil {
		return nil, err
	}
	defer f.Close()
	tok := &oauth2.Token{}
	err = json.NewDecoder(f).Decode(tok)
	return tok, err
}

对于不需要认证的公开Web应用,确保在Google Apps Script部署设置中设置为"Anyone, even anonymous"。如果仍然遇到问题,可以尝试使用http.ClientTransport来禁用重定向:

client := &http.Client{
	CheckRedirect: func(req *http.Request, via []*http.Request) error {
		return http.ErrUseLastResponse // 停止重定向
	},
}

resp, err := client.Get(fullURL)
if err != nil {
	log.Fatal(err)
}
defer resp.Body.Close()

// 检查是否是重定向
if resp.StatusCode >= 300 && resp.StatusCode < 400 {
	location, err := resp.Location()
	if err == nil {
		fmt.Printf("重定向到: %s\n", location.String())
	}
}
回到顶部