~loggerhead-team/loggerhead/trunk-rich

« back to all changes in this revision

Viewing changes to loggerhead/controllers/download_ui.py

Merge the "don't run template on HEAD requests" branch.

This should stop us from getting OOPS during HEAD requests from haproxy
(bug #701329). It also should mean that at least most HEAD requests stop
returning body content (bug #716201), and that we perform less total work
to return HEAD info (bug #716217).

Show diffs side-by-side

added added

removed removed

Lines of Context:
19
19
 
20
20
import logging
21
21
import mimetypes
22
 
import time
23
 
 
24
 
import turbogears
25
 
from cherrypy import HTTPRedirect, response
26
 
 
 
22
import urllib
 
23
 
 
24
from paste import httpexceptions
 
25
from paste.request import path_info_pop
 
26
 
 
27
from loggerhead.controllers import TemplatedBranchView
27
28
 
28
29
log = logging.getLogger("loggerhead.controllers")
29
30
 
30
31
 
31
 
class DownloadUI (object):
32
 
 
33
 
    def __init__(self, branch):
34
 
        # BranchView object
35
 
        self._branch = branch
36
 
        self.log = branch.log
37
 
 
38
 
    @turbogears.expose()
39
 
    def default(self, *args, **kw):
 
32
class DownloadUI (TemplatedBranchView):
 
33
 
 
34
    def __call__(self, environ, start_response):
40
35
        # /download/<rev_id>/<file_id>/[filename]
41
 
        z = time.time()
42
 
        h = self._branch.get_history()
43
 
        
44
 
        h._branch.lock_read()
45
 
        try:
46
 
            if len(args) < 2:
47
 
                raise HTTPRedirect(self._branch.url('/changes'))
48
 
 
49
 
            revid = h.fix_revid(args[0])
50
 
            file_id = args[1]
51
 
            path, filename, content = h.get_file(file_id, revid)
52
 
            mime_type, encoding = mimetypes.guess_type(filename)
53
 
            if mime_type is None:
54
 
                mime_type = 'application/octet-stream'
55
 
 
56
 
            self.log.info('/download %s @ %s (%d bytes)', path, h.get_revno(revid), len(content))
57
 
            response.headers['Content-Type'] = mime_type
58
 
            response.headers['Content-Length'] = len(content)
59
 
            response.headers['Content-Disposition'] = 'attachment; filename=%s'%(filename,)
60
 
            response.body = content
61
 
            return response.body
62
 
        finally:
63
 
            h._branch.unlock()
 
36
 
 
37
        h = self._history
 
38
 
 
39
        args = []
 
40
        while True:
 
41
            arg = path_info_pop(environ)
 
42
            if arg is None:
 
43
                break
 
44
            args.append(arg)
 
45
 
 
46
        if len(args) < 2:
 
47
            raise httpexceptions.HTTPMovedPermanently(
 
48
                self._branch.absolute_url('/changes'))
 
49
 
 
50
        revid = h.fix_revid(args[0])
 
51
        file_id = args[1]
 
52
        path, filename, content = h.get_file(file_id, revid)
 
53
        mime_type, encoding = mimetypes.guess_type(filename)
 
54
        if mime_type is None:
 
55
            mime_type = 'application/octet-stream'
 
56
 
 
57
        self.log.info('/download %s @ %s (%d bytes)',
 
58
                      path,
 
59
                      h.get_revno(revid),
 
60
                      len(content))
 
61
        encoded_filename = urllib.quote(filename.encode('utf-8'))
 
62
        headers = [
 
63
            ('Content-Type', mime_type),
 
64
            ('Content-Length', str(len(content))),
 
65
            ('Content-Disposition',
 
66
             "attachment; filename*=utf-8''%s" % (encoded_filename,)),
 
67
            ]
 
68
        start_response('200 OK', headers)
 
69
        return [content]