Нет описания

unpaginate.go 2.9KB

    // `unpaginate` unpaginates json resources. // // The requested resource is assumed to return an array of JSON // objects. `unpaginate` prints a new array containing the JSON // objects from all pages on stdout. // // Pagination is assumed to be in the format that the GitHub v3 // API uses: // // HTTP/1.1 200 OK // ... // Link: <https://api.github.com/user/527119/repos?per_page=42&page=2>; rel="next", <https://api.github.com/user/527119/repos?per_page=42&page=2>; rel="last" package main import ( "encoding/base64" "encoding/json" "flag" "fmt" "golang.org/x/crypto/ssh/terminal" "net/http" "os" "strings" ) var config struct { userInfo string } func init() { flag.StringVar(&config.userInfo, "user", "", "The basic auth user information") flag.Usage = func() { fmt.Fprintf(os.Stderr, "Usage: %s [flags] <url>\n\n", os.Args[0]) fmt.Fprintf(os.Stderr, `Fetches JSON documents from a paginated resource and returns a single JSON document. `) flag.PrintDefaults() fmt.Fprintf(os.Stderr, " -h, --help\n\tDisplay this message\n") } } func main() { flag.Parse() if flag.NArg() != 1 { flag.Usage() os.Exit(1) } url := flag.Arg(0) authorization := "" if config.userInfo != "" { if !strings.Contains(config.userInfo, ":") { fmt.Fprint(os.Stderr, "Type in your password/token: ") password, err := terminal.ReadPassword(int(os.Stdin.Fd())) if err != nil { fmt.Println(err) os.Exit(1) } config.userInfo += ":" + string(password) } authorization = "Basic " + base64.StdEncoding.EncodeToString([]byte(config.userInfo)) } os.Stdout.WriteString("[\n") first := true for url != "" { req, err := http.NewRequest("GET", url, nil) if err != nil { fmt.Println(err) os.Exit(1) } if authorization != "" { req.Header.Set("Authorization", authorization) } res, err := http.DefaultClient.Do(req) if err != nil { fmt.Println(err) os.Exit(1) } decoder := json.NewDecoder(res.Body) _, err = decoder.Token() if err != nil { fmt.Println(err) os.Exit(1) } for decoder.More() { if !first { os.Stdout.WriteString(", ") } else { first = false } var data interface{} err := decoder.Decode(&data) if err != nil { fmt.Println("decode:", err) os.Exit(1) } out, err := json.MarshalIndent(data, " ", " ") if err != nil { fmt.Println(err) os.Exit(1) } os.Stdout.Write(out) } _, err = decoder.Token() if err != nil { fmt.Println(err) os.Exit(1) } url = "" links := res.Header.Get("Link") if links != "" { for _, link := range strings.Split(links, ",") { link := strings.TrimSpace(link) start := strings.Index(link, "<") end := strings.Index(link, ">") if start != -1 && end != -1 && start < end && strings.HasSuffix(link, "rel=\"next\"") { url = link[start+1 : end] break } } } } os.Stdout.WriteString("\n]\n") }