My Kingdom for an API (that works!)

By far the most complicated thing about this project was finding the right API to work with. Historical reading indicated that Google’s Image Search API had once been fairly open, but do they even pretend that their motto is “Don’t be evil” these days?

Imgur seemed a likely candidate, but unfortunately there seemed to be no easy way to request non-album images, and no easy way to extract a direct link to the image contained in an album, and therefore no way to build thumbnail links. Drat.

Eventually I settled on Flickr, and I had to dust off an ancient Yahoo! email address to do so.

Build your own URL

The most perplexing thing about the Flickr API was that no direct link was provided in the data. Instead, provided are various pieces of data that must be manually pieced together, as their documentation explains:

You can construct the source URL to a photo once you know its ID, server ID, farm ID and secret, as returned by many API methods.

The URL takes the following format:

https://farm{farm-id}.staticflickr.com/{server-id}/{id}_{secret}.jpg
	or
https://farm{farm-id}.staticflickr.com/{server-id}/{id}_{secret}_[mstzb].jpg
	or
https://farm{farm-id}.staticflickr.com/{server-id}/{id}_{o-secret}_o.(jpg|gif|png)

I’m still not sure why they do it this way, but it wasn’t too hard to wire everything together from the raw API results.

A Series of Tubes

The verboseness of Go bit me a bit on this one, since although it makes decoding and encoding JSON values relatively easy via structs, I needed to work with three separate kinds of data structures: the incoming data from Flickr:

type ImageData struct {
	Id     string `json:"id"`
	Secret string `json:"secret"`
	Server string `json:"server"`
	Title  string `json:"title"`
	Farm   int    `json:"farm"`
}

The outgoing response given to my client:

type ImageResponse struct {
	Uri       string `json:"uri"`
	Thumbnail string `json:"thumbnail"`
	Text      string `json:"text"`
}

And the outgoing response for a “latest search” request:

type Search struct {
	Term string `json:"term"`
	When string `json:"when"`
}

Only ImageResponse truly needed a dedicated constructor, mostly to run through the URL construction hoops, but this got a bit wordy, especially once accomodating the need for array structures and functions to prettily print all of this. The entire thing could do with a decent refactor, since I’m fairly sure my String() string function is exactly the same for each structure.

It’s the Latest Show!

“Show the 10 most recent image searches” doesn’t seem like the kind of user story that really needs true data persistence, so I decided to just hold search history in a simple array that cuts off the oldest entry when it exceeds 10 entries.

This worked out just fine but is also when Heroku’s free tier really bit me too (I sense a pattern), since when Heroku sends the application to sleep, it flushes the memory. Any request sent to the server wakes it, but this effectively means that the search history is limited to the latest session.

Of course this could be avoided by paying $7/month to run this service non-stop, but I’m not there yet.

Room for Improvement

  • some serious refactoring to remove code duplication should/could be done
  • added parameters along with “offset” would be pretty easy to implement, perhaps one that sets the size of the thumbnail?
  • the original demo had a “context” field, although it wasn’t listed as a user story. Could I return something sensible in this case anyway? The owner of the picture’s profile?