我有一个HTTP(Go)服务器端点,它接收到一个webhook POST,验证签名后,我得到了w.WriteHeader(http.StatusAccepted)
。
使用ngrok,如果我在下面提到的函数之前的各个点上简单地执行return
,服务器就会正确地响应,我可以在ngrok中看到202响应,并且我的服务器日志显示202已经发送。
当我点击这个函数时,在那之后的任何时间,我的Go服务器日志都显示处理完成,并给出202的响应,我在到达端点函数末尾的过程中放入了不同的日志,每一个都打印成功,我记录了每一个错误,但没有错误,函数应该做的每一件事,它都完成了。
但是在调用特定函数之后,ngrok永远不会收到响应。
我试着刷新响应编写器,但没有任何效果(我知道我不应该这么做--我只是在尝试,因为我正在戳所有的东西),就好像Go语言正在挂起或处理某个东西,但我不知道是什么。
我想让你看得懂,但要知道我会记录和处理每一个错误(但不会收到任何错误):
// Using chi router but that shouldn't matter
r.Post("/webhook", func(w http.ResponseWriter, r *http.Request) {
var payload webhookPayload
b, err := io.ReadAll(r.Body)
if err != nil {
logger.logEntry(err, "info", r)
w.WriteHeader(http.StatusBadRequest)
return
}
defer r.Body.Close()
// Validate webhook or send http.StatusUnauthorized and return
w.WriteHeader(http.StatusAccepted)
// Unmarshal body
// Get oauth refresh token from credential manager
// Get new tokens from oauth server
// Update token in credential manager
// None of the above produce errors and if I `return` now,
// I can see the completed 202 response in ngrok
// Here's where the problem is:
purchases, err := getPurchases(ids, token, service)
if err != nil {
logger.logEntry(err, "critical", r)
return
}
// I get no error from the above
// This prints in the console
fmt.Println("done processing")
// After this prints, my Docker log shows: 202 0B in 2.501328168s
// telling me it's done in 2.5s and should send the 202 with no body,
// but ngrok doesn't receive it any time after getPurchases
})
getPurchases
函数没有什么特别之处。service
是一个接口,它的函数向API发出一个简单的HTTP GET请求,它 * 是 * 在检查错误后关闭请求主体,它调用data, err := io.ReadAll(res.Body)
并在之后返回data, err
。
// This is the only place my getPurchases is doing anything outside of read data/update struct logic
func (s Service) GetPurchasesFromApi(ids string, token string) ([]byte, error) {
queryURL := fmt.Sprintf("%s/purchases/%s", s.baseURL, ids)
req, err := http.NewRequest("GET", queryURL, nil)
if err != nil {
return []byte{}, err
}
q := req.URL.Query()
q.Add("version", fmt.Sprint(s.version))
req.URL.RawQuery = q.Encode()
req.Header.Add("Accept", "application/json")
req.Header.Add("Authorization", fmt.Sprintf("Bearer %s", token))
req.Header.Add("Content-Type", "application/text")
res, err := s.httpClient.Do(req)
if err != nil {
return []byte{}, err
}
defer res.Body.Close()
if res.StatusCode < 200 && res.StatusCode > 299 {
return []byte{}, fmt.Errorf("got a status code of %d", res.StatusCode)
}
data, err := io.ReadAll(res.Body)
return data, err
}
出于完成目的,使用的http客户端是在服务器启动之前在main
中设置的客户端,并提供给Service
用于其API调用:
httpClient := &http.Client{
Transport: &http.Transport{
MaxIdleConns: 10,
IdleConnTimeout: 30 * time.Second,
},
}
ngrok继续坐在那里,不断地监听响应,我的总处理时间从来没有超过3秒,所以这不是ngrok超时的情况。
有没有什么想法,我可以看看下一步来弄清楚这一点?或者有什么东西跳出来你?
1条答案
按热度按时间xlpyo6sf1#
根据提供的代码,该问题似乎与处理webhook后未向客户端发送响应有关。在代码中,向客户端发送了HTTP.StatusAccepted应答,表示服务器已收到并接受webhook。但是,服务器在处理getPurchases()函数后似乎未进一步响应。
要解决此问题,您需要在处理webhook后向客户端发送响应。您可以通过添加对w.Write()的调用来发送空响应正文沿着HTTP.StatusAccepted状态代码来完成此操作。例如:
w.写入标头(接受的http.状态)w.写入([]字节{})
这将发送一个带有HTTP.StatusAccepted状态代码的空响应正文,向客户端指示webhook已成功处理。
此外,您可能需要检查getPurchases()函数中是否有任何错误可能导致未发送响应的问题。您还可以尝试记录getPurchases()的响应,以查看它是否返回任何意外结果。
购买,如果错误!= nil { logger.logEntry(错误,“关键”,r)//
enter code here.
return } //enter code here.
,则错误:=获取购买(ID、令牌、服务)//记录购买fmt.Println(购买)
w.写入标头(接受的http.状态)w.写入([]字节{})