From 46d2e17d297f56ad7a35a5ee77b2d31915f75585 Mon Sep 17 00:00:00 2001 From: Maxim Lebedev Date: Sat, 25 Sep 2021 16:00:19 +0500 Subject: [PATCH] :rotating_light: Removed linter warnings for client package --- go.mod | 1 + go.sum | 2 + .../client/repository/http/http_client.go | 90 +++++++++++-------- .../repository/http/http_client_test.go | 57 +++++++----- internal/client/usecase/client_ucase.go | 8 +- internal/client/usecase/client_ucase_test.go | 1 - internal/model/client.go | 2 +- 7 files changed, 101 insertions(+), 60 deletions(-) diff --git a/go.mod b/go.mod index fa85436..c99919b 100644 --- a/go.mod +++ b/go.mod @@ -9,6 +9,7 @@ require ( github.com/pkg/errors v0.9.1 github.com/spf13/viper v1.8.1 github.com/stretchr/testify v1.7.0 + github.com/tomnomnom/linkheader v0.0.0-20180905144013-02ca5825eb80 github.com/valyala/fasthttp v1.29.0 github.com/valyala/quicktemplate v1.6.3 go.etcd.io/bbolt v1.3.6 diff --git a/go.sum b/go.sum index e720e6b..266b4a9 100644 --- a/go.sum +++ b/go.sum @@ -254,6 +254,8 @@ github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5Cc github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= +github.com/tomnomnom/linkheader v0.0.0-20180905144013-02ca5825eb80 h1:nrZ3ySNYwJbSpD6ce9duiP+QkD3JuLCcWkdaehUS/3Y= +github.com/tomnomnom/linkheader v0.0.0-20180905144013-02ca5825eb80/go.mod h1:iFyPdL66DjUD96XmzVL3ZntbzcflLnznH0fr99w5VqE= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fasthttp v1.16.0/go.mod h1:YOKImeEosDdBPnxc0gy7INqi3m1zK6A+xl6TwOBhHCA= diff --git a/internal/client/repository/http/http_client.go b/internal/client/repository/http/http_client.go index b3a691b..596a7c4 100644 --- a/internal/client/repository/http/http_client.go +++ b/internal/client/repository/http/http_client.go @@ -6,6 +6,7 @@ import ( "net/url" "strings" + "github.com/pkg/errors" "github.com/tomnomnom/linkheader" http "github.com/valyala/fasthttp" "source.toby3d.me/website/oauth/internal/client" @@ -17,6 +18,19 @@ type httpClientRepository struct { client *http.Client } +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" +) + func NewHTTPClientRepository(c *http.Client) client.Repository { return &httpClientRepository{ client: c, @@ -34,7 +48,7 @@ func (repo *httpClientRepository) Get(ctx context.Context, id string) (*model.Cl defer http.ReleaseResponse(resp) if err := repo.client.Do(req, resp); err != nil { - return nil, err + return nil, errors.Wrap(err, "failed to make a request to the client") } client := new(model.Client) @@ -51,61 +65,67 @@ func (repo *httpClientRepository) Get(ctx context.Context, id string) (*model.Cl u, err := url.Parse(id) if err != nil { - return nil, err + return nil, errors.Wrap(err, "failed to parse id as url") } data := microformats.Parse(bytes.NewReader(resp.Body()), u) - populateItems(client, data.Items) - populateRels(client, data.Rels) + 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) return client, nil } -func populateItems(c *model.Client, items []*microformats.Microformat) { - for _, item := range items { - if len(item.Type) == 0 && item.Type[0] != "h-app" && item.Type[0] != "h-x-app" { +func populateProperties(src map[string][]interface{}, dst *model.Client) { + for key, property := range src { + if len(property) == 0 { continue } - for key, property := range item.Properties { - if len(property) == 0 { - continue - } - - switch key { - case "name": - for i := range property { - val, _ := property[i].(string) - c.Name = model.URL(val) - } - case "logo": - for i := range property { - switch val := property[i].(type) { - case string: - c.Logo = model.URL(val) - case map[string]string: - c.Logo = model.URL(val["value"]) - } - } - case "url": - for i := range property { - val, _ := property[i].(string) - c.URL = model.URL(val) + switch key { + case KeyName: + dst.Name = getString(property) + case KeyLogo: + for i := range property { + switch val := property[i].(type) { + case string: + dst.Logo = model.URL(val) + case map[string]string: + dst.Logo = model.URL(val[ValueValue]) } } + case KeyURL: + dst.URL = model.URL(getString(property)) } } } -func populateRels(c *model.Client, rels map[string][]string) { - for key, values := range rels { - if key != "redirect_uri" { +func populateRels(src map[string][]string, dst *model.Client) { + for key, values := range src { + if !strings.EqualFold(key, RelRedirectURI) { continue } for i := range values { - c.RedirectURI = append(c.RedirectURI, model.URL(values[i])) + dst.RedirectURI = append(dst.RedirectURI, model.URL(values[i])) } } } + +func getString(property []interface{}) string { + for i := range property { + val, _ := property[i].(string) + + return val + } + + return "" +} diff --git a/internal/client/repository/http/http_client_test.go b/internal/client/repository/http/http_client_test.go index f2422e5..3e6f1d4 100644 --- a/internal/client/repository/http/http_client_test.go +++ b/internal/client/repository/http/http_client_test.go @@ -2,12 +2,15 @@ package http_test import ( "context" + "net" "testing" + "github.com/pkg/errors" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "github.com/valyala/fasthttp" - "source.toby3d.me/website/oauth/internal/client/repository/http" + http "github.com/valyala/fasthttp" + httputil "github.com/valyala/fasthttp/fasthttputil" + repository "source.toby3d.me/website/oauth/internal/client/repository/http" "source.toby3d.me/website/oauth/internal/common" "source.toby3d.me/website/oauth/internal/model" ) @@ -33,35 +36,45 @@ const testBody string = ` func TestGet(t *testing.T) { t.Parallel() - //nolint: exhaustivestruct - srv := &fasthttp.Server{ - ReduceMemoryUsage: true, - GetOnly: true, - CloseOnShutdown: true, - Handler: func(ctx *fasthttp.RequestCtx) { - ctx.SuccessString(common.MIMETextHTML, testBody) - ctx.Response.Header.Set(fasthttp.HeaderLink, `; rel="redirect_uri">`) - }, - } - - go func(srv *fasthttp.Server) { - assert.NoError(t, srv.ListenAndServe("127.0.0.1:2368")) - }(srv) + ln := httputil.NewInmemoryListener() + u := http.AcquireURI() + u.SetScheme("http") + u.SetHost(ln.Addr().String()) t.Cleanup(func() { - assert.NoError(t, srv.Shutdown()) + http.ReleaseURI(u) + assert.NoError(t, ln.Close()) }) - result, err := http.NewHTTPClientRepository(new(fasthttp.Client)).Get(context.TODO(), "http://127.0.0.1:2368/") + go func(t *testing.T) { + t.Helper() + require.NoError(t, http.Serve(ln, func(ctx *http.RequestCtx) { + ctx.SuccessString(common.MIMETextHTML, testBody) + ctx.Response.Header.Set(http.HeaderLink, + `; rel="redirect_uri">`) + })) + }(t) + + client := new(http.Client) + client.Dial = func(addr string) (net.Conn, error) { + conn, err := ln.Dial() + if err != nil { + return nil, errors.Wrap(err, "failed to dial the address") + } + + return conn, nil + } + + result, err := repository.NewHTTPClientRepository(client).Get(context.TODO(), u.String()) require.NoError(t, err) assert.Equal(t, &model.Client{ - ID: "http://127.0.0.1:2368/", + ID: model.URL(u.String()), Name: "Example App", - Logo: "http://127.0.0.1:2368/logo.png", - URL: "http://127.0.0.1:2368/", + Logo: model.URL(u.String() + "logo.png"), + URL: model.URL(u.String()), RedirectURI: []model.URL{ "https://app.example.com/redirect", - "http://127.0.0.1:2368/redirect", + model.URL(u.String() + "redirect"), }, }, result) } diff --git a/internal/client/usecase/client_ucase.go b/internal/client/usecase/client_ucase.go index e9e9705..6800ab2 100644 --- a/internal/client/usecase/client_ucase.go +++ b/internal/client/usecase/client_ucase.go @@ -3,6 +3,7 @@ package usecase import ( "context" + "github.com/pkg/errors" "source.toby3d.me/website/oauth/internal/client" "source.toby3d.me/website/oauth/internal/model" ) @@ -18,5 +19,10 @@ func NewClientUseCase(clients client.Repository) client.UseCase { } func (useCase *clientUseCase) Discovery(ctx context.Context, clientID model.URL) (*model.Client, error) { - return useCase.clients.Get(ctx, string(clientID)) + c, err := useCase.clients.Get(ctx, string(clientID)) + if err != nil { + return nil, errors.Wrap(err, "failed to get client information") + } + + return c, nil } diff --git a/internal/client/usecase/client_ucase_test.go b/internal/client/usecase/client_ucase_test.go index 192b15a..bba4c24 100644 --- a/internal/client/usecase/client_ucase_test.go +++ b/internal/client/usecase/client_ucase_test.go @@ -7,7 +7,6 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - repository "source.toby3d.me/website/oauth/internal/client/repository/memory" "source.toby3d.me/website/oauth/internal/client/usecase" "source.toby3d.me/website/oauth/internal/model" diff --git a/internal/model/client.go b/internal/model/client.go index feaf578..d6a57da 100644 --- a/internal/model/client.go +++ b/internal/model/client.go @@ -2,7 +2,7 @@ package model type Client struct { ID URL - Name URL + Name string Logo URL URL URL RedirectURI []URL