@@ -2,6 +2,7 @@ package main
22
33import (
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
2426var shTemplates * template.Template
2527var serverURL string
2628var 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
2860func 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+
228300func fetchBinary (rw http.ResponseWriter , req * http.Request ) {
229301 pkg := strings .TrimPrefix (req .URL .Path , "/binary/" )
230302
0 commit comments