Writing my Python Marvel API Wrapper Part 2: Requests

This post is part of the series Writing my Python Marvel API Wrapper

Other posts in this series:

  1. Writing my Python Marvel API Wrapper Part 1: Structure
  2. Writing my Python Marvel API Wrapper Part 2: Requests (Current)
  3. Writing my Python Marvel API Wrapper Part 3: Refactor

With my structure largely in place I was now ready to add functionality.

To make things a little easier on me, I’ve decided to use the wonderful Requests Python library. It makes it significantly easier to make requests and handle responses, because it does all the heavy lifting for you.

Discoveries

I quickly discovered there’s more to making these requests than that. Because I’m technically building an app, I’m required to also send along a few other things:

  • A unique identifier, like a timestamp
  • An MD5 hash of the API key, private key, and timestamp

Luckily, Python has built in date and encoding libraries so tacking on these extra requirements is pretty straight forward:

import hashlib
import time

It also means we’ll need to adjust our main object so that it can accept the private key that is provided by Marvel.

class MarvelAPIObject(object):
  BASE_URL = "http://gateway.marvel.com/v1/public"
	
  def __init__(self, apikey=None, privkey=None):
    self.API_KEY = apikey
    self.PRIV_KEY = privkey

I’ve placed my hash generator in a separate method, to make it easy to re-use. Which looks something like this:

def getHash(self, ts, priv_key, pub_key):
  return hashlib.md5(ts+priv_key+pub_key).hexdigest()

The main reason I’m not generating the timestamp in this function is because the timestamp also needs to be sent along with the API request. As such, it needs to be the exact same and it’s easier to deal with by simply generating it where I also create the URL.

Building the request URL

def getList(self, args):
  request_url = self.API_URL + '?apikey=%s' % self.API_KEY
  ts = str(time.time())

    request_url += '&ts=%s' % ts
    request_url += '&hash=%s' % self.getHash(ts, self.PRIV_KEY, self.API_KEY)

    for arg in args:
      request_url += "&%s=%s" % (arg, args[arg])

    return requests.get(request_url)

There are a few things to note here. As mentioned before, I’m generating the timestamp in this method so that I can easily append it and use it in the hash generator.

I’m also going through the arguments and simply appending the key:value pairs to the URL. As a future improvement I’d probably need to make sure that they are valid to avoid exploits of some sort.

And finally, it’s simply returning whatever the response is of the request. This means that you get a request object that will have a status code and response text for you to handle. If everything went well, your response text will be JSON and the status code will be 200.

Next: Refactor, refactor, refactor

At this point you may have already noticed that we’ve got all these methods that do the exact same thing and only differ slightly in their endpoints.

While the application works in this state, it’s probably a good idea to start refactoring the code and rip out all the repetition to make this thing easier to maintain in the future.

This will be an undertaking that I’ll describe in a future post. Until then, feel free to fork my stuff on Github or let me know what you think so far either by filling out this form or passing me a message on Twitter.

Continue reading this series: