Skip to content

Commit 80c34a3

Browse files
authored
feat: add a simple version resolver api (#25)
* feat: add a simple version resolver api * feat: simple rate limiter addition for the same
1 parent 5a2b1d6 commit 80c34a3

File tree

3 files changed

+79
-0
lines changed

3 files changed

+79
-0
lines changed

cmd/goblin-api/main.go

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package main
22

33
import (
44
"bytes"
5+
"encoding/json"
56
"errors"
67
"flag"
78
"fmt"
@@ -19,11 +20,42 @@ import (
1920
"github.com/barelyhuman/goblin/resolver"
2021
"github.com/barelyhuman/goblin/storage"
2122
"github.com/joho/godotenv"
23+
"go.uber.org/ratelimit"
2224
)
2325

2426
var shTemplates *template.Template
2527
var serverURL string
2628
var storageClient storage.Storage
29+
var rateLimiter ratelimit.Limiter
30+
31+
type ErrorJSON struct {
32+
Success bool `json:"success"`
33+
Message string `json:"message"`
34+
}
35+
36+
func (ej ErrorJSON) toJSONString() (string, error) {
37+
marshaled, err := json.Marshal(ej)
38+
if err != nil {
39+
return "", err
40+
}
41+
return string(marshaled), nil
42+
}
43+
44+
type VersionJSON struct {
45+
Success bool `json:"success"`
46+
Package string `json:"package"`
47+
Binary string `json:"binary"`
48+
OriginalVersion string `json:"originalVersion"`
49+
Version string `json:"version"`
50+
}
51+
52+
func (ej VersionJSON) toJSONString() (string, error) {
53+
marshaled, err := json.Marshal(ej)
54+
if err != nil {
55+
return "", err
56+
}
57+
return string(marshaled), nil
58+
}
2759

2860
func HandleRequest(rw http.ResponseWriter, req *http.Request) {
2961
path := req.URL.Path
@@ -41,6 +73,13 @@ func HandleRequest(rw http.ResponseWriter, req *http.Request) {
4173
return
4274
}
4375

76+
if strings.HasPrefix(path, "/version") {
77+
log.Println("Resolving version")
78+
rateLimiter.Take()
79+
resolveVersionJSON(rw, req)
80+
return
81+
}
82+
4483
if strings.HasPrefix(path, "/binary") {
4584
log.Print("handle binary")
4685
fetchBinary(rw, req)
@@ -75,6 +114,9 @@ func main() {
75114

76115
flag.Parse()
77116

117+
// starting off with 250 since there's only one operation that's being rate limited
118+
rateLimiter = ratelimit.New(250)
119+
78120
if _, err := os.Stat(*envFile); !errors.Is(err, os.ErrNotExist) {
79121
err := godotenv.Load()
80122
if err != nil {
@@ -225,6 +267,36 @@ func fetchInstallScript(rw http.ResponseWriter, req *http.Request) {
225267
})
226268
}
227269

270+
func resolveVersionJSON(rw http.ResponseWriter, req *http.Request) {
271+
// only reply in JSON
272+
rw.Header().Set("Content-Type", "application/json")
273+
274+
pkg := strings.TrimPrefix(req.URL.Path, "/version")
275+
pkg, _, version, name := parsePackage(pkg)
276+
v := &resolver.Resolver{
277+
Pkg: pkg,
278+
}
279+
v.ParseVersion(version)
280+
resolvedVersion, err := v.ResolveVersion()
281+
if err != nil || len(resolvedVersion) == 0 {
282+
errorJson, _ := ErrorJSON{Success: false, Message: "Failed to resolve version:" + version}.toJSONString()
283+
rw.Write([]byte(errorJson))
284+
return
285+
}
286+
287+
responseJson, _ := VersionJSON{
288+
Success: true,
289+
Package: pkg,
290+
Binary: name,
291+
OriginalVersion: version,
292+
Version: resolvedVersion,
293+
}.toJSONString()
294+
295+
rw.Write([]byte(responseJson))
296+
return
297+
298+
}
299+
228300
func fetchBinary(rw http.ResponseWriter, req *http.Request) {
229301
pkg := strings.TrimPrefix(req.URL.Path, "/binary/")
230302

go.mod

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,13 @@ require (
99
github.com/joho/godotenv v1.5.1
1010
github.com/minio/minio-go v6.0.14+incompatible
1111
github.com/tj/go-semver v1.0.0
12+
go.uber.org/ratelimit v0.3.1
1213
golang.org/x/oauth2 v0.16.0
1314
)
1415

1516
require (
1617
github.com/ProtonMail/go-crypto v1.0.0 // indirect
18+
github.com/benbjohnson/clock v1.3.0 // indirect
1719
github.com/cloudflare/circl v1.3.7 // indirect
1820
github.com/go-ini/ini v1.67.0 // indirect
1921
github.com/golang/protobuf v1.5.3 // indirect

go.sum

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ github.com/ProtonMail/go-crypto v1.0.0 h1:LRuvITjQWX+WIfr930YHG2HNfjR1uOfyf5vE0k
44
github.com/ProtonMail/go-crypto v1.0.0/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0=
55
github.com/barelyhuman/go v0.2.2 h1:Lpk1XrlP40F3II8BibVzViZUOJ1GgDdzXUBb8ENwb0U=
66
github.com/barelyhuman/go v0.2.2/go.mod h1:hox2iDYZAarjpS7jKQeYIi2F+qMA8KLMtCws++L2sSY=
7+
github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A=
8+
github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
79
github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0=
810
github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA=
911
github.com/cloudflare/circl v1.3.7 h1:qlCDlTPz2n9fu58M0Nh1J/JzcFpfgkFHHX3O35r5vcU=
@@ -45,6 +47,9 @@ github.com/tj/assert v0.0.0-20190920132354-ee03d75cd160/go.mod h1:mZ9/Rh9oLWpLLD
4547
github.com/tj/go-semver v1.0.0 h1:vpn6Jmn6Hi3QSmrP1PzYcqScop9IZiGCVOSn18wzu8w=
4648
github.com/tj/go-semver v1.0.0/go.mod h1:YZuwVc013rh7KDV0k6tPbWrFeEHBHcp8amfJL+nHzjM=
4749
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
50+
go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=
51+
go.uber.org/ratelimit v0.3.1 h1:K4qVE+byfv/B3tC+4nYWP7v/6SimcO7HzHekoMNBma0=
52+
go.uber.org/ratelimit v0.3.1/go.mod h1:6euWsTB6U/Nb3X++xEUXA8ciPJvr19Q/0h1+oDcJhRk=
4853
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
4954
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
5055
golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=

0 commit comments

Comments
 (0)