package main import ( "encoding/json" log "github.com/sirupsen/logrus" "net/http" ) const API_PREFIX = "https://swapi.dev/api" // Source: https://swapi.dev/documentation#people type Person struct { Name string // ... other fields unused by this application } // Source: https://swapi.dev/documentation#starships type Starship struct { Name string Pilots []string // URLs to retrieve [People] // ... other fields unused by this application } // Structs which may be retrieved in a paginated fasion from swapi.dev type Pageable interface { Starship | Person } type Gettable interface { Starship | Person } // Represents a single page of [Pageable] structs type PageOf[T Pageable] struct { Count uint Next *string Previous *string Results []T } // Used for retrieving data from swapi.dev // // resp, err := Get("/starships") // // If [path] does not start with "/", it assumes you have provided a full URL to // make following [PageOf]'s [Next] and [Previous] simpler. // // resp, err := Get("https://git.lyte.dev/swagger.v1.json") func Get[T interface{}](path string, data *T) error { var url string if path[0] == '/' { url = API_PREFIX + path } else { url = path } resp, err := http.Get(url) if err != nil { log.Errorf("Error GET'ing %s: %+v", url, err) } defer resp.Body.Close() err = json.NewDecoder(resp.Body).Decode(data) if err != nil { log.Errorf("Failed to decode response JSON: %+v", err) } log.Debugf("GET %s: %+v", url, resp) return err } func AllStarships() (*[]Starship, error) { results := make([]Starship, 0) var page PageOf[Starship] var resp *http.Response err := Get("/starships", &page) if err != nil { return &[]Starship{}, err } err = json.NewDecoder(resp.Body).Decode(&page) log.Debugf("Page: %+v", page) if err != nil { log.Errorf("Error decoding response body: %+v", err) } results = append(results, page.Results...) // TODO: loop for page.Next != nil { err := Get(*page.Next, &page) log.Debugf("Page: %+v", page) if err != nil { return &[]Starship{}, err } json.NewDecoder(resp.Body).Decode(&page) results = append(results, page.Results...) } return &results, nil }