хранилище переехало с PocketBase на SQLite со своим каталогом файлов
- база своя: два пула, захват одним UPDATE ... RETURNING, шаги схемы на goose под файловым замком, одна миграция начальной схемы вместо семи прежних - транспорт переписан на net/http: свои слои, свой ограничитель частоты, отдача файла с проверкой владельца; панель /_/ и пространство /api/ исчезли - по находкам ревью: журнал не пишет путь под корнем приложения, ключ бюджета читается справа налево, узнавание известного идёт читающим пулом
This commit is contained in:
@@ -0,0 +1,54 @@
|
||||
package http
|
||||
|
||||
import (
|
||||
"log/slog"
|
||||
"net/http"
|
||||
"net/netip"
|
||||
|
||||
"git.vakhrushev.me/av/transcriber/internal/contract"
|
||||
)
|
||||
|
||||
// AppChain одевает адреса приложения в их слои.
|
||||
//
|
||||
// Порядок один и он несущий: ограничитель частоты → узнавание → требование
|
||||
// учётной записи → обработчик.
|
||||
//
|
||||
// - ограничитель стоит первым, потому что узнавание читает базу, а на новом
|
||||
// имени ещё и пишет в неё: поставленное раньше, оно работало бы на запросах,
|
||||
// которые ограничитель уже отверг, и поток отвергнутых обращений заводил бы
|
||||
// учётные записи, которые потом не убираются ничем;
|
||||
// - требование учётной записи стоит перед чтением тела: запись, за которую не
|
||||
// заплатит узнанный отправитель, не должна попасть даже в память, а позже
|
||||
// пришлось бы убирать уже уложенный файл — чего сервис не умеет вовсе.
|
||||
//
|
||||
// Область действия всех трёх — корень приложения, и берётся она из перечня
|
||||
// адресного пространства: цепочка вешается на корень целиком, вторым списком
|
||||
// адресов её не описывают.
|
||||
func AppChain(
|
||||
routes http.Handler,
|
||||
users contract.UserRepository,
|
||||
trusted []netip.Prefix,
|
||||
logger *slog.Logger,
|
||||
) http.Handler {
|
||||
handler := RequireUser()(routes)
|
||||
handler = TrustedHeaderIdentity(users, trusted, logger)(handler)
|
||||
handler = RateLimit(trusted)(handler)
|
||||
return handler
|
||||
}
|
||||
|
||||
// BuildHandler собирает поверхность сервиса целиком.
|
||||
//
|
||||
// Раздача приложения вешается последней: она занимает корень, и всё, что не
|
||||
// совпало ни с одним адресом сервиса, доходит до неё.
|
||||
//
|
||||
// Снаружи всех — журнал и восстановление после паники: первый обязан видеть код
|
||||
// ответа, каким бы слоем тот ни родился, второй — не дать одному паникующему
|
||||
// запросу уронить процесс.
|
||||
func BuildHandler(mounts []Mount, webapp *WebappHandler, logger *slog.Logger) http.Handler {
|
||||
mux := http.NewServeMux()
|
||||
|
||||
RegisterServiceRoutes(mux, mounts)
|
||||
webapp.Register(mux)
|
||||
|
||||
return Journal(mounts, logger)(Recover(logger)(mux))
|
||||
}
|
||||
Reference in New Issue
Block a user