feat(gateway): WebSocket Gateway с HELLO, IDENTIFY и READY
Реализован Gateway по AGENT.md §8.3:
- оп-коды 0/1/2/3/4/7/10/11, единый конверт {op,t,d,s};
- HELLO с интервалом сердцебиения (45 с) и идентификатором сессии;
- IDENTIFY/RESUME с проверкой токена через auth.ResolveSession;
- READY: пользователь, серверы, видимые комнаты, роли, участники и права,
собранные через движок прав (VIEW_CHANNEL-фильтрация);
- HEARTBEAT → HEARTBEAT_ACK, лимит частоты IDENTIFY (5 с);
- RESUME: буфер на 1000 событий с TTL 5 минут, догон пропущенных событий и
подтверждение RESUMED, полный READY при расхождении состояния;
- рассылка Dispatch/SendToUser с буферизацией для отключённых сессий;
- проверка Origin по allowlist доменов инстанса (AGENT.md §9.7);
- httpx.statusRecorder пробрасывает Hijack, иначе апгрейд ломается.
Тесты: 6 сценариев Gateway (READY, скрытые комнаты, неверный токен,
heartbeat, dispatch, RESUME) и 2 теста маршрута /gateway через полный стек
middleware, включая отклонение чужого Origin.
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
package httpx
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"context"
|
||||
"log/slog"
|
||||
"net"
|
||||
@@ -44,6 +45,20 @@ func (r *statusRecorder) Flush() {
|
||||
}
|
||||
}
|
||||
|
||||
// Unwrap отдаёт исходный ResponseWriter: http.ResponseController и другие
|
||||
// обёртки должны видеть возможности базового писателя.
|
||||
func (r *statusRecorder) Unwrap() http.ResponseWriter { return r.ResponseWriter }
|
||||
|
||||
// Hijack пробрасывает перехват соединения: без него не работает апгрейд на
|
||||
// WebSocket через /gateway (AGENT.md 8.3).
|
||||
func (r *statusRecorder) Hijack() (net.Conn, *bufio.ReadWriter, error) {
|
||||
hijacker, ok := r.ResponseWriter.(http.Hijacker)
|
||||
if !ok {
|
||||
return nil, nil, http.ErrNotSupported
|
||||
}
|
||||
return hijacker.Hijack()
|
||||
}
|
||||
|
||||
// RequestInfoMiddleware кладёт IP и User-Agent запроса в контекст: huma-хендлеры
|
||||
// не получают *http.Request, а сервисам эти данные нужны (аудит, безопасность).
|
||||
func RequestInfoMiddleware(next http.Handler) http.Handler {
|
||||
|
||||
Reference in New Issue
Block a user