Привет, сегодня мы рассмотрим функционал HTTP Round Tripper в стандартной библиотеке Go. Этот функционал позволяет улучшить работу с HTTP клиентами и написать более эффективный и автоматизированный код.
Давайте начнем с простых примеров. В основном, для создания HTTP запроса мы используем http.Client. Который выглядит следующим образом
type Client struct {
Transport RoundTripper
CheckRedirect func(req *Request, via []*Request) error
Jar CookieJar
Timeout time.Duration
}
Сегодня мы рассмотрим интерфейс Round Tripper, который представляет собой более низкоуровневую абстракцию для отправки HTTP запросов и получения ответов.
type RoundTripper interface {
RoundTrip(*Request) (*Response, error)
}
Интерфейс Round Tripper содержит всего один метод - RoundTrip, который выполняет одну транзакцию HTTP и возвращает ответ и ошибку. Мы можем настраивать Round Tripper для различных целей, например, для логирования запросов и ответов, повторной отправки запросов при ошибке, управления аутентификацией и иных других действий до или после запроса. Далее приведены базовые примеры использования.
Базовый пример логирующего
type loggingRoundTripper struct {
next http.RoundTripper
logger io.Writer
}
// RoundTrip декоратор дефолтного RoundTripper
func (l loggingRoundTripper) RoundTrip(r *http.Request) (*http.Response, error) {
// логирование зарпроса
fmt.Fprintf(l.logger, "[%s] %s %s\n", time.Now().Format(time.ANSIC), r.Method, r.URL.String())
resp, err := l.next.RoundTrip(r)
// логирование ответа
fmt.Fprintf(l.logger, "[%s] %s %s %d\n", time.Now().Format(time.ANSIC), r.Method, r.URL.String(), resp.StatusCode)
return resp, err
}
Базовый пример для ретрай логики
type retryRoundTripper struct {
next http.RoundTripper
maxRetries int
delay time.Duration
}
func (rr retryRoundTripper) RoundTrip(r *http.Request) (*http.Response, error) {
var res *http.Response
var err error
for attempts := 0; attempts < rr.maxRetries; attempts++ {
res, err = rr.next.RoundTrip(r)
// good outcome
if err == nil && res.StatusCode < http.StatusInternalServerError {
break
}
// delay and retry
select {
case <-r.Context().Done():
return res, r.Context().Err()
case <-time.After(rr.delay):
}
}
return res, err
}
Базовый пример для логики авторизации
type authRoundTripper struct {
next http.RoundTripper
user, pwd string
}
func (a authRoundTripper) RoundTrip(r *http.Request) (*http.Response, error) {
r.SetBasicAuth(a.user, a.pwd)
return a.next.RoundTrip(r)
}
После чего на основании данных RoundTripper можно иницализировать HTTP клиент
c := &http.Client{
Transport: &authRoundTripper{
next: &retryRoundTripper{
next: &loggingRoundTripper{
next: http.DefaultTransport,
logger: os.Stdout,
},
maxRetries: maxRetrieNum,
delay: delayDuration,
},
user: "user",
pwd: "pwd",
},
}
В общем, Round Tripper представляет собой мощный инструмент для настройки HTTP клиентов в Go, который позволяет улучшить их функциональность и эффективность. Применить данный инструмент можно для элегантного решения множества задач. В своем рабочем проекте получилось достаточно элегантно реализовать Round Tripper для авторизации посредством JWT, c перелоогином в случае когда токен перестал быть валидным. Возможно в ваших проектах вы найдете какое либо более интересное применение.
Надеюсь, эти примеры помогли вам лучше понять его возможности и применение.
Doc RoundTripper
Мой телеграм канал