Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add HTTP authentication test tool (bug 1539)
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
Showing
1 changed file
with
119 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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() | ||
|