auth/internal/client/repository/http/http_client.go

154 lines
3.0 KiB
Go
Raw Normal View History

package http
import (
"context"
2021-12-29 20:53:31 +00:00
"fmt"
http "github.com/valyala/fasthttp"
"source.toby3d.me/website/indieauth/internal/client"
"source.toby3d.me/website/indieauth/internal/domain"
"source.toby3d.me/website/indieauth/internal/util"
)
type httpClientRepository struct {
client *http.Client
}
const (
DefaultMaxRedirectsCount int = 10
hApp string = "h-app"
hXApp string = "h-x-app"
propertyLogo string = "logo"
propertyName string = "name"
propertyURL string = "url"
relRedirectURI string = "redirect_uri"
)
func NewHTTPClientRepository(c *http.Client) client.Repository {
return &httpClientRepository{
client: c,
}
}
2021-12-29 20:53:31 +00:00
func (repo *httpClientRepository) Get(ctx context.Context, id *domain.ClientID) (*domain.Client, error) {
req := http.AcquireRequest()
defer http.ReleaseRequest(req)
2021-12-29 20:53:31 +00:00
req.SetRequestURI(id.String())
2021-10-04 19:46:54 +00:00
req.Header.SetMethod(http.MethodGet)
resp := http.AcquireResponse()
defer http.ReleaseResponse(resp)
if err := repo.client.DoRedirects(req, resp, DefaultMaxRedirectsCount); err != nil {
2021-12-29 20:53:31 +00:00
return nil, fmt.Errorf("failed to make a request to the client: %w", err)
}
2021-12-29 20:53:31 +00:00
if resp.StatusCode() == http.StatusNotFound {
return nil, fmt.Errorf("%w: status on client page is not 200", client.ErrNotExist)
2021-12-29 20:53:31 +00:00
}
client := &domain.Client{
ID: id,
RedirectURI: make([]*domain.URL, 0),
2021-12-29 20:53:31 +00:00
Logo: make([]*domain.URL, 0),
URL: make([]*domain.URL, 0),
Name: make([]string, 0),
2021-12-29 20:53:31 +00:00
}
extract(client, resp)
return client, nil
}
func extract(dst *domain.Client, src *http.Response) {
for _, u := range util.ExtractEndpoints(src, relRedirectURI) {
if containsURL(dst.RedirectURI, u) {
continue
}
dst.RedirectURI = append(dst.RedirectURI, u)
}
for _, t := range []string{hXApp, hApp} {
for _, name := range util.ExtractProperty(src, t, propertyName) {
n, ok := name.(string)
if !ok || containsString(dst.Name, n) {
continue
}
2021-12-29 20:53:31 +00:00
dst.Name = append(dst.Name, n)
}
for _, logo := range util.ExtractProperty(src, t, propertyLogo) {
var err error
2021-12-29 20:53:31 +00:00
var u *domain.URL
switch l := logo.(type) {
2021-12-29 20:53:31 +00:00
case string:
2022-01-29 14:57:54 +00:00
u, err = domain.ParseURL(l)
case map[string]string:
value, ok := l["value"]
if !ok {
continue
}
2022-01-29 14:57:54 +00:00
u, err = domain.ParseURL(value)
}
if err != nil {
continue
}
if containsURL(dst.Logo, u) {
continue
}
dst.Logo = append(dst.Logo, u)
}
2021-12-29 20:53:31 +00:00
for _, url := range util.ExtractProperty(src, t, propertyURL) {
l, ok := url.(string)
if !ok {
continue
}
2021-12-29 20:53:31 +00:00
2022-01-29 14:57:54 +00:00
u, err := domain.ParseURL(l)
if err != nil {
continue
}
if containsURL(dst.URL, u) {
continue
}
2021-12-29 20:53:31 +00:00
dst.URL = append(dst.URL, u)
}
}
}
func containsString(src []string, find string) bool {
for i := range src {
if src[i] != find {
continue
}
2021-12-29 20:53:31 +00:00
return true
}
2021-12-29 20:53:31 +00:00
return false
}
func containsURL(src []*domain.URL, find *domain.URL) bool {
for i := range src {
if src[i].String() != find.String() {
continue
}
return true
}
return false
}