babychristopher2023
Member
- Joined
- Aug 26, 2023
- Messages
- 14
- Programming Experience
- Beginner
what is the proper way to create a console app using .net 7 and use http client to hit an api endpoint that requires oauth?
Please read the flurl docs on their website; doing auth is essentially a one line operation:would still have same hurdles of passing in basic auth
So they tell us that we can get the TotalRecords that our query params return, and then we must use skip and take to query/query/query until we get all of the results. But limitations are only 1,000 records are returned at at time, and we can only make 15 requests every 60 seconds
If you don't want to roll your own scheduling system, most people just take an off the shell message queuing system and queue messages with specific times for when the messages should be processed. So in your case, each queued item would be one of the pages as well as one queued item to process all the pages once they are available.
var res = await response.Content.ReadFromJsonAsync<T>();
int totalRecords = res.TotalRecords;
int batchSize = 1000;
int skip = 0;
int take = 0;
int iterations = 0;
int maxIterations = totalRecords / batchSize;
do
{
Console.WriteLine("API Requset Number: {0}", iterations);
iterations++;
} while (iterations <= maxIterations);
Or is it best practice to use just the base http client?
f you want full control to be able to monitor and tweak performance (or manage any potential security issues), then writing your own code would be the way to go
Technically it's (16876/1000)+1 - you can't make 0.876 of a request (if you're doing double math) and integer math would omit the last page of 876 resultsSo the TotalResults is 16876, the API will only return 1,000 at a time, so I would need to make 16876/1000 requests in order to get all of the records.
for(int x= 0; x<totalCount; x+= 1000){
var r = await "api.com/getthings"
.SetQueryParams(new { start = x, num = 1000 } )
.GetJsonAsync<MyThing[]>();
}
var r = await "api.com/getthings"
.GetJsonAsync<MyThing[]>();
var nextReq =DateTime.Now;
for(int x= 0; x<totalCount; x+= 1000)
{
if(nextReq > DateTime.Now) await Task.Delay(nextReq - DateTime.Now);
var r = await "api.com/getthings"
.SetQueryParams(new { start = x, num = 1000 } )
.GetJsonAsync<MyThing[]>();
nextReq = nextReq.AddMilliseconds(667); //keep to 3 req in 2 sec, a bit slower than the 4 req in 2 sec rate limit
}
Since there are so many stipulations/requirements in place by the APi with very little documentation, I wasn't sure if a 3rd party lib or nuget package etc would handle this best.
Technically it's (16876/1000)+1 - you can't make 0.876 of a request (if you're doing double math) and integer math would omit the last page of 876 results
Every API is different as to how it paginates so no, there isn't something built that automatically paginates for you. The notion is simple though, typically you supply some parameter to start from, so you just run your calls in a loop that starts x=0, gets 1000 results from api.com/getthings?start=0&num=1000 and then increments x. In flurl that might look like:
C#:for(int x= 0; x<totalCount; x+= 1000){ var r = await "api.com/getthings" .SetQueryParams(new { start = x, num = 1000 } ) .GetJsonAsync<MyThing[]>(); }
Compared to a non paginated version
C#:var r = await "api.com/getthings" .GetJsonAsync<MyThing[]>();
Pagination isn't particularly onerous.
I tend to read the api docs too and find out if there is a request limit like 2 per second and then add some delay code to keep to that
C#:var nextReq =DateTime.Now; for(int x= 0; x<totalCount; x+= 1000) { if(nextReq > DateTime.Now) await Task.Delay(nextReq - DateTime.Now); var r = await "api.com/getthings" .SetQueryParams(new { start = x, num = 1000 } ) .GetJsonAsync<MyThing[]>(); nextReq = nextReq.AddMilliseconds(667); //keep to 3 req in 2 sec, a bit slower than the 4 req in 2 sec rate limit }
Edit: I just read that you're allowed 15 in 60. You might want to keep a queue of all the dates you've made a request, and if the queue length is <15 or the oldest request in the last 15 is >60s ago, make the request, else wait for 60-(now-oldest).TotalSeconds). This way you can burst request up to 15, then wait the minimum time. Cap the queue at 15 items
If that doesnt make sense or is too hard, just make one request every 4 seconds (nextReq.AddSeconds(4))
Forum etiquette; please don't quote a massive post in it's entirety and then (essentially) just say "thanks" under it.Ohhhh - that makes sense. Wow,
Please read the flurl docs on their website; doing auth is essentially a one line operation:would still have same hurdles of passing in basic auth
var r = await "https://api.xxxxx.com"
.AppendPathSegment("/hipments/search")
.SetQueryParams(new { skip = x, take = 1000, shipmentDateBegin = "08/01/2023", shipmentDateEnd = "08/10/2023"} )
.WithBasicAuth("username", "password")
.GetJsonAsync<T[]>();