Nginx устанавливает оставшееся количество для limit_req в заголовке X-RateLimit-Remaining
На самом деле я немного удивлен, что через пару часов работы в Google не смог найти ничего, но проблема такова:
Я хочу, чтобы nginx служил моим дросселем для моего API.
Мой конфигурационный файл содержит хорошо цитированный пример limit_req_zone
:
limit_req_zone $binary_remote_addr zone=limit:2m rate=10r/m;
вместе с моей директивой location
, содержащей ожидаемый limit_req zone=limit nodelay;
Мне бы хотелось, чтобы nginx прикреплял заголовки к ответному сообщению для атрибутов X-RateLimit-Remaining
и X-RateLimit-Reset
. В основном, nginx использует активный счетчик rate=10r/m
для заполнения X-RateLimit-Remaining
и таймфрейма того же значения rate=10r/m
, чтобы заполнить X-RateLimit-Reset
, сколько секунд осталось до обновления.
http {
limit_req_zone $binary_remote_addr zone=login:10m rate=2r/s;
limit_req_status 429;
limit_conn_status 429;
server {
listen 80;
server_name [removed];
location / {
limit_req zone=limit nodelay;
proxy_pass http://reverse-proxy-example;
add_header X-RateLimit-Remaining [nginx variable?];
add_header X-RateLimit-Reset [nginx variable?]
}
}
Мысли? Возможное? Хотелось бы избежать удара приложения, чтобы получить эти цифры.
Ответы
Ответ 1
Я бы сказал, что это невозможно с исходной версией nginx.
Вы можете найти документацию для директивы limit_req
через http://nginx.org/r/limit_req, которая перенаправляет на http://nginx.org/docs/http/ngx_http_limit_req_module.html#limit_req, что убедительно показывает, что в модуле нет никаких известных переменных внутри него.
Взгляд на http://ngx.su/src/http/modules/ngx_http_limit_req_module.c подтверждает гипотезу.
Другой вариант - взглянуть на http://nginx.org/docs/varindex.html, в котором перечислены все переменные - поиск limit
приведет вас только к $limit_rate
, который является не связанной переменной.
Постскриптум Учтите, что limit_req
выполняется методом утечки.
Не вдаваясь в подробности или придумывая что-либо (статья в Википедии огромна!), Я бы предположил, что представление этой информации конечному пользователю непротиворечивым и действенным образом может быть не совсем тривиальным.
Ответ 2
Packngo из Packet имеет функцию, которая может быть подходящей для того, что вам нужно делать.
Пример из пакета:
func (r *Response) populateRate() {
// parse the rate limit headers and populate Response.Rate
if limit := r.Header.Get(headerRateLimit); limit != "" {
r.Rate.RequestLimit, _ = strconv.Atoi(limit)
}
if remaining := r.Header.Get(headerRateRemaining); remaining != "" {
r.Rate.RequestsRemaining, _ = strconv.Atoi(remaining)
}
if reset := r.Header.Get(headerRateReset); reset != "" {
if v, _ := strconv.ParseInt(reset, 10, 64); v != 0 {
r.Rate.Reset = Timestamp{time.Unix(v, 0)}
}
}
}