Go http.ResponseWriter.Write не возвращает ошибку, когда клиент закрыл соединение - PullRequest
0 голосов
/ 27 мая 2020

Я написал простой http HandleFun c, обработка которого занимает 2 секунды, затем я отправляю на сервер запрос с таймаутом в 1 секунду. Я ожидаю, что вызов ResponseWriter.Write вернет ошибку, но это не так. Пожалуйста, объясните мне это.

Код сервера:


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

func main() {
    log.SetFlags(log.Ltime | log.Lshortfile)

    handler := http.NewServeMux()
    handler.HandleFunc("/long-task",
        func(w http.ResponseWriter, r *http.Request) {
            go func() {
                <-r.Context().Done()
                log.Println("client closed or server responded")
            }()
            log.Println("handling long-task")
            time.Sleep(2 * time.Second)
            n, err := w.Write([]byte("my slow response"))
            if err != nil {
                log.Println("error when ResponseWriter Write: ", err)
            }
            log.Printf("responded to long-task. n: %v\n", n)
        })
    server := &http.Server{Addr: ":8008", Handler: handler}

    log.Println("listening on port ", server.Addr)
    err := server.ListenAndServe()
    if err != nil {
        log.Fatal(err)
    }
}

Код клиента:

package main

import (
    "io/ioutil"
    "log"
    "net/http"
    "time"
)

func main() {
    client := http.Client{Timeout: 1 * time.Second}
    r, _ := http.NewRequest("GET", "http://127.0.0.1:8008/long-task", nil)
    w, err := client.Do(r)
    if err != nil {
        log.Fatal(err)
    }
    defer w.Body.Close()
    body, err := ioutil.ReadAll(w.Body)
    if err != nil {
        log.Fatal(err)
    }
    log.Printf("response: %s\n", body)
}

Вывод сервера:

10:50:58 http_server.go:28: listening on port  :8008
10:51:01 http_server.go:19: handling long-task
10:51:02 http_server.go:17: client closed or server responded
10:51:03 http_server.go:25: responded to long-task. n: 16

Вывод клиента :

2020/05/27 10:51:02 Get "http://127.0.0.1:8008/long-task": context deadline exceeded (Client.Timeout exceeded while awaiting headers)

1 Ответ

1 голос
/ 27 мая 2020

Записано слишком мало данных, ResponseWriter не отправил буферизованные данные клиенту.

    handler.HandleFunc("/long-task", func(w http.ResponseWriter, r *http.Request) {
        go func() {
            <-r.Context().Done()
            log.Println("client closed or server responded")
        }()
        log.Println("handling long-task")
        time.Sleep(2 * time.Second)
        for i := 0; i < 520; i++ {
            _, err := w.Write([]byte("my slow response"))
            if err != nil {
                log.Println("error when ResponseWriter Write: ", err, i)
            }
        }
        // log.Printf("responded to long-task. n: %v\n", n)
    })

srv out:

13:53:19 01.go:30: listening on port  :8008
13:53:22 01.go:18: handling long-task
13:53:23 01.go:16: client closed or server responded
13:53:24 01.go:23: error when ResponseWriter Write:  write tcp 127.0.0.1:8008->127.0.0.1:57098: write: broken pipe 512
13:53:24 01.go:23: error when ResponseWriter Write:  write tcp 127.0.0.1:8008->127.0.0.1:57098: write: broken pipe 513
13:53:24 01.go:23: error when ResponseWriter Write:  write tcp 127.0.0.1:8008->127.0.0.1:57098: write: broken pipe 514
13:53:24 01.go:23: error when ResponseWriter Write:  write tcp 127.0.0.1:8008->127.0.0.1:57098: write: broken pipe 515
13:53:24 01.go:23: error when ResponseWriter Write:  write tcp 127.0.0.1:8008->127.0.0.1:57098: write: broken pipe 516
13:53:24 01.go:23: error when ResponseWriter Write:  write tcp 127.0.0.1:8008->127.0.0.1:57098: write: broken pipe 517
13:53:24 01.go:23: error when ResponseWriter Write:  write tcp 127.0.0.1:8008->127.0.0.1:57098: write: broken pipe 518
13:53:24 01.go:23: error when ResponseWriter Write:  write tcp 127.0.0.1:8008->127.0.0.1:57098: write: broken pipe 519
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...