fasthttp icon indicating copy to clipboard operation
fasthttp copied to clipboard

HEAD request hangs

Open NitinRamesh25 opened this issue 1 year ago • 1 comments

I noticed that a request with method HEAD successfully gets sent to the server, but the server response isn't returned by the fasthttp client. Hence the Do method gets stuck, without giving the response.

The same works fine with net/http package.

Note:

  • My server also provides a GET API for the same URL as the HEAD, and that works fine with fasthttp client.
  • I'm using v1.51.0 of fasthttp module.

The following are the sample code I used for testing.

fasthttp

func main() {
	req := &fasthttp.Request{}
	req.SetRequestURI("<Added the relative URL here>")

        req.Header.Add("Authorization", "...")
	req.Header.SetMethod("HEAD") // The "GET" endpoint works fine though.

	req.SetHost("<Added my host here>")
	req.URI().SetScheme("https")

	resp := &fasthttp.Response{}

	fmt.Println("Sending request")

	client := &fasthttp.Client{}
	err := client.Do(req, resp) // This method call gets stuck.
	if err != nil {
		fmt.Println("Failed do: " + err.Error())
		return
	}

	fmt.Println(resp)
}

net/http

func main() {
	req, err := http.NewRequest(http.MethodHead, "<Added the complete URL here>", nil)
	if err != nil {
		fmt.Println("Failed to create request " + err.Error())
	}

        req.Header.Add("Authorization", "...")

        fmt.Println("Sending request")

	client := &http.Client{}
	resp, err := client.Do(req) // Works fine and returns the proper response.
	if err != nil {
		fmt.Println("Failed do: " + err.Error())
		return
	}

	fmt.Println(resp)
}

NitinRamesh25 avatar Jan 11 '24 11:01 NitinRamesh25

This seems to work just fine, can you provide a complete sample where it doesn't work?

func main() {
	go func() {
		if err := http.ListenAndServe(":6060", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			w.WriteHeader(http.StatusOK)
		})); err != nil {
			panic(err)
		}
	}()

	// Give the server a second to start.
	time.Sleep(time.Second)

	req := &fasthttp.Request{}
	req.SetRequestURI("http://localhost:6060")

	req.Header.Add("Authorization", "...")
	req.Header.SetMethod("HEAD")

	req.SetHost("localhost:6060")
	req.URI().SetScheme("http")

	resp := &fasthttp.Response{}

	fmt.Println("Sending request")

	client := &fasthttp.Client{}
	err := client.Do(req, resp)
	if err != nil {
		fmt.Println("Failed do: " + err.Error())
		return
	}

	fmt.Println(resp)
}

erikdubbelboer avatar Jan 14 '24 02:01 erikdubbelboer

Looks like my API proxy was sending chunked response. But the terminating chunk wasn't sent properly, thus leading to the client to wait forever.

Even though the chunk isn't terminated properly, I could get this to work for now by setting the two fields in the Response struct fasthttp.Response{SkipBody: true, StreamBody: true}

NitinRamesh25 avatar Jan 16 '24 09:01 NitinRamesh25