From ee94be04ff10037c71b1aeb12473e40cd7d598a8 Mon Sep 17 00:00:00 2001 From: Milo Casagrande Date: Wed, 17 Apr 2013 11:26:32 +0200 Subject: Use X-Sendfile for all requests. * Not all requests were served with X-Sendfile, only few of them. * Guess mime type and encoding, and fallback in case. --- rhodecode/lib/middleware/pygrack.py | 60 ++++++++++++++++++------------------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/rhodecode/lib/middleware/pygrack.py b/rhodecode/lib/middleware/pygrack.py index a2fabad8..a70ed420 100644 --- a/rhodecode/lib/middleware/pygrack.py +++ b/rhodecode/lib/middleware/pygrack.py @@ -3,6 +3,7 @@ import socket import logging import subprocess import traceback +import mimetypes from webob import Request, Response, exc @@ -73,24 +74,24 @@ class GitRepository(object): """ resp = Response() - resp.charset = None if self.dumb: log.debug('Using dumb HTTP git protocol') git_path = self._get_fixedpath(request.path_info) filename = os.path.join(self.content_path, git_path) + mime_type, encoding = mimetypes.guess_type(filename) + if os.path.isfile(filename): resp.content_disposition = ('attachment; filename="%s"' % os.path.basename(filename)) - resp.content_type = 'application/octet-stream' + resp.content_type = mime_type or 'application/octet-stream' + resp.charset = encoding or 'binary' resp.headers = {'X-Sendfile': - (os.path.abspath(filename)).encode('utf-8')} + (os.path.abspath(filename)).encode('utf8')} resp.status = 200 else: log.info("File not found: %s" % git_path) - resp.content_type = 'text/html' resp.status = 404 - resp.app_iter = ['', ] else: log.debug('Using smart HTTP git protocol') git_command = request.GET.get('service') @@ -109,7 +110,7 @@ class GitRepository(object): try: out = subprocessio.SubprocessIOChunker( r'git %s --stateless-rpc --advertise-refs "%s"' % ( - git_command[4:], self.content_path), + git_command[4:], self.content_path), starting_values=[ packet_len + server_advert + '0000' ] @@ -118,6 +119,7 @@ class GitRepository(object): log.error(traceback.format_exc()) raise exc.HTTPExpectationFailed() + resp.charset = None resp.content_type = ('application/x-%s-advertisement' % str(git_command)) resp.status = 200 @@ -133,21 +135,25 @@ class GitRepository(object): response to stdout """ git_command = self._get_fixedpath(request.path_info) + resp = Response() + if self.dumb: + log.debug('Using dumb HTTP git protocol') filename = os.path.join(self.content_path, git_command) + git_path = self._get_fixedpath(request.path_info) + mime_type, encoding = mimetypes.guess_type(filename) - if os.path.isfile(filename): - out = open(filename) - content_type = 'text/plain' - content_length = os.path.getsize(filename) - status = 200 + if os.path.isfile(filename): + resp.content_disposition = ('attachment; filename="%s"' % + os.path.basename(filename)) + resp.content_type = mime_type or 'application/octet-stream' + resp.charset = encoding or 'binary' + resp.headers = {'X-Sendfile': + (os.path.abspath(filename)).encode('utf8')} + resp.status = 200 else: - log.info("File not found: %s" % git_command) - content_type = 'text/html' - content_length = 0 - status = 404 - out = ['', ] - #raise exc.HTTPExpectationFailed() + log.info("File not found: %s" % git_path) + resp.status = 404 else: if git_command not in self.commands: log.debug('command %s not allowed' % git_command) @@ -155,7 +161,7 @@ class GitRepository(object): if 'CONTENT_LENGTH' in environ: inputstream = FileWrapper(environ['wsgi.input'], - request.content_length) + request.content_length) else: inputstream = environ['wsgi.input'] @@ -170,7 +176,7 @@ class GitRepository(object): cwd=os.getcwd() ) cmd = r'git %s --stateless-rpc "%s"' % (git_command[4:], - self.content_path), + self.content_path), log.debug('handling cmd %s' % cmd) out = subprocessio.SubprocessIOChunker( cmd, @@ -181,25 +187,19 @@ class GitRepository(object): log.error(traceback.format_exc()) raise exc.HTTPExpectationFailed() - content_type = 'application/x-%s-result' % git_command.encode('utf8') - content_length = 0 - status = 200 + resp.content_type = 'application/x-%s-result' % git_command.encode('utf8') + resp.status = 200 + resp.charset = None + resp.app_iter = out if git_command in [u'git-receive-pack']: # updating refs manually after each push. # Needed for pre-1.7.0.4 git clients using regular HTTP mode. cmd = (u'git --git-dir "%s" ' - 'update-server-info' % self.content_path) + 'update-server-info' % self.content_path) log.debug('handling cmd %s' % cmd) subprocess.call(cmd, shell=True) - resp = Response() - resp.content_type = content_type - if content_length > 0: - resp.content_length = content_length - resp.status = status - resp.charset = None - resp.app_iter = out return resp def __call__(self, environ, start_response): -- cgit v1.2.3