如何正确关闭一个请求并在后台继续处理它

huangapple go评论90阅读模式
英文:

How to properly close a request and continue processing it on the background

问题

对于一个传入的HTTP请求,我需要用202 Accepted状态码进行响应,同时在后台继续处理有效载荷。举个例子,这是我目前正在做的:

package main

import (
	"fmt"
	"log"
	"net/http"
	"time"

	"github.com/nbari/violetear"
)

func sleep() {
	time.Sleep(3 * time.Second)
	fmt.Println("done...")
}

func index(w http.ResponseWriter, r *http.Request) {
	w.WriteHeader(http.StatusAccepted)
	go sleep()
}

func main() {
	router := violetear.New()
	router.HandleFunc("*", index)

	http.Handle("/", router)
	log.Fatal(http.ListenAndServe(":8080", router))
}

基本上,在处理程序中,我只是使用WriteHeader,然后在一个goroutine中调用sleep函数:

func index(w http.ResponseWriter, r *http.Request) {
	w.WriteHeader(http.StatusAccepted)
	go sleep()
}

如果我想要响应"200 OK",我注意到我可以简单地返回,例如:

func index(w http.ResponseWriter, r *http.Request) {
	go sleep()
	return
}

因此,我想知道是否我应该在想要关闭时总是返回:

func index(w http.ResponseWriter, r *http.Request) {
	w.WriteHeader(http.StatusAccepted)
	go sleep()
	return
}

或者只需写入头部,然后调用goroutine就足够了。

英文:

For an incoming HTTP request, I had to respond with a 202 Accepted status code, while continue processing the payload in the background. for example purposes this is what I am currently doing:

<!-- language: lang-golang -->

package main

import (
	&quot;fmt&quot;
	&quot;log&quot;
	&quot;net/http&quot;
	&quot;time&quot;

	&quot;github.com/nbari/violetear&quot;
)

func sleep() {
	time.Sleep(3 * time.Second)
	fmt.Println(&quot;done...&quot;)
}

func index(w http.ResponseWriter, r *http.Request) {
	w.WriteHeader(http.StatusAccepted)
	go sleep()
}

func main() {
	router := violetear.New()
	router.HandleFunc(&quot;*&quot;, index)

	http.Handle(&quot;/&quot;, router)
	log.Fatal(http.ListenAndServe(&quot;:8080&quot;, router))
}

Basically, on the handler I just use WriteHeader and later a call the the sleep function within a goroutine:

<!-- language: lang-golang -->

func index(w http.ResponseWriter, r *http.Request) {
	w.WriteHeader(http.StatusAccepted)
	go sleep()
}

In case I would like to respond with "200 OK", I notice that I can simple return, for example:

<!-- language: lang-golang -->

func index(w http.ResponseWriter, r *http.Request) {
  	go sleep()
    return
}

Therefore wondering if I should return always I want to close:

<!-- language: lang-golang -->

func index(w http.ResponseWriter, r *http.Request) {
	w.WriteHeader(http.StatusAccepted)
	go sleep()
    return
}

Or by just writing the header and next calling the goroutine is enough.

答案1

得分: 8

从处理程序返回就足够了,这也是应该做的。引用自http.Handler

> 返回信号表示请求已完成;在ServeHTTP调用完成后或同时使用ResponseWriter或从Request.Body读取是无效的。

请注意,最后的return语句是不必要的,你可以简单地省略它。当处理程序的最后一条语句执行时,执行将从处理程序返回,执行不会等待从函数启动的goroutine完成。(请注意,延迟语句将在之前执行,但你这里没有。)

此外,在返回时,如果未设置HTTP头,将自动设置为200 OK。因此,如果你想要202 Accepted,最少需要以下代码:

func index(w http.ResponseWriter, r *http.Request) {
	w.WriteHeader(http.StatusAccepted)
	go sleep()
}

只需确保在从处理程序返回后不要在并发的goroutine中使用http.ResponseWriterhttpRequest值,因为它们可能会被重用,所以你甚至不应该尝试读取它们。

英文:

Returning from the handler is sufficient and is what should be done. Quoting from http.Handler:

> Returning signals that the request is finished; it is not valid to use the ResponseWriter or read from the Request.Body after or concurrently with the completion of the ServeHTTP call.

Note that the final return statement is not necessary, you can simply omit it. Execution returns from the handler when its last statement is executed, execution does not wait for goroutines started from the function to complete. (Note that deferred statements would be executed prior, but you don't have any here.)

Also when returning, if HTTP headers are not set, 200 OK will be set automatically. So if you want 202 Accepted, the following is the minimal required:

func index(w http.ResponseWriter, r *http.Request) {
	w.WriteHeader(http.StatusAccepted)
	go sleep()
}

Just make sure you don't use the http.ResponseWriter and httpRequest values in the concurrent goroutine after you return from the handler as they may be reused, so you should not even attempt to read them.

huangapple
  • 本文由 发表于 2016年8月29日 17:27:19
  • 转载请务必保留本文链接:https://go.coder-hub.com/39202768.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定