A while ago I built a little web app using the Strava API, that tells you how far you’ve run so far this year, and how many miles you’re projected to do my the end of the year if you keep up the same average.
As Strava lets you see your friends’ year-to-date mileage on their profile pages, I thought it would be a nice addition to generate a leaderboard to show where you stood against your running friends. The URI to query an athlete’s stats is https://www.strava.com/api/v3/athletes/:id/stats
, which I’m already using to get the stats for the person using my app, so all I have to do is query that person’s friends list and map over all the IDs calling the same API with their IDs, right?
First things first, mock up the UI for the new page. After a bit of wrestling with Bootstrap I had some navigation elements I was happy with, so moved onto the core app. It turned out that the Strava library I’m using didn’t have a wrapper for the friends/followers API, but it was pretty easy to add one, so I made the required changes and submitted a pull request. Then a nice test-driven feature from the outside of the app, stubbing the boundary to the function that retrieved the stats for each friend, as that was already there for the current user and didn’t need to be changed. A data structure specifically to hold the friend’s name, profile URL and mileage to display in the table, and a public function to return a list of those structs, and the core was all done.
Finally I put it all together, wired the controller in the web app up to the core function to make the required query, and modified the view to display each friend’s details in a row in the leaderboard. Tests all green! Finally! Let’s try it out!
500 internal server error
Wait, that’s not supposed to happen. Lets look at the logs. Hmm, the call to the Strava API seems to be failing. Unauthorised. That’s odd.
Better take another look at the API documentation.
Totals and stats
Returns recent (last 4 weeks), year to date and all time stats for a given athlete. Only available for the authenticated athlete. This is the recommended endpoint when polling for athlete upload events.
Wait, what’s that bit in the middle again? “Only available for the authenticated athlete”. Oh. Realisation dawns. No leaderboard then, and a couple of days’ work wasted on a branch that’s never going to make it into master
.
So what’s the moral of the story? If you’re building a feature that relies on something outside your control, don’t make assumptions about what works and what doesn’t. Build a spike first, to test your assumptions before ploughing your time into building the real thing.
Oh, and read the documentation.