go-challenge/swapi.go
2022-10-21 12:02:03 -05:00

97 lines
2.1 KiB
Go

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
}