94 lines
2.2 KiB
Go
94 lines
2.2 KiB
Go
package internal
|
|
|
|
import (
|
|
"context"
|
|
"net"
|
|
"net/http"
|
|
"net/url"
|
|
"time"
|
|
|
|
"github.com/pkg/errors"
|
|
"golang.org/x/text/language"
|
|
"golang.org/x/text/message/catalog"
|
|
)
|
|
|
|
var ErrInvalidResponseCode = errors.New("invalid response status code")
|
|
|
|
func NewExternalLoader(baseURL string, header http.Header) *ExternalLoader {
|
|
client := http.Client{
|
|
Transport: &http.Transport{
|
|
DialContext: (&net.Dialer{
|
|
Timeout: 2 * time.Second,
|
|
}).DialContext,
|
|
DisableKeepAlives: true,
|
|
MaxIdleConns: 1,
|
|
MaxIdleConnsPerHost: 1,
|
|
MaxConnsPerHost: 2,
|
|
IdleConnTimeout: 30 * time.Second,
|
|
ResponseHeaderTimeout: 5 * time.Second,
|
|
MaxResponseHeaderBytes: 1024 * 3,
|
|
WriteBufferSize: 100,
|
|
ReadBufferSize: 1024 * 8,
|
|
},
|
|
Timeout: time.Second * 10,
|
|
}
|
|
|
|
return NewExternalLoaderWithClient(baseURL, header, &client)
|
|
}
|
|
|
|
func NewExternalLoaderWithClient(baseURL string, header http.Header, client *http.Client) *ExternalLoader {
|
|
return &ExternalLoader{baseURL: baseURL, client: client, header: header}
|
|
}
|
|
|
|
type ExternalLoader struct {
|
|
baseURL string
|
|
header http.Header
|
|
client *http.Client
|
|
}
|
|
|
|
func (e *ExternalLoader) Load(builder *catalog.Builder) error {
|
|
languages := builder.Languages()
|
|
|
|
for _, lang := range languages {
|
|
if err := e.load(lang, builder); err != nil {
|
|
return errors.WithMessagef(err, "load translation for %s", lang.String())
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (e *ExternalLoader) load(lang language.Tag, builder *catalog.Builder) error {
|
|
langURL, err := url.JoinPath(e.baseURL, lang.String())
|
|
if err != nil {
|
|
return errors.Wrap(err, "join url path")
|
|
}
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
|
defer cancel()
|
|
|
|
req, err := http.NewRequestWithContext(ctx, http.MethodGet, langURL, nil)
|
|
if err != nil {
|
|
return errors.Wrap(err, "new request")
|
|
}
|
|
|
|
if e.header != nil {
|
|
req.Header = e.header
|
|
}
|
|
|
|
response, err := e.client.Do(req)
|
|
if err != nil {
|
|
return errors.Wrap(err, "do request")
|
|
}
|
|
|
|
if response.StatusCode != http.StatusOK {
|
|
return errors.Wrapf(ErrInvalidResponseCode, "got status %d", response.StatusCode)
|
|
}
|
|
|
|
if err := load(response.Body, lang, builder); err != nil {
|
|
return errors.WithMessage(err, "load translation")
|
|
}
|
|
|
|
return nil
|
|
}
|