diff --git a/cmd/install.go b/cmd/install.go index decdf66..e7c19b2 100644 --- a/cmd/install.go +++ b/cmd/install.go @@ -35,7 +35,7 @@ var installCmd = &cobra.Command{ } } - repo := core.NewRepository(core.DefaultHttpClient, packUrl, hformat, hhash) + repo := core.NewRepository(packUrl, hformat, hhash) err = repo.Load(cmd.Context()) if err != nil { return err @@ -44,7 +44,7 @@ var installCmd = &cobra.Command{ if err != nil { return err } - inst, err := core.NewLocalInstaller(cmd.Flag("dir").Value.String(), pack) + inst, err := core.NewLocalInstaller(pack, cmd.Flag("dir").Value.String()) if err != nil { return err } diff --git a/core/curseforge.go b/core/curseforge.go index eacd456..c036b95 100644 --- a/core/curseforge.go +++ b/core/curseforge.go @@ -4,10 +4,13 @@ import ( "context" "fmt" "os" + + "github.com/carlmjohnson/requests" ) var ( cf_api_key = "" + cf_api_host = "https://api.curseforge.com" DefaultCurseClient = NewCurseClient(getApiKey()) ) @@ -17,20 +20,17 @@ type cfDownloadUrlRes struct { type CurseClient struct { apiKey string - httpClient HttpClient + httpClient *requests.Builder } func NewCurseClient(apiKey string) *CurseClient { - c := &CurseClient{ + return &CurseClient{ apiKey: apiKey, - httpClient: NewHttpClient( - WithBaseURL("https://api.curseforge.com"), - WithAccept(acceptJson), - WithHeader("user-agent", userAgent), - WithHeader("x-api-key", apiKey), - ), + httpClient: defaultRequestBuilder. + Clone(). + BaseURL(cf_api_host). + Header("x-api-key", apiKey), } - return c } func getApiKey() string { @@ -45,7 +45,8 @@ func (c *CurseClient) getJson(ctx context.Context, path string, v any) error { if c.apiKey == "" { return fmt.Errorf("invalid curseforge api key") } - err := httpGetJson(ctx, c.httpClient, path, &v) + + err := c.httpClient.Path(path).ToJSON(&v).Fetch(context.WithoutCancel(ctx)) if err != nil { return fmt.Errorf("curseforge api: %w", err) } diff --git a/core/http-client.go b/core/http-client.go deleted file mode 100644 index 2458b02..0000000 --- a/core/http-client.go +++ /dev/null @@ -1,92 +0,0 @@ -package core - -import ( - "net/http" - "net/url" - "strings" - "time" -) - -const ( - acceptText = acceptMime("text/plain") - acceptHtml = acceptMime("text/html") - acceptJson = acceptMime("application/json") - acceptOctetStream = acceptMime("application/octet-stream") -) - -type acceptMime string -type httpOptFn func(c *httpClient) - -type HttpClient interface { - Do(req *http.Request) (*http.Response, error) -} - -type httpClient struct { - baseURL string - headers map[string]string - client *http.Client -} - -func NewHttpClient(opts ...httpOptFn) *httpClient { - c := &httpClient{ - headers: map[string]string{}, - client: &http.Client{ - Timeout: 30 * time.Second, - }, - } - for _, opt := range opts { - opt(c) - } - return c -} - -func (c *httpClient) Do(req *http.Request) (*http.Response, error) { - // apply baseURL - if c.baseURL != "" { - u, err := url.ParseRequestURI(c.baseURL + req.URL.Path) - if err != nil { - return nil, err - } - req.URL = u - } - - // apply headers - if c.headers != nil { - for k, v := range c.headers { - req.Header.Set(k, v) - } - } - - return c.client.Do(req) -} - -func WithBaseURL(u string) httpOptFn { - return func(c *httpClient) { - c.baseURL = u - } -} - -func WithAccept(mime acceptMime) httpOptFn { - return func(c *httpClient) { - c.headers["accept"] = string(mime) - } -} - -func WithHeader(key, value string) httpOptFn { - return func(c *httpClient) { - key = strings.ToLower(key) - c.headers[key] = value - } -} - -func WithTimeout(t time.Duration) httpOptFn { - return func(c *httpClient) { - c.client.Timeout = t - } -} - -func WithProxy(url *url.URL) httpOptFn { - return func(c *httpClient) { - c.client.Transport.(*http.Transport).Proxy = http.ProxyURL(url) - } -} diff --git a/core/http.go b/core/http.go index b69a6fb..f6c31d2 100644 --- a/core/http.go +++ b/core/http.go @@ -1,56 +1,45 @@ package core import ( + "bytes" "context" - "encoding/json" "fmt" - "io" "net/http" + + "github.com/carlmjohnson/requests" ) var ( - userAgent = "packwiz-install" - DefaultHttpClient = NewHttpClient(WithHeader("user-agent", userAgent)) + userAgent = "packwiz-install" + defaultRequestBuilder = newRequestBuilder(http.DefaultClient) ) -func httpGetJson(ctx context.Context, c HttpClient, url string, v any) error { - req, err := http.NewRequestWithContext(context.WithoutCancel(ctx), "GET", url, nil) - if err != nil { - return err - } - - req.Header.Set("accept", string(acceptJson)) - res, err := c.Do(req) - if err != nil { - return err - } - defer res.Body.Close() - - return json.NewDecoder(res.Body).Decode(v) +func newRequestBuilder(c *http.Client) *requests.Builder { + return requests.New(). + Client(c). + UserAgent(userAgent) } -func httpGetBytes(ctx context.Context, c HttpClient, url string) ([]byte, error) { - req, err := http.NewRequestWithContext(context.WithoutCancel(ctx), "GET", url, nil) - if err != nil { - return nil, err - } - req.Header.Set("accept", string(acceptOctetStream)) - - res, err := c.Do(req) - if err != nil { - return nil, err - } - defer res.Body.Close() +func httpGetJson(ctx context.Context, c *http.Client, url string, v any) error { + return defaultRequestBuilder.Clone().Client(c).BaseURL(url).ToJSON(&v).Fetch(ctx) +} - data, err := io.ReadAll(res.Body) +func httpGetBytes(ctx context.Context, c *http.Client, url string) ([]byte, error) { + buf := &bytes.Buffer{} + err := defaultRequestBuilder. + Clone(). + Client(c). + BaseURL(url). + ToBytesBuffer(buf). + Fetch(context.WithoutCancel(ctx)) if err != nil { return nil, err } - return data, nil + return buf.Bytes(), nil } -func httpGetValidBytes(ctx context.Context, c HttpClient, url string, hashFormat string, hash string) ([]byte, error) { - data, err := httpGetBytes(context.WithoutCancel(ctx), c, url) +func httpGetValidBytes(ctx context.Context, c *http.Client, url string, hashFormat string, hash string) ([]byte, error) { + data, err := httpGetBytes(ctx, c, url) if err != nil { return nil, err } diff --git a/core/installer.go b/core/installer.go index c4fb497..97fc1cd 100644 --- a/core/installer.go +++ b/core/installer.go @@ -5,6 +5,7 @@ import ( "context" "encoding/json" "fmt" + "net/http" "os" "path/filepath" "runtime" @@ -45,10 +46,10 @@ type Installer interface { type LocalInstaller struct { BaseDir string Pack *Pack - httpClient HttpClient + httpClient *http.Client } -func NewLocalInstaller(dir string, p *Pack) (*LocalInstaller, error) { +func NewLocalInstaller(p *Pack, dir string) (*LocalInstaller, error) { abs, err := filepath.Abs(dir) if err != nil { return nil, err @@ -56,7 +57,7 @@ func NewLocalInstaller(dir string, p *Pack) (*LocalInstaller, error) { return &LocalInstaller{ BaseDir: abs, Pack: p, - httpClient: DefaultHttpClient, + httpClient: http.DefaultClient, }, nil } diff --git a/core/repo.go b/core/repo.go index a6b862c..fcc9bcd 100644 --- a/core/repo.go +++ b/core/repo.go @@ -2,6 +2,7 @@ package core import ( "context" + "net/http" "net/url" "sync" @@ -17,15 +18,15 @@ type Repository struct { Metafiles []*MetafileToml PackHashFormat string PackHash string - httpClient HttpClient + httpClient *http.Client } -func NewRepository(c HttpClient, url *url.URL, hashFormat, hash string) *Repository { +func NewRepository(url *url.URL, hashFormat, hash string) *Repository { return &Repository{ Url: url, PackHashFormat: hashFormat, PackHash: hash, - httpClient: c, + httpClient: http.DefaultClient, } } diff --git a/go.mod b/go.mod index b890f3d..e7e0feb 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,10 @@ require ( github.com/spf13/cobra v1.8.0 ) -require github.com/inconshreveable/mousetrap v1.1.0 // indirect +require ( + github.com/inconshreveable/mousetrap v1.1.0 // indirect + golang.org/x/net v0.15.0 // indirect +) require ( github.com/BurntSushi/toml v1.2.1 // indirect @@ -16,6 +19,7 @@ require ( github.com/VividCortex/ewma v1.2.0 // indirect github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d // indirect github.com/aviddiviner/go-murmur v0.0.0-20150519214947-b9740d71e571 // indirect + github.com/carlmjohnson/requests v0.23.5 github.com/fsnotify/fsnotify v1.6.0 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/magiconair/properties v1.8.7 // indirect @@ -29,12 +33,12 @@ require ( github.com/subosito/gotenv v1.4.2 // indirect github.com/unascribed/FlexVer/go/flexver v1.0.0 // indirect github.com/vbauerster/mpb/v4 v4.12.2 // indirect - golang.org/x/crypto v0.5.0 // indirect + golang.org/x/crypto v0.13.0 // indirect golang.org/x/exp v0.0.0-20230118134722-a68e582fa157 // indirect golang.org/x/sync v0.6.0 - golang.org/x/sys v0.4.0 // indirect - golang.org/x/term v0.4.0 // indirect - golang.org/x/text v0.6.0 // indirect + golang.org/x/sys v0.12.0 // indirect + golang.org/x/term v0.12.0 // indirect + golang.org/x/text v0.13.0 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 9065640..fd366b4 100644 --- a/go.sum +++ b/go.sum @@ -49,6 +49,8 @@ github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d h1:licZJFw2RwpH github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d/go.mod h1:asat636LX7Bqt5lYEZ27JNDcqxfjdBQuJ/MM4CN/Lzo= github.com/aviddiviner/go-murmur v0.0.0-20150519214947-b9740d71e571 h1:seCdAEDyB0Hti/v1VajB7pAOIk9zmz/0/KE0D0oFqnc= github.com/aviddiviner/go-murmur v0.0.0-20150519214947-b9740d71e571/go.mod h1:VzSzsYCY3W9xWYWD8T2GLDidWTe5rTZv+UdDMGhLfjg= +github.com/carlmjohnson/requests v0.23.5 h1:NPANcAofwwSuC6SIMwlgmHry2V3pLrSqRiSBKYbNHHA= +github.com/carlmjohnson/requests v0.23.5/go.mod h1:zG9P28thdRnN61aD7iECFhH5iGGKX2jIjKQD9kqYH+o= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= @@ -216,8 +218,8 @@ golang.org/x/crypto v0.0.0-20200214034016-1d94cc7ab1c6/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.5.0 h1:U/0M97KRkSFvyD/3FSmdP5W5swImpNgle/EHFhOsQPE= -golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU= +golang.org/x/crypto v0.13.0 h1:mvySKfSWJ+UKUii46M40LOvyWfN0s2U+46/jDd0e6Ck= +golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -284,6 +286,8 @@ golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwY golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.15.0 h1:ugBLEUaxABaB5AJqW9enI0ACdci2RUd4eP51NTBvuJ8= +golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -341,19 +345,19 @@ golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.4.0 h1:Zr2JFtRQNX3BCZ8YtxRE9hNJYC8J6I1MVbMg6owUp18= -golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o= +golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.4.0 h1:O7UWfv5+A2qiuulQk30kVinPoMtoIPeVaKLEgLpVkvg= -golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ= +golang.org/x/term v0.12.0 h1:/ZfYdc3zq+q02Rv9vGqTeSItdzZTSNDmfTi0mBAuidU= +golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.6.0 h1:3XmdazWV+ubf7QgHSTWeykHOci5oeekaGJBLkrkaw4k= -golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= +golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= diff --git a/lefthook.yml b/lefthook.yml index b92ace7..0630ed4 100644 --- a/lefthook.yml +++ b/lefthook.yml @@ -14,6 +14,11 @@ pre-commit: run: > go vet ./... && git update-index --again + gomodtidy: + glob: "go.{mod,sum}" + run: > + go mod tidy + && git update-index --again goreleaser: glob: .goreleaser.yaml run: CF_API_KEY="" goreleaser release --snapshot --clean