【问题标题】:How to send external HTTP request in google app engine如何在谷歌应用引擎中发送外部 HTTP 请求
【发布时间】:2017-01-22 22:27:40
【问题描述】:

我在 appengine 中发出 HTTP 请求时遇到问题,因为它不支持 http.Client。我正在创建一个 slackbot 并希望创建一个延迟响应。逻辑是,一旦我收到 slack 的 POST 请求,我将成功响应并旋转一个调用外部 API 的 goroutine,完成后,创建一个新的 slack 请求。

看起来很简单,但我遇到的问题是在使用 appengine 的 urlfetchNewContext 时,因为 NewContext 接受 *http.Request 作为参数,但因为我会立即响应第一个松弛请求,响应主体在我可以使用它向外部 API 发出响应之前关闭。有其他选择吗?

代码:

func Twit(w http.ResponseWriter, r *http.Request) {
    defaultResponse := &SlashResponse{ResponseType: "ephemeral", Text: "success"}

    // prepare to make a slack delayed response
    responseURL := r.FormValue("response_url")
    go sendDelayResponse(responseURL, r)

    w.Header().Set("Content-Type", "application/json")
    w.WriteHeader(200)
    json.NewEncoder(w).Encode(defaultResponse)
}

func sendDelayResponse(url string, r *http.Request) {
    response := &SlashResponse{ResponseType: "in_channel", Text: twit.TweetTCL(r)}
    b, _ := json.Marshal(response)

    // send request to slack using given response_url
    ctx := appengine.NewContext(r)
    client := urlfetch.Client(ctx)
    req, _ := http.NewRequest("POST", url, bytes.NewBuffer(b))
    req.Header.Add("Content-Type", "application/json")
    resp, err := client.Do(req)
    defer resp.Body.Close()

    if err != nil {
        log.Println(err)
    } else {
        log.Println("success")
    }
}

【问题讨论】:

    标签: google-app-engine go


    【解决方案1】:

    使用delay 包执行请求范围之外的功能。

    您也可以使用较低级别的taskqueue 包。延迟包位于任务队列包之上。

    用延迟函数声明包级变量:

    var laterFunc("dr", func(ctx context.Context, url string) {
      response := &SlashResponse{ResponseType: "in_channel", Text: twit.TweetTCL(r)}
      b, _ := json.Marshal(response)
    
      // send request to slack using given response_url
      client := urlfetch.Client(ctx)
      req, _ := http.NewRequest("POST", url, bytes.NewBuffer(b))
      req.Header.Add("Content-Type", "application/json")
      resp, err := client.Do(req)
      defer resp.Body.Close()
    
      if err != nil {
        log.Println(err)
      } else {
        log.Println("success")
      }
    })
    

    这样称呼它:

    laterfunc.Call(appengine.NewContext(r), responseURL)
    

    【讨论】:

    • 这在调用另一个 API 时会起作用吗?我的问题是 *http.Reader 提前关闭了。
    • 所有 appengine API 都可以从延迟函数中调用。问题中的 goroutine 仅使用请求来创建上下文。延迟函数包自动创建上下文。
    • @Finks 查看更新的答案。它基本上是将您的代码复制/粘贴到延迟函数示例中。
    猜你喜欢
    • 2023-03-30
    • 2014-05-25
    • 1970-01-01
    • 2015-05-17
    • 1970-01-01
    • 2017-04-10
    • 2012-05-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多