Skip to content

Commit

Permalink
Add HTTP authentication test tool (bug 1539)
Browse files Browse the repository at this point in the history
The test-auth-server.py tool allows you to start a
web server that serves a podcast feed (plus episodes).

This can be used to debug the HTTP authentication
mechanism of gPodder for feed updates and episodes.

See http://gpodder.org/bug/1539 for details.
  • Loading branch information
thp committed Jan 20, 2012
1 parent 08f9190 commit dba5a21
Showing 1 changed file with 119 additions and 0 deletions.
119 changes: 119 additions & 0 deletions tools/test-auth-server.py
@@ -0,0 +1,119 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# Simple HTTP web server for testing HTTP Authentication (see bug 1539)
# from our crappy-but-does-the-job department
# Thomas Perl <thp.io/about>; 2012-01-20

import BaseHTTPServer
import sys
import re
import hashlib
import datetime

USERNAME = 'user@example.com' # Username used for HTTP Authentication
PASSWORD = 'secret' # Password used for HTTP Authentication

HOST, PORT = 'localhost', 8000 # Hostname and port for the HTTP server

# When the script contents change, the feed's episodes each get a new GUID
GUID = hashlib.sha1(open(__file__).read()).hexdigest()

URL = 'http://%(HOST)s:%(PORT)s' % locals()

FEEDNAME = sys.argv[0] # The title of the RSS feed
FEEDFILE = 'feed.rss' # The "filename" of the feed on the server
EPISODES = 'episode' # Base name for the episode files
EPISODES_EXT = '.mp3' # Extension for the episode files
EPISODES_MIME = 'audio/mpeg' # Mime type for the episode files
EP_COUNT = 7 # Number of episodes in the feed
SIZE = 500000 # Size (in bytes) of the episode downloads)

def mkpubdates(items):
"""Generate fake pubDates (one each day, recently)"""
current = datetime.datetime.now() - datetime.timedelta(days=items+3)
for i in range(items):
yield current.ctime()
current += datetime.timedelta(days=1)

def mkrss(items=EP_COUNT):
"""Generate a dumm RSS feed with a given number of items"""
ITEMS = '\n'.join("""
<item>
<title>Episode %(INDEX)s</title>
<guid>tag:test.gpodder.org,2012:%(GUID)s,%(URL)s,%(INDEX)s</guid>
<pubDate>%(PUBDATE)s</pubDate>
<enclosure
url="%(URL)s/%(EPISODES)s%(INDEX)s%(EPISODES_EXT)s"
type="%(EPISODES_MIME)s"
length="%(SIZE)s"/>
</item>
""" % dict(locals().items()+globals().items())
for INDEX, PUBDATE in enumerate(mkpubdates(items)))

return """
<rss>
<channel><title>%(FEEDNAME)s</title><link>%(URL)s</link>
%(ITEMS)s
</channel>
</rss>
""" % dict(locals().items()+globals().items())

def mkdata(size=SIZE):
"""Generate dummy data of a given size (in bytes)"""
return ''.join(chr(32+(i%(127-32))) for i in range(size))

class AuthRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
FEEDFILE_PATH = '/%s' % FEEDFILE
EPISODES_PATH = '/%s' % EPISODES

def do_GET(self):
authorized = False
is_feed = False
is_episode = False

auth_header = self.headers.get('authorization', '')
m = re.match(r'^Basic (.*)$', auth_header)
if m is not None:
auth_data = m.group(1).decode('base64').split(':', 1)
if len(auth_data) == 2:
username, password = auth_data
print 'Got username:', username
print 'Got password:', password
if (username, password) == (USERNAME, PASSWORD):
print 'Valid credentials provided.'
authorized = True

if self.path == self.FEEDFILE_PATH:
print 'Feed request.'
is_feed = True
elif self.path.startswith(self.EPISODES_PATH):
print 'Episode request.'
is_episode = True

if not authorized:
print 'Not authorized - sending WWW-Authenticate header.'
self.send_response(401)
self.send_header('WWW-Authenticate',
'Basic realm="%s"' % sys.argv[0])
self.end_headers()
self.wfile.close()
return

self.send_response(200)
self.send_header('Content-type',
'application/xml' if is_feed else 'audio/mpeg')
self.end_headers()
self.wfile.write(mkrss() if is_feed else mkdata())
self.wfile.close()


if __name__ == '__main__':
httpd = BaseHTTPServer.HTTPServer((HOST, PORT), AuthRequestHandler)
print """
Feed URL: %(URL)s/%(FEEDFILE)s
Username: %(USERNAME)s
Password: %(PASSWORD)s
""" % locals()
while True:
httpd.handle_request()

0 comments on commit dba5a21

Please sign in to comment.