13257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel"""Simple HTTP Server.
23257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
33257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielThis module builds on BaseHTTPServer by implementing the standard GET
43257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanieland HEAD requests in a fairly straightforward manner.
53257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
63257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel"""
73257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
83257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
93257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel__version__ = "0.6"
103257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
113257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel__all__ = ["SimpleHTTPRequestHandler"]
123257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
133257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielimport os
143257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielimport posixpath
153257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielimport BaseHTTPServer
163257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielimport urllib
173257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielimport urlparse
183257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielimport cgi
193257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielimport sys
203257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielimport shutil
213257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielimport mimetypes
223257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanieltry:
233257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    from cStringIO import StringIO
243257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielexcept ImportError:
253257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    from StringIO import StringIO
263257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
273257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
283257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielclass SimpleHTTPRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler):
293257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
303257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    """Simple HTTP request handler with GET and HEAD commands.
313257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
323257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    This serves files from the current directory and any of its
333257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    subdirectories.  The MIME type for files is determined by
343257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    calling the .guess_type() method.
353257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
363257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    The GET and HEAD requests are identical except that the HEAD
373257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    request omits the actual contents of the file.
383257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
393257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    """
403257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
413257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    server_version = "SimpleHTTP/" + __version__
423257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
433257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def do_GET(self):
443257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        """Serve a GET request."""
453257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        f = self.send_head()
463257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if f:
473257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            try:
483257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                self.copyfile(f, self.wfile)
493257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            finally:
503257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                f.close()
513257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
523257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def do_HEAD(self):
533257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        """Serve a HEAD request."""
543257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        f = self.send_head()
553257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if f:
563257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            f.close()
573257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
583257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def send_head(self):
593257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        """Common code for GET and HEAD commands.
603257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
613257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        This sends the response code and MIME headers.
623257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
633257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        Return value is either a file object (which has to be copied
643257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        to the outputfile by the caller unless the command was HEAD,
653257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        and must be closed by the caller under all circumstances), or
663257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        None, in which case the caller has nothing further to do.
673257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
683257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        """
693257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        path = self.translate_path(self.path)
703257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        f = None
713257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if os.path.isdir(path):
723257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            parts = urlparse.urlsplit(self.path)
733257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            if not parts.path.endswith('/'):
743257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                # redirect browser - doing basically what apache does
753257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                self.send_response(301)
763257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                new_parts = (parts[0], parts[1], parts[2] + '/',
773257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                             parts[3], parts[4])
783257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                new_url = urlparse.urlunsplit(new_parts)
793257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                self.send_header("Location", new_url)
803257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                self.end_headers()
813257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                return None
823257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            for index in "index.html", "index.htm":
833257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                index = os.path.join(path, index)
843257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                if os.path.exists(index):
853257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                    path = index
863257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                    break
873257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            else:
883257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                return self.list_directory(path)
893257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        ctype = self.guess_type(path)
903257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        try:
913257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            # Always read in binary mode. Opening files in text mode may cause
923257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            # newline translations, making the actual size of the content
933257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            # transmitted *less* than the content-length!
943257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            f = open(path, 'rb')
953257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        except IOError:
963257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            self.send_error(404, "File not found")
973257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            return None
983257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        try:
993257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            self.send_response(200)
1003257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            self.send_header("Content-type", ctype)
1013257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            fs = os.fstat(f.fileno())
1023257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            self.send_header("Content-Length", str(fs[6]))
1033257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            self.send_header("Last-Modified", self.date_time_string(fs.st_mtime))
1043257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            self.end_headers()
1053257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            return f
1063257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        except:
1073257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            f.close()
1083257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            raise
1093257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
1103257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def list_directory(self, path):
1113257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        """Helper to produce a directory listing (absent index.html).
1123257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
1133257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        Return value is either a file object, or None (indicating an
1143257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        error).  In either case, the headers are sent, making the
1153257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        interface the same as for send_head().
1163257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
1173257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        """
1183257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        try:
1193257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            list = os.listdir(path)
1203257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        except os.error:
1213257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            self.send_error(404, "No permission to list directory")
1223257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            return None
1233257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        list.sort(key=lambda a: a.lower())
1243257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        f = StringIO()
1253257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        displaypath = cgi.escape(urllib.unquote(self.path))
1263257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        f.write('<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">')
1273257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        f.write("<html>\n<title>Directory listing for %s</title>\n" % displaypath)
1283257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        f.write("<body>\n<h2>Directory listing for %s</h2>\n" % displaypath)
1293257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        f.write("<hr>\n<ul>\n")
1303257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        for name in list:
1313257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            fullname = os.path.join(path, name)
1323257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            displayname = linkname = name
1333257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            # Append / for directories or @ for symbolic links
1343257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            if os.path.isdir(fullname):
1353257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                displayname = name + "/"
1363257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                linkname = name + "/"
1373257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            if os.path.islink(fullname):
1383257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                displayname = name + "@"
1393257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                # Note: a link to a directory displays with @ and links with /
1403257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            f.write('<li><a href="%s">%s</a>\n'
1413257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel                    % (urllib.quote(linkname), cgi.escape(displayname)))
1423257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        f.write("</ul>\n<hr>\n</body>\n</html>\n")
1433257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        length = f.tell()
1443257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        f.seek(0)
1453257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        self.send_response(200)
1463257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        encoding = sys.getfilesystemencoding()
1473257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        self.send_header("Content-type", "text/html; charset=%s" % encoding)
1483257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        self.send_header("Content-Length", str(length))
1493257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        self.end_headers()
1503257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        return f
1513257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
1523257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def translate_path(self, path):
1533257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        """Translate a /-separated PATH to the local filename syntax.
1543257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
1553257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        Components that mean special things to the local file system
1563257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        (e.g. drive or directory names) are ignored.  (XXX They should
1573257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        probably be diagnosed.)
1583257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
1593257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        """
1603257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        # abandon query parameters
1613257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        path = path.split('?',1)[0]
1623257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        path = path.split('#',1)[0]
1633257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        # Don't forget explicit trailing slash when normalizing. Issue17324
1643257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        trailing_slash = path.rstrip().endswith('/')
1653257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        path = posixpath.normpath(urllib.unquote(path))
1663257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        words = path.split('/')
1673257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        words = filter(None, words)
1683257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        path = os.getcwd()
1693257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        for word in words:
1703257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            drive, word = os.path.splitdrive(word)
1713257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            head, word = os.path.split(word)
1723257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            if word in (os.curdir, os.pardir): continue
1733257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            path = os.path.join(path, word)
1743257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if trailing_slash:
1753257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            path += '/'
1763257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        return path
1773257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
1783257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def copyfile(self, source, outputfile):
1793257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        """Copy all data between two file objects.
1803257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
1813257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        The SOURCE argument is a file object open for reading
1823257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        (or anything with a read() method) and the DESTINATION
1833257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        argument is a file object open for writing (or
1843257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        anything with a write() method).
1853257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
1863257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        The only reason for overriding this would be to change
1873257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        the block size or perhaps to replace newlines by CRLF
1883257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        -- note however that this the default server uses this
1893257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        to copy binary data as well.
1903257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
1913257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        """
1923257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        shutil.copyfileobj(source, outputfile)
1933257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
1943257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    def guess_type(self, path):
1953257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        """Guess the type of a file.
1963257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
1973257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        Argument is a PATH (a filename).
1983257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
1993257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        Return value is a string of the form type/subtype,
2003257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        usable for a MIME Content-type header.
2013257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
2023257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        The default implementation looks the file's extension
2033257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        up in the table self.extensions_map, using application/octet-stream
2043257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        as a default; however it would be permissible (if
2053257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        slow) to look inside the data to make a better guess.
2063257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
2073257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        """
2083257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
2093257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        base, ext = posixpath.splitext(path)
2103257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if ext in self.extensions_map:
2113257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            return self.extensions_map[ext]
2123257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        ext = ext.lower()
2133257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        if ext in self.extensions_map:
2143257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            return self.extensions_map[ext]
2153257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        else:
2163257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel            return self.extensions_map['']
2173257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
2183257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    if not mimetypes.inited:
2193257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        mimetypes.init() # try to read system mime.types
2203257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    extensions_map = mimetypes.types_map.copy()
2213257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    extensions_map.update({
2223257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        '': 'application/octet-stream', # Default
2233257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        '.py': 'text/plain',
2243257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        '.c': 'text/plain',
2253257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        '.h': 'text/plain',
2263257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel        })
2273257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
2283257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
2293257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanieldef test(HandlerClass = SimpleHTTPRequestHandler,
2303257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel         ServerClass = BaseHTTPServer.HTTPServer):
2313257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    BaseHTTPServer.test(HandlerClass, ServerClass)
2323257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
2333257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel
2343257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDanielif __name__ == '__main__':
2353257aa99321d745773a6bd1bd4ce7f6fafe74411Daryl McDaniel    test()
236