ebb34f173900d8fd9c2ba12d47adbbccb9a57b8c
[quix0rs-apt-p2p.git] / apt_dht / HTTPServer.py
1 import os.path, time
2
3 from twisted.python import log
4 from twisted.internet import defer
5 from twisted.web2 import server, http, resource, channel
6 from twisted.web2 import static, http_headers, responsecode
7
8 class FileDownloader(static.File):
9     
10     def __init__(self, path, manager, defaultType="text/plain", ignoredExts=(), processors=None, indexNames=None):
11         self.manager = manager
12         super(FileDownloader, self).__init__(path, defaultType, ignoredExts, processors, indexNames)
13         
14     def renderHTTP(self, req):
15         log.msg('Got request for %s from %s' % (req.uri, req.remoteAddr))
16         resp = super(FileDownloader, self).renderHTTP(req)
17         if isinstance(resp, defer.Deferred):
18             resp.addCallback(self._renderHTTP_done, req)
19         else:
20             resp = self._renderHTTP_done(resp, req)
21         return resp
22         
23     def _renderHTTP_done(self, resp, req):
24         log.msg('Initial response to %s: %r' % (req.uri, resp))
25         
26         if self.manager:
27             path = 'http:/' + req.uri
28             if resp.code >= 200 and resp.code < 400:
29                 return self.manager.check_freshness(path, resp.headers.getHeader('Last-Modified'), resp)
30             
31             log.msg('Not found, trying other methods for %s' % req.uri)
32             return self.manager.get_resp(path)
33         
34         return resp
35
36     def createSimilarFile(self, path):
37         return self.__class__(path, self.manager, self.defaultType, self.ignoredExts,
38                               self.processors, self.indexNames[:])
39         
40         
41 class TopLevel(resource.Resource):
42     addSlash = True
43     
44     def __init__(self, directory, manager):
45         self.directory = directory
46         self.manager = manager
47         self.subdirs = []
48
49     def addDirectory(self, directory):
50         assert directory
51         try:
52             idx = self.subdirs.index(directory)
53         except ValueError:
54             idx = len(self.subdirs)
55             self.subdirs.append(directory)
56         path = "~" + str(idx)
57         return path
58     
59     def removeDirectory(self, directory):
60         loc = self.subdirs.index(directory)
61         self.subdirs[loc] = ''
62         
63     def render(self, ctx):
64         return http.Response(
65             200,
66             {'content-type': http_headers.MimeType('text', 'html')},
67             """<html><body>
68             <h2>Statistics</h2>
69             <p>TODO: eventually some stats will be shown here.</body></html>""")
70
71     def locateChild(self, request, segments):
72         name = segments[0]
73         if len(name) > 1 and name[0] == '~':
74             try:
75                 loc = int(name[1:])
76             except:
77                 log.msg('Not found: %s from %s' % (request.uri, request.remoteAddr))
78                 return None, ()
79             
80             if loc >= 0 and loc < len(self.subdirs) and self.subdirs[loc]:
81                 log.msg('Sharing %s with %s' % (request.uri, request.remoteAddr))
82                 return static.File(self.subdirs[loc]), segments[1:]
83             else:
84                 log.msg('Not found: %s from %s' % (request.uri, request.remoteAddr))
85                 return None, ()
86         
87         if request.remoteAddr.host != "127.0.0.1":
88             log.msg('Blocked illegal access to %s from %s' % (request.uri, request.remoteAddr))
89             return None, ()
90             
91         if len(name) > 1:
92             return FileDownloader(self.directory, self.manager), segments[0:]
93         else:
94             return self, ()
95         
96 if __name__ == '__builtin__':
97     # Running from twistd -y
98     t = TopLevel('/home', None)
99     t.addDirectory('/tmp')
100     t.addDirectory('/var/log')
101     site = server.Site(t)
102     
103     # Standard twisted application Boilerplate
104     from twisted.application import service, strports
105     application = service.Application("demoserver")
106     s = strports.service('tcp:18080', channel.HTTPFactory(site))
107     s.setServiceParent(application)