Возвратите ошибку, когда обработчик достигнет максимального предела клиента - PullRequest
5 голосов
/ 02 мая 2019

Я написал небольшую функцию-обертку, которая использует концепцию подсчета семафоров, чтобы ограничить количество соединений с определенным обработчиком (так как этот обработчик потребляет ресурсы). Ниже приведен код, который достигает того же.

func LimitNumClients(f http.HandlerFunc, maxClients int) http.HandlerFunc {
    // Counting semaphore using a buffered channel
    sema := make(chan struct{}, maxClients)

    return func(w http.ResponseWriter, req *http.Request) {
        sema <- struct{}{}
        defer func() { <-sema }()
        f(w, req)
    }
}

А затем обернуть его в обработчик, как показано ниже

Route{
        "Test",
        "GET",
        /test,
        LimitNumClients(testhandler, 5),
    },

Теперь я хочу ответить с ошибкой 501, когда достигнут предел клиента для любого нового соединения. Как добиться того же.

1 Ответ

6 голосов
/ 02 мая 2019

Вы можете использовать неблокирующую операцию отправки. Если это успешно, продолжайте как обычно, если отправка на sema заблокирует, затем отправьте обратно ошибку и вернитесь из ограничителя без вызова обработчика:

return func(w http.ResponseWriter, req *http.Request) {
    select {
    case sema <- struct{}{}:
    default:
        http.Error(w, "rate limit reached", 501)
        return
    }

    defer func() { <-sema }()
    f(w, req)
}

Также обратите внимание, что для сообщения об ошибке «достигнут предел скорости» возвращаемый код состояния должен быть HTTP 429 Too Many Requests, см. RFC 6585 .

Так что вместо этого верните:

http.Error(w, "rate limit reached", http.StatusTooManyRequests)
...