- адреса приложения переехали в своё пространство `/app/`, опрос готовности убран целиком: рубеж и причину остановки владелец узнаёт карточкой записи, текст — отдельным адресом названного вида - заведена единая точка отображения доменной ошибки и слой, приводящий к той же форме отказы библиотеки: тело несёт машиночитаемый код рядом с сообщением - у записи появились имя файла отправителя, длительность и размер своими колонками, а у ленты владельца — свой индекс: без него страница сканировала весь архив сервиса
59 lines
2.5 KiB
Go
59 lines
2.5 KiB
Go
package http
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"github.com/pocketbase/pocketbase/core"
|
|
)
|
|
|
|
// Своё правило ограничителя частоты под корнем приложения.
|
|
//
|
|
// Заводится потому, что правило хранилища настроено на **его** корень и наших
|
|
// адресов больше не покрывает: приложение уехало в своё пространство, и вместе с
|
|
// переездом ограничитель перестал бы существовать для него вовсе. Потеря тихая —
|
|
// заметить её нечем, пока кто-нибудь не начнёт опрашивать карточку в цикле.
|
|
//
|
|
// Числа скромные намеренно: сервисом пользуются единицы человек, а экран
|
|
// опрашивает карточку, пока запись идёт по конвейеру. Из них же выводится
|
|
// частота опроса, которую сервис объявляет приложению, — два числа об одном и
|
|
// том же разъехались бы при первой правке.
|
|
const (
|
|
appRateMaxRequests = 120
|
|
appRateWindowSec = 60
|
|
)
|
|
|
|
// ApplyAppRateLimit ставит правило ограничителя на корень приложения.
|
|
//
|
|
// Правило приводится к настройке при каждом подъёме, как и настройки провайдера:
|
|
// применённый шаг схемы не переписывается, а настройки хранилища живут в базе, и
|
|
// правило, положенное однажды, не пережило бы ни правки числа, ни чистого
|
|
// каталога данных.
|
|
func ApplyAppRateLimit(app core.App) error {
|
|
settings := app.Settings()
|
|
|
|
rule := core.RateLimitRule{
|
|
Label: AppRoot + "/",
|
|
MaxRequests: appRateMaxRequests,
|
|
Duration: appRateWindowSec,
|
|
}
|
|
|
|
replaced := false
|
|
for i, existing := range settings.RateLimits.Rules {
|
|
if existing.Label == rule.Label {
|
|
settings.RateLimits.Rules[i] = rule
|
|
replaced = true
|
|
break
|
|
}
|
|
}
|
|
if !replaced {
|
|
settings.RateLimits.Rules = append(settings.RateLimits.Rules, rule)
|
|
}
|
|
|
|
settings.RateLimits.Enabled = true
|
|
|
|
if err := app.Save(settings); err != nil {
|
|
return fmt.Errorf("failed to apply app rate limit: %w", err)
|
|
}
|
|
return nil
|
|
}
|