@@ -114,24 +114,66 @@ auto ghSendRequest(T...)(HTTPMethod method, string url, T arg)
114
114
// range-based page loader for the GH API
115
115
private struct AllPages
116
116
{
117
- private string url;
118
- private string link = " next" ;
119
-
120
- // does not cache
121
- Json front () {
122
- scope req = ghGetRequest(url);
123
- link = req.headers.get (" Link" , null );
124
- return req.body ;
117
+ private static string [string ] parseLinks (string s)
118
+ {
119
+ string [string ] result;
120
+ auto items = s.split(" , " ); // Hacky but should never occur inside an URL or "rel" value
121
+ foreach (item; items)
122
+ {
123
+ auto parts = item.split(" ; " ); // ditto
124
+ string url; string [string ] args;
125
+ foreach (part; parts)
126
+ {
127
+ if (part.startsWith(" <" ) && part.endsWith(" >" ))
128
+ url = part[1 .. $- 1 ];
129
+ else
130
+ {
131
+ auto ps = part.findSplit(" =" );
132
+ auto key = ps[0 ];
133
+ auto value = ps[2 ];
134
+ if (value.startsWith(' "' ) && value.endsWith(' "' ))
135
+ value = value[1 .. $- 1 ];
136
+ args[key] = value;
137
+ }
138
+ }
139
+ result[args.get (" rel" , null )] = url;
140
+ }
141
+ return result;
142
+ }
143
+
144
+ unittest
145
+ {
146
+ auto header = ` <https://api.github.com/repositories/1257070/pulls?per_page=100&page=2>; rel="next", ` ~
147
+ ` <https://api.github.com/repositories/1257070/pulls?per_page=100&page=3>; rel="last"` ;
148
+ assert (parseLinks(header) == [
149
+ " next" : " https://api.github.com/repositories/1257070/pulls?per_page=100&page=2" ,
150
+ " last" : " https://api.github.com/repositories/1257070/pulls?per_page=100&page=3" ,
151
+ ]);
125
152
}
153
+
154
+ private Result result;
155
+
156
+ this (string url)
157
+ {
158
+ result = ghGetRequest(url);
159
+ }
160
+
161
+ Json front ()
162
+ {
163
+ return result.body ;
164
+ }
165
+
126
166
void popFront ()
127
167
{
128
- import std.utf : byCodeUnit;
129
- if (link)
130
- url = link[1 .. $].byCodeUnit.until(" >" ).array;
168
+ if (auto pNext = " next" in parseLinks(result.headers.get (" Link" , null )))
169
+ result = ghGetRequest(* pNext);
170
+ else
171
+ result = Result.init; // empty
131
172
}
173
+
132
174
bool empty ()
133
175
{
134
- return ! link.canFind( " next " ) ;
176
+ return result is Result.init ;
135
177
}
136
178
}
137
179
0 commit comments