source: products/quintagroup.distrpoxy/trunk/quintagroup/distproxy/wsgi.py @ 1082

Last change on this file since 1082 was 1082, checked in by koval, 15 years ago

added static wsgi application with folder listings

  • Property svn:eol-style set to native
File size: 5.3 KB
Line 
1import os
2import socket
3import sys
4from paste.script.appinstall import Installer as BaseInstaller
5from paste.fileapp import FileApp
6from paste import urlparser
7from paste import request
8from paste.httpexceptions import HTTPNotFound
9from spider import webmirror
10
11class PackageProxyApp(object):
12
13    def __init__(self, index_url=None, pack_dir=None):
14        if not index_url: 
15            print "No repository index provided"
16            sys.exit()
17        if not pack_dir:
18            print "No packages cache directory provided"
19            sys.exit()
20        if not os.path.isdir(pack_dir):
21            print 'You must create the %r directory' % pack_dir
22            sys.exit()
23        self.index_url = index_url
24        self.pack_dir = pack_dir
25
26    def __call__(self, environ, start_response):
27        path = environ.get('PATH_INFO', '').strip()
28        if path.split('/')[1] == "favicon.ico":
29            return HTTPNotFound()(environ, start_response)
30        filename = self.checkCache(path)
31        if filename is None:
32            return HTTPNotFound()(environ, start_response)
33        return FileApp(filename)(environ, start_response)
34
35    def checkCache(self, path):   
36        pth = self.pack_dir + path
37        pth1 = pth
38        if not (path[-3:] in ['tgz','.gz','egg','zip','exe']): 
39            pth1 = pth + 'index.html'
40        else:
41            pth = '/'.join(pth.split('/')[:-1])
42        if not os.path.exists(pth1):
43            webmirror(pth,1,self.index_url+path,0,1)
44        if pth1:
45            return pth1
46        return pth
47
48def app_factory(global_config, **local_conf):
49    # Grab config from wsgi .ini file. If not specified, config.py's values
50    # take over.
51    pack_dir = local_conf.get('pack_directory', None)
52    index_url = local_conf.get('index', None)
53    return PackageProxyApp(index_url, pack_dir)
54
55class StaticURLParser(urlparser.StaticURLParser):
56
57    def __call__(self, environ, start_response):
58        path_info = environ.get('PATH_INFO', '')
59        if not path_info:
60            return self.add_slash(environ, start_response)
61        if path_info == '/':
62            # @@: This should obviously be configurable
63            filename = 'index.html'
64        else:
65            filename = request.path_info_pop(environ)
66        full = os.path.normcase(os.path.normpath(
67            os.path.join(self.directory, filename)))
68        if os.path.sep != '/':
69            full = full.replace('/', os.path.sep)
70        if self.root_directory is not None and not full.startswith(self.root_directory):
71            # Out of bounds
72            return self.not_found(environ, start_response)
73        if not os.path.exists(full):
74            if full.endswith('index.html') and not os.path.isfile(full):
75                start_response('200 OK', [])
76                return [self.get_index_html()]
77            return self.not_found(environ, start_response)
78        if os.path.isdir(full):
79            # @@: Cache?
80            child_root = self.root_directory is not None and \
81                self.root_directory or self.directory
82            return self.__class__(full, root_directory=child_root,
83                                  cache_max_age=self.cache_max_age)(environ,
84                                                                   start_response)
85        if environ.get('PATH_INFO') and environ.get('PATH_INFO') != '/':
86            return self.error_extra_path(environ, start_response)
87        if_none_match = environ.get('HTTP_IF_NONE_MATCH')
88        if if_none_match:
89            mytime = os.stat(full).st_mtime
90            if str(mytime) == if_none_match:
91                headers = []
92                ETAG.update(headers, mytime)
93                start_response('304 Not Modified', headers)
94                return [''] # empty body
95
96        fa = self.make_app(full)
97        if self.cache_max_age:
98            fa.cache_control(max_age=self.cache_max_age)
99        return fa(environ, start_response)
100
101    def get_index_html(self):
102        path = self.directory
103        # create sorted lists of directories and files
104        names = os.listdir(path)
105        dirs = [i for i in names if os.path.isdir(os.path.join(path, i))]
106        dirs.sort()
107        files = [i for i in names if os.path.isfile(os.path.join(path, i))]
108        files.sort()
109        names = dirs + files
110        links = '\n'.join(['<li><a href="%s">%s</a></li>' %  (i, i) for i in names])
111        template = open(os.path.join(os.path.dirname(__file__), 'index.html')).read()
112        return template % {'path': path[len(self.root_directory):], 'links': links}
113
114def make_static(global_conf, document_root, cache_max_age=None):
115    """
116    Return a WSGI application that serves a directory (configured
117    with document_root)
118
119    cache_max_age - integer specifies CACHE_CONTROL max_age in seconds
120    """
121    if cache_max_age is not None:
122        cache_max_age = int(cache_max_age)
123    return StaticURLParser(
124        document_root, cache_max_age=cache_max_age)
125
126
127"""
128class Installer(BaseInstaller):
129    use_cheetah = False
130    config_file = 'deployment.ini_tmpl'
131
132    def config_content(self, command, vars):
133        import pkg_resources
134        module = 'collective.eggproxy'
135        if pkg_resources.resource_exists(module, self.config_file):
136            return self.template_renderer(
137                pkg_resources.resource_string(module, self.config_file),
138                vars,
139                filename=self.config_file)
140"""
Note: See TracBrowser for help on using the repository browser.