github.com/mavryk-network/mvgo@v1.19.9/internal/compose/fetch.go (about) 1 // Copyright (c) 2023 Blockwatch Data Inc. 2 // Author: alex@blockwatch.cc, abdul@blockwatch.cc 3 4 package compose 5 6 import ( 7 "encoding/json" 8 "fmt" 9 "io" 10 "net/http" 11 "net/http/httputil" 12 "strings" 13 14 "github.com/echa/log" 15 "github.com/tidwall/gjson" 16 ) 17 18 func Fetch[T any](ctx Context, url string) (*T, error) { 19 cleanUrl, jsonPath, hasPath := strings.Cut(url, "#") 20 client := http.DefaultClient 21 req, err := http.NewRequestWithContext(ctx, http.MethodGet, cleanUrl, nil) 22 if err != nil { 23 return nil, err 24 } 25 if ctx.apiKey != "" { 26 req.Header.Add("X-Api-Key", ctx.apiKey) 27 } 28 if ctx.Log.Level() == log.LevelDebug { 29 ctx.Log.Debugf("%s %s %s", req.Method, req.URL, req.Proto) 30 } 31 if ctx.Log.Level() == log.LevelTrace { 32 d, _ := httputil.DumpRequest(req, true) 33 ctx.Log.Trace(string(d)) 34 } 35 res, err := client.Do(req) 36 if err != nil { 37 return nil, err 38 } 39 if ctx.Log.Level() == log.LevelTrace { 40 d, _ := httputil.DumpResponse(res, true) 41 ctx.Log.Trace(string(d)) 42 } 43 if res.StatusCode != 200 { 44 return nil, fmt.Errorf("request failed: %s ", res.Status) 45 } 46 defer res.Body.Close() 47 buf, err := io.ReadAll(res.Body) 48 if err != nil { 49 return nil, err 50 } 51 if hasPath { 52 res := gjson.GetBytes(buf, jsonPath) 53 if !res.Exists() { 54 return nil, fmt.Errorf("missing path %q in result from %s", jsonPath, cleanUrl) 55 } 56 buf = []byte(res.Raw) 57 } 58 var k T 59 if err := json.Unmarshal(buf, &k); err != nil { 60 return nil, err 61 } 62 return &k, nil 63 }