Skip to content

Commit bf88b42

Browse files
committed
add pagination
1 parent 5d4f8ee commit bf88b42

File tree

1 file changed

+54
-8
lines changed

1 file changed

+54
-8
lines changed

fsharp/HopacSeries/Part3/ApiGateway.fsx

Lines changed: 54 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,15 +23,41 @@ let httpGet url =
2323
|> getResponse
2424
|> Job.bind Response.readBodyAsString
2525

26-
let host = "https://api.github.com"
27-
let userUrl = sprintf "%s/users/%s" host
26+
type GitHubResponse = {
27+
Body : string
28+
NextPageUrl : string option
29+
}
30+
31+
let getNextPageUrl (linkText : string) =
32+
linkText.Split([|','|])
33+
|> Array.map (fun l -> l.Split([|';'|]))
34+
|> Array.tryFind(fun l -> l.Length = 2 && l.[1].Contains("next"))
35+
|> Option.map(fun l -> l.[0].Trim().TrimStart('<').TrimEnd('>'))
36+
37+
let gitHubResponse response = job {
38+
let! body = Response.readBodyAsString response
39+
let nextPageUrl =
40+
match response.headers.TryFind(ResponseHeader.Link) with
41+
| Some linkText -> getNextPageUrl linkText
42+
| None -> None
43+
return {Body = body; NextPageUrl = nextPageUrl}
44+
}
45+
46+
let httpGetWithPagination url =
47+
Request.createUrl Get url
48+
|> Request.setHeader (UserAgent "FsHopac")
49+
|> getResponse
50+
|> Job.bind gitHubResponse
51+
52+
let basePath = "https://api.github.com"
53+
let userUrl = sprintf "%s/users/%s" basePath
2854

2955
let getUser username : Job<User> =
3056
userUrl username
3157
|> httpGet
3258
|> Job.map UserTypeProvider.Parse
3359

34-
let userReposUrl = sprintf "%s/users/%s/repos" host
60+
let userReposUrl = sprintf "%s/users/%s/repos?per_page=100" basePath
3561

3662
let topThreeUserRepos (repos : Repo []) =
3763
let takeCount =
@@ -42,14 +68,30 @@ let topThreeUserRepos (repos : Repo []) =
4268
|> Array.sortByDescending (fun repo -> repo.StargazersCount)
4369
|> Array.take takeCount
4470

71+
let getUserAllRepos username =
72+
let rec getUserAllRepos' url (repos : Repo list) = job {
73+
let! gitHubResponse =
74+
httpGetWithPagination url
75+
let currentPageRepos =
76+
gitHubResponse.Body
77+
|> ReposTypeProvider.Parse
78+
|> Array.toList
79+
let reposSoFar = repos @ currentPageRepos
80+
match gitHubResponse.NextPageUrl with
81+
| Some nextPageUrl ->
82+
return! getUserAllRepos' nextPageUrl reposSoFar
83+
| None -> return reposSoFar
84+
}
85+
getUserAllRepos' (userReposUrl username) []
86+
|> Job.map (List.toArray)
87+
4588
let getTopThreeUserRepos username : Job<Repo []> =
46-
userReposUrl username
47-
|> httpGet
48-
|> Job.map ReposTypeProvider.Parse
89+
getUserAllRepos username
4990
|> Job.map topThreeUserRepos
5091

92+
5193
let languagesUrl userName repoName =
52-
sprintf "%s/repos/%s/%s/languages" host userName repoName
94+
sprintf "%s/repos/%s/%s/languages" basePath userName repoName
5395

5496
let parseLanguagesJson languagesJson =
5597
languagesJson
@@ -98,4 +140,8 @@ let getUserDto username = job {
98140
AvatarUrl = user.AvatarUrl
99141
TopThreeRepos = repoDtos.ToArray()
100142
}
101-
}
143+
}
144+
145+
#time "on"
146+
getUserDto "haf" |> run
147+
#time "off"

0 commit comments

Comments
 (0)