~lutostag/ubuntu/trusty/maas/1.5.4+keystone

« back to all changes in this revision

Viewing changes to src/maastesting/httpd.py

  • Committer: Package Import Robot
  • Author(s): Andres Rodriguez
  • Date: 2013-03-04 11:49:44 UTC
  • mto: This revision was merged to the branch mainline in revision 25.
  • Revision ID: package-import@ubuntu.com-20130304114944-azcvu9anlf8mizpa
Tags: upstream-1.3+bzr1452+dfsg
ImportĀ upstreamĀ versionĀ 1.3+bzr1452+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
15
15
    ]
16
16
 
17
17
from BaseHTTPServer import HTTPServer
 
18
import gzip
 
19
from io import BytesIO
 
20
import os
18
21
from SimpleHTTPServer import SimpleHTTPRequestHandler
19
22
from SocketServer import ThreadingMixIn
20
23
import threading
31
34
    log_request = lambda *args, **kwargs: None
32
35
    log_error = lambda *args, **kwargs: None
33
36
 
 
37
    def _gzip_compress(self, f):
 
38
        gz_out = BytesIO()
 
39
        gz = gzip.GzipFile(mode='wb', fileobj=gz_out)
 
40
        gz.write(f.read())
 
41
        gz.flush()
 
42
        gz_out.getvalue()
 
43
        return gz_out
 
44
 
 
45
    def is_gzip_accepted(self):
 
46
        accepted = set()
 
47
        for header in self.headers.getallmatchingheaders('Accept-Encoding'):
 
48
            # getallmatchingheaders returns the whole line, so first we have to
 
49
            # split off the header definition
 
50
            _, content = header.split(':', 1)
 
51
            content = content.strip()
 
52
            # Then, you are allowed to specify a comma separated list of
 
53
            # acceptable encodings. You are also allowed to specify
 
54
            # 'encoding;q=XXX' to specify what encodings you would prefer.
 
55
            # We'll allow it to be set, but just ignore it.
 
56
            #   http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html
 
57
            encodings = [encoding.strip().split(';', )[0]
 
58
                         for encoding in content.split(',')]
 
59
            accepted.update(encodings)
 
60
        if 'gzip' in accepted:
 
61
            return True
 
62
        return False
 
63
 
 
64
    # This is a copy & paste and minor modification of
 
65
    # SimpleHTTPRequestHandler's send_head code. Because to support
 
66
    # Content-Encoding gzip, we have to change what headers get returned (as it
 
67
    # affects Content-Length headers.
 
68
    def send_head(self):
 
69
        """Common code for GET and HEAD commands.
 
70
 
 
71
        This sends the response code and MIME headers.
 
72
 
 
73
        Return value is either a file object (which has to be copied
 
74
        to the outputfile by the caller unless the command was HEAD,
 
75
        and must be closed by the caller under all circumstances), or
 
76
        None, in which case the caller has nothing further to do.
 
77
 
 
78
        """
 
79
        path = self.translate_path(self.path)
 
80
        f = None
 
81
        if os.path.isdir(path):
 
82
            if not self.path.endswith('/'):
 
83
                # redirect browser - doing basically what apache does
 
84
                self.send_response(301)
 
85
                self.send_header("Location", self.path + "/")
 
86
                self.end_headers()
 
87
                return None
 
88
            for index in "index.html", "index.htm":
 
89
                index = os.path.join(path, index)
 
90
                if os.path.exists(index):
 
91
                    path = index
 
92
                    break
 
93
            else:
 
94
                return self.list_directory(path)
 
95
        ctype = self.guess_type(path)
 
96
        try:
 
97
            # Always read in binary mode. Opening files in text mode may cause
 
98
            # newline translations, making the actual size of the content
 
99
            # transmitted *less* than the content-length!
 
100
            f = open(path, 'rb')
 
101
        except IOError:
 
102
            self.send_error(404, "File not found")
 
103
            return None
 
104
        if self.is_gzip_accepted():
 
105
            return self.start_gz_response(ctype, f)
 
106
        else:
 
107
            return self.start_response(ctype, f)
 
108
 
 
109
    def start_gz_response(self, ctype, f):
 
110
        self.send_response(200)
 
111
        self.send_header("Content-type", ctype)
 
112
        self.send_header("Content-Encoding", 'gzip')
 
113
        gz_out = self._gzip_compress(f)
 
114
        self.send_header("Content-Length", str(gz_out.tell()))
 
115
        gz_out.seek(0)
 
116
        self.end_headers()
 
117
        return gz_out
 
118
 
 
119
    def start_response(self, ctype, f):
 
120
        self.send_response(200)
 
121
        self.send_header("Content-type", ctype)
 
122
        fs = os.fstat(f.fileno())
 
123
        self.send_header("Content-Length", str(fs[6]))
 
124
        self.send_header("Last-Modified", self.date_time_string(fs.st_mtime))
 
125
        self.end_headers()
 
126
        return f
 
127
 
34
128
 
35
129
class HTTPServerFixture(Fixture):
36
130
    """Bring up a very simple, threaded, web server.