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

Last change on this file since 1260 was 1260, checked in by crchemist, 15 years ago

added cfg to known file extensions

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