2 # -*- coding: utf-8 -*-
3 # Simple HTTP web server for testing HTTP Authentication (see bug 1539)
4 # from our crappy-but-does-the-job department
5 # Thomas Perl <thp.io/about>; 2012-01-20
13 USERNAME
= 'user@example.com' # Username used for HTTP Authentication
14 PASSWORD
= 'secret' # Password used for HTTP Authentication
16 HOST
, PORT
= 'localhost', 8000 # Hostname and port for the HTTP server
18 # When the script contents change, the feed's episodes each get a new GUID
19 GUID
= hashlib
.sha1(open(__file__
).read()).hexdigest()
21 URL
= 'http://%(HOST)s:%(PORT)s' % locals()
23 FEEDNAME
= sys
.argv
[0] # The title of the RSS feed
24 FEEDFILE
= 'feed.rss' # The "filename" of the feed on the server
25 EPISODES
= 'episode' # Base name for the episode files
26 EPISODES_EXT
= '.mp3' # Extension for the episode files
27 EPISODES_MIME
= 'audio/mpeg' # Mime type for the episode files
28 EP_COUNT
= 7 # Number of episodes in the feed
29 SIZE
= 500000 # Size (in bytes) of the episode downloads)
31 def mkpubdates(items
):
32 """Generate fake pubDates (one each day, recently)"""
33 current
= datetime
.datetime
.now() - datetime
.timedelta(days
=items
+3)
34 for i
in range(items
):
36 current
+= datetime
.timedelta(days
=1)
38 def mkrss(items
=EP_COUNT
):
39 """Generate a dumm RSS feed with a given number of items"""
42 <title>Episode %(INDEX)s</title>
43 <guid>tag:test.gpodder.org,2012:%(GUID)s,%(URL)s,%(INDEX)s</guid>
44 <pubDate>%(PUBDATE)s</pubDate>
46 url="%(URL)s/%(EPISODES)s%(INDEX)s%(EPISODES_EXT)s"
47 type="%(EPISODES_MIME)s"
50 """ % dict(locals().items()+globals().items())
51 for INDEX
, PUBDATE
in enumerate(mkpubdates(items
)))
55 <channel><title>%(FEEDNAME)s</title><link>%(URL)s</link>
59 """ % dict(locals().items()+globals().items())
61 def mkdata(size
=SIZE
):
62 """Generate dummy data of a given size (in bytes)"""
63 return ''.join(chr(32+(i
%(127-32))) for i
in range(size
))
65 class AuthRequestHandler(BaseHTTPServer
.BaseHTTPRequestHandler
):
66 FEEDFILE_PATH
= '/%s' % FEEDFILE
67 EPISODES_PATH
= '/%s' % EPISODES
74 auth_header
= self
.headers
.get('authorization', '')
75 m
= re
.match(r
'^Basic (.*)$', auth_header
)
77 auth_data
= m
.group(1).decode('base64').split(':', 1)
78 if len(auth_data
) == 2:
79 username
, password
= auth_data
80 print 'Got username:', username
81 print 'Got password:', password
82 if (username
, password
) == (USERNAME
, PASSWORD
):
83 print 'Valid credentials provided.'
86 if self
.path
== self
.FEEDFILE_PATH
:
89 elif self
.path
.startswith(self
.EPISODES_PATH
):
90 print 'Episode request.'
94 print 'Not authorized - sending WWW-Authenticate header.'
95 self
.send_response(401)
96 self
.send_header('WWW-Authenticate',
97 'Basic realm="%s"' % sys
.argv
[0])
102 self
.send_response(200)
103 self
.send_header('Content-type',
104 'application/xml' if is_feed
else 'audio/mpeg')
106 self
.wfile
.write(mkrss() if is_feed
else mkdata())
110 if __name__
== '__main__':
111 httpd
= BaseHTTPServer
.HTTPServer((HOST
, PORT
), AuthRequestHandler
)
113 Feed URL: %(URL)s/%(FEEDFILE)s
114 Username: %(USERNAME)s
115 Password: %(PASSWORD)s
118 httpd
.handle_request()