Documentation
¶
Overview ¶
Package restfront — собственный REST-фронт службы: два мультиплексора на двух слушателях, публичный и внутренний.
Предмет ¶
Пока служба стоит за краем платформы, её HTTP-поверхность принадлежит краю: маршруты объявлены аннотациями контракта, а поднимает их чужое дерево. Вынесенная отдельным продуктом, служба края не имеет BY CONSTRUCTION — и её REST обязан существовать сам.
Почему фронтов ДВА, а не один с разбором пути ¶
Раздельность есть свойство СОКЕТА, а не содержимого запроса. Один слушатель, решающий «этот путь внутренний, а этот нет», делает принадлежность маршрута фронту решением, принимаемым на каждом запросе. Требование «внутреннее не публикуется наружу» проверяемо ровно тогда, когда «не опубликован» значит «недосягаем»: это доказуемо снаружи одним обращением, а не чтением условия.
Почему регистрация ТОЛЬКО через собственный адрес ¶
Все звенья, решающие о вызывающем и о доступе к объекту, — перехватчики СЛУШАТЕЛЯ. Внутрипроцессная форма регистрации зовёт реализацию напрямую, поэтому запрос, пришедший по HTTP, обслуживался бы иначе, чем тот же запрос по gRPC: два пути к одному обработчику с разными решениями по дороге. REST и gRPC обязаны отвечать ОДНИМ звеном на один вопрос, а единственный способ это обеспечить — общий слушатель.
Почему свой обработчик ошибок здесь НЕ заводится ¶
Отображение кода отказа в HTTP-статус делает библиотека. Пока мультиплексор собран без своего обработчика, множество производимых статусов конечно, и вызывающему не приходится знать, через какую поверхность он пришёл. Заведи фронт свой обработчик — таблица статусов в приёмке перестанет описывать поведение и обязана переехать за ним тем же изменением.
Прежняя редакция этого абзаца обосновывала отсутствие обработчика тем, что множество статусов «совпадает у обеих HTTP-поверхностей платформы». Для отдельно поставленной службы это оказалось НЕВЕРНО, и неверно наблюдаемо: на промах глагола фронт отвечал 501, а эндпоинт выдачи токена — 405 (задача #2493).
Форма отказа на неверный ГЛАГОЛ — одна на обе внешние поверхности ¶
Обе отвечают 405. Это решение продукта, а не умолчание: библиотека переводит промах глагола в `Unimplemented`, то есть в 501, и «не реализовано» уводит клиента с дороги — он идёт заводить задачу вместо того, чтобы сменить глагол. Сведение живёт в обработчике ошибок МАРШРУТИЗАЦИИ (mux.go), который судит промах глагола и отображения кодов отказа не трогает.
Заголовок допустимых глаголов при этом остаётся ТОЛЬКО у эндпоинта токена, и это записанное расхождение, а не пропуск: у него глагол один и перечень известен, а фронт множество глаголов пути не знает — маршрутизатор наружу его не выставляет, и выписанный перечень был бы ложью. Предикат снятия — порождённая таблица маршрутов службы.
Index ¶
Constants ¶
const AuthenticationChallenge = "Bearer"
AuthenticationChallenge — ЕДИНСТВЕННОЕ значение подсказки.
Голая схема, без кода ошибки: RFC 6750 §3.1 прямо говорит, что запросу БЕЗ сведений об аутентификации код ошибки прилагать не следует. Отсюда и второе, более важное свойство — подсказка одинакова на ОБЕИХ полосах отказа аутентификации, поэтому по ней нельзя отличить «не предъявлял» от «предъявил негодное», и оракулом она не является.
Экспортировано затем, чтобы проба утверждала ЕГО, а не свою копию.
Variables ¶
This section is empty.
Functions ¶
func DialTarget ¶
DialTarget переводит адрес ПРИВЯЗКИ слушателя в адрес, по которому до него дозваниваются из этого же процесса.
Почему это не одно и то же ¶
«0.0.0.0» и «[::]» — не адреса машины, а указание «принимать на всех интерфейсах». Как цель соединения они неопределённы: часть систем резолвит их в петлю молча, часть отказывает, и поведение фронта зависело бы от того, где он поднят. Пустой хост (форма «:9090») неопределён ровно так же.
Перевод сделан ЯВНО, потому что цена неявного здесь не отказ, а расхождение стендов: на одном фронт работает, на другом — нет, и причина не видна ни в одном файле.
Порт сохраняется как есть: фронт идёт к СВОЕМУ слушателю, и другого порта у него быть не может.
func NewInternal ¶
func NewInternal(ctx context.Context, grpcAddr string, opts []grpc.DialOption) (http.Handler, error)
NewInternal собирает внутренний REST-фронт службы.
Отдельный мультиплексор на отдельном слушателе, а не разбор пути на общем: принадлежность маршрута фронту обязана быть свойством того, куда вообще можно дозвониться, а не решением, принимаемым на каждом запросе.
func NewPublic ¶
NewPublic собирает публичный REST-фронт службы.
grpcAddr — адрес СОБСТВЕННОГО публичного gRPC-слушателя. Через него и только через него идёт каждый запрос фронта: все звенья, решающие о вызывающем и о доступе к объекту, суть перехватчики слушателя, и внутрипроцессная регистрация обошла бы их все.
Types ¶
This section is empty.