Announcing tinyLinkFeed — RSS feeds for links posted to Twitter

I’ve come to enjoy the link-sharing that happens on Twitter, but a few months back I found myself with less time to regularly scan my Twitter stream.

Since I don’t always need real-time links, devising a mechanism to time-shift, and read at my leisure, seemed appropriate. Furthermore, since I don’t mind following friend’s del.icio.us feeds with a feed reader, converting tweets-with-links into RSS feeds seemed like a natural fit. After some brainstorming with @karllong and a bit of hacking, tinyLinkFeed was born!

tinyLinkFeed is designed to aggregate microblogging streams (like Twitter), and expose RSS feeds for posts containing URLs. To make the feeds a bit more useful, tinyLinkFeed also resolves shortened URLs, so you know what you’re linking to. (The URL un-shortening is done by another webservice I wrote at the same time, called tinyexpander; but I’ll save those details for another post.)

Using tinyLinkFeed is pretty straight-forward. For example, my normal Twitter page can be found at http://twitter.com/smartt, so my tinyLinkFeed page lives at http://www.tinylinkfeed.com/twitter/smartt. To follow the links I post to Twitter, you’d point your RSS reader to http://www.tinylinkfeed.com/feed/twitter/smartt.xml. For something perhaps more useful, you might try Tim O’Reilly’s link feed: http://www.tinylinkfeed.com/feed/twitter/timoreilly.xml (which is actually one of the main reasons I wrote tinyLinkFeed.)

The application came together fairly quick (it’s written in Python and runs on Google App Engine), though I haven’t had time to expand it since launch. I have a few ideas on what to add next, but I’m setting up getSatisfaction so you can leave ideas as well.

Adding profiles to tinyLinkFeed’s aggregator isn’t openly available yet, so if you’d like a profile added, drop a message to @smartt or @tinylinkfeed. I hope you find it useful!

Detecting whether your code is running on App Engine servers, or in development

For one of my projects running on Google App Engine, I’m using Google Analytics to track traffic, but I didn’t want the tracking code showing up in my local development environment. Fortunately, detecting where your code is running is easy.

Take a look at this sample:

import os

try:
  is_dev = os.environ['SERVER_SOFTWARE'].startswith('Dev')
except:
  is_dev = False
  
is_prod = not(is_dev)

If the is_dev and is_prod variables are exposed to your templates, you can do something like this:

{% if is_prod %}
 {% include "analytics.html" %}
{% endif %}

Hope this helps!

How-To: Dynamic WWW-Authentication (.htaccess style) on Google App Engine

Sometimes classic Basic Access Authentication is the right approach to password protecting a webpage. It’s not secure from sniffing, but functional if you’re just trying to ward off the casual surfer in the wrong spot. (For example, restricting access to your cat pictures, not your missile silo codes.)

Basic authentication is often added to sites (or directories) using a .htaccess file and something like this:

AuthUserFile /home/foo/.htpasswd
AuthName "Private Area"
AuthType Basic

<Limit GET>
require valid-user
</Limit>

…but you can also do basic authentication on-the-fly by reading/writing HTTP Headers. To ask the browser for a user/password, you can raise a 401 error, and write a “www-Authenticate” header containing something like ‘Basic realm=”Secure Area”‘. To read the user/password, look for an Authorization header, grab it’s value, Base 64 decode it, and you should have a string in the form of “user:password”.

Here’s how you might handle it with Google App Engine. (Well, really you might use a decorator.. but this example is easier to explain.)

class AuthTest(webapp.RequestHandler):
  def get(self):

    # Wrapping in a huge try/except isn't the best approach. This is just 
    # an example for how you might do this.
    try:
      # Parse the header to extract a user/password combo.
      # We're expecting something like "Basic XZxgZRTpbjpvcGVuIHYlc4FkZQ=="
      auth_header = self.request.headers['Authorization']

      # Isolate the encoded user/passwd and decode it
      auth_parts = auth_header.split(' ')
      user_pass_parts = base64.b64decode(auth_parts[1]).split(':')
      user_arg = user_pass_parts[0]
      pass_arg = user_pass_parts[1]
    
      checkAuth(user_arg, pass_arg) # have this call raise an exception if it fails

      self.response.out.write(template.render('templates/foo.html', {}))

    except Exception, e:
      logging.debug("AuthTest Exception: %s" % (e))

      # Here's how you set the headers requesting the browser to prompt
      # for a user/password:
      self.response.set_status(401, message="Authorization Required")
      self.response.headers['WWW-Authenticate'] = 'Basic realm="Secure Area"'

      # Rendering a 401 Error page is a good way to go...
      self.response.out.write(template.render('templates/error/401.html', {}))

That’s all there is to it.

If you want to programatically write an Authorization header (as in, sending authentication credentials to another site, like the Twitter API’s, for example) you’ll do something like this:

request = urllib2.Request(url)
request.add_header('Authorization', "Basic %s" % (base64.b64encode("%s:%s" % (user, password))))

Enjoy!