2021-09-23 23:01:28 +00:00
|
|
|
package http
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bytes"
|
|
|
|
"context"
|
|
|
|
"net/url"
|
|
|
|
"strings"
|
|
|
|
|
2021-09-25 11:00:19 +00:00
|
|
|
"github.com/pkg/errors"
|
2021-09-23 23:01:28 +00:00
|
|
|
"github.com/tomnomnom/linkheader"
|
|
|
|
http "github.com/valyala/fasthttp"
|
|
|
|
"willnorris.com/go/microformats"
|
2021-09-29 20:35:39 +00:00
|
|
|
|
|
|
|
"source.toby3d.me/website/oauth/internal/client"
|
|
|
|
"source.toby3d.me/website/oauth/internal/domain"
|
2021-09-23 23:01:28 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
type httpClientRepository struct {
|
|
|
|
client *http.Client
|
|
|
|
}
|
|
|
|
|
2021-09-25 11:00:19 +00:00
|
|
|
const (
|
|
|
|
HApp string = "h-app"
|
|
|
|
HXApp string = "h-x-app"
|
|
|
|
|
|
|
|
KeyName string = "name"
|
|
|
|
KeyLogo string = "logo"
|
|
|
|
KeyURL string = "url"
|
|
|
|
|
|
|
|
ValueValue string = "value"
|
|
|
|
|
|
|
|
RelRedirectURI string = "redirect_uri"
|
|
|
|
)
|
|
|
|
|
2021-09-23 23:01:28 +00:00
|
|
|
func NewHTTPClientRepository(c *http.Client) client.Repository {
|
|
|
|
return &httpClientRepository{
|
|
|
|
client: c,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-09-29 20:35:39 +00:00
|
|
|
func (repo *httpClientRepository) Get(ctx context.Context, id string) (*domain.Client, error) {
|
2021-09-23 23:01:28 +00:00
|
|
|
req := http.AcquireRequest()
|
|
|
|
defer http.ReleaseRequest(req)
|
|
|
|
|
|
|
|
req.Header.SetMethod(http.MethodGet)
|
|
|
|
req.SetRequestURI(id)
|
|
|
|
|
|
|
|
resp := http.AcquireResponse()
|
|
|
|
defer http.ReleaseResponse(resp)
|
|
|
|
|
|
|
|
if err := repo.client.Do(req, resp); err != nil {
|
2021-09-25 11:00:19 +00:00
|
|
|
return nil, errors.Wrap(err, "failed to make a request to the client")
|
2021-09-23 23:01:28 +00:00
|
|
|
}
|
|
|
|
|
2021-09-29 20:35:39 +00:00
|
|
|
client := domain.NewClient()
|
|
|
|
client.ID = id
|
2021-09-23 23:01:28 +00:00
|
|
|
|
|
|
|
for _, l := range linkheader.Parse(string(resp.Header.Peek(http.HeaderLink))) {
|
|
|
|
if !strings.Contains(l.Rel, "redirect_uri") {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
2021-09-29 20:35:39 +00:00
|
|
|
client.RedirectURI = append(client.RedirectURI, l.URL)
|
2021-09-23 23:01:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
u, err := url.Parse(id)
|
|
|
|
if err != nil {
|
2021-09-25 11:00:19 +00:00
|
|
|
return nil, errors.Wrap(err, "failed to parse id as url")
|
2021-09-23 23:01:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
data := microformats.Parse(bytes.NewReader(resp.Body()), u)
|
|
|
|
|
2021-09-25 11:00:19 +00:00
|
|
|
for _, item := range data.Items {
|
|
|
|
if len(item.Type) == 0 && !strings.EqualFold(item.Type[0], HApp) &&
|
|
|
|
!strings.EqualFold(item.Type[0], HXApp) {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
populateProperties(item.Properties, client)
|
|
|
|
}
|
|
|
|
|
|
|
|
populateRels(data.Rels, client)
|
2021-09-23 23:01:28 +00:00
|
|
|
|
|
|
|
return client, nil
|
|
|
|
}
|
|
|
|
|
2021-09-29 20:35:39 +00:00
|
|
|
func populateProperties(src map[string][]interface{}, dst *domain.Client) {
|
2021-09-25 11:00:19 +00:00
|
|
|
for key, property := range src {
|
|
|
|
if len(property) == 0 {
|
2021-09-23 23:01:28 +00:00
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
2021-09-25 11:00:19 +00:00
|
|
|
switch key {
|
|
|
|
case KeyName:
|
|
|
|
dst.Name = getString(property)
|
|
|
|
case KeyLogo:
|
|
|
|
for i := range property {
|
|
|
|
switch val := property[i].(type) {
|
|
|
|
case string:
|
2021-09-29 20:35:39 +00:00
|
|
|
dst.Logo = val
|
2021-09-25 11:00:19 +00:00
|
|
|
case map[string]string:
|
2021-09-29 20:35:39 +00:00
|
|
|
dst.Logo = val[ValueValue]
|
2021-09-23 23:01:28 +00:00
|
|
|
}
|
|
|
|
}
|
2021-09-25 11:00:19 +00:00
|
|
|
case KeyURL:
|
2021-09-29 20:35:39 +00:00
|
|
|
dst.URL = getString(property)
|
2021-09-23 23:01:28 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-09-29 20:35:39 +00:00
|
|
|
func populateRels(src map[string][]string, dst *domain.Client) {
|
2021-09-25 11:00:19 +00:00
|
|
|
for key, values := range src {
|
|
|
|
if !strings.EqualFold(key, RelRedirectURI) {
|
2021-09-23 23:01:28 +00:00
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
for i := range values {
|
2021-09-29 20:35:39 +00:00
|
|
|
dst.RedirectURI = append(dst.RedirectURI, values[i])
|
2021-09-23 23:01:28 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-09-25 11:00:19 +00:00
|
|
|
|
|
|
|
func getString(property []interface{}) string {
|
|
|
|
for i := range property {
|
|
|
|
val, _ := property[i].(string)
|
|
|
|
|
|
|
|
return val
|
|
|
|
}
|
|
|
|
|
|
|
|
return ""
|
|
|
|
}
|