Обнаружить сбой HTTP-соединения в го - PullRequest
2 голосов
/ 27 апреля 2019

Предположим, клиент загружает тяжелое изображение по http с медленным интернет-соединением, он открывает соединение с сервером, начинает записывать данные и внезапно теряет это соединение из-за проблем с сетью.Как я могу обнаружить это на сервере, если функция обработчика еще не была вызвана.Решение, которое я нашел, это проверить состояние соединения.Но проблема в том, что он не масштабируемый, потому что многие программы будут взаимодействовать с глобальной переменной.Есть ли более элегантные решения?

package main

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

// current state of connections
var connStates = make(map[string]http.ConnState)

func main() {
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        fmt.Println("got new request")
        fmt.Println(connStates)
    })

    srv := &http.Server{
        Addr: ":8080",
        ConnState: func(conn net.Conn, event http.ConnState) {
            if event != http.StateClosed {
                connStates[conn.RemoteAddr().String()] = event
            } else {
                if connStates[conn.RemoteAddr().String()] == http.StateActive {
                    fmt.Println("client cancelled request")
                }
                delete(connStates, conn.RemoteAddr().String())
            }
        },
    }
    log.Fatal(srv.ListenAndServe())
}

Ответы [ 2 ]

1 голос
/ 29 апреля 2019

Вы можете использовать context в вашем обработчике, например, это будет определять, когда клиент отключается и возвращается, и http.StatusPartialContent, кроме вызова someCleanup(), где вы можете иметь свою логику регистрации.

https://play.golang.org/p/5Yr_HBuyiZW

func helloWorld(w http.ResponseWriter, r *http.Request) {
    ctx := r.Context()

    ch := make(chan struct{})

    go func() {
            time.Sleep(5 * time.Second)
            fmt.Fprintln(w, "Hello World!")
            ch <- struct{}{}
    }()

    select {
    case <-ch:
    case <-ctx.Done():
            http.Error(w, ctx.Err().Error(), http.StatusPartialContent)
            someCleanUP()
    }

}

0 голосов
/ 29 апреля 2019

Если вам нужны только журналы, вы можете даже упростить код:

srv := &http.Server{
        Addr: ":8080",
        ConnState: func(conn net.Conn, event http.ConnState) {
            log.Printf("addr: %s, changed state to: %s", conn.RemoteAddr(), event.String())
        },
    }

Этот обратный вызов будет срабатывать при каждом изменении conn

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...