Mercurial > cpython-lru_cache-weakref
annotate Lib/SimpleHTTPServer.py @ 6719:faebc1940432 legacy-trunk
Understand -Xlinker option.
| author | Guido van Rossum <guido@python.org> |
|---|---|
| date | Tue, 02 Dec 1997 20:38:11 +0000 |
| parents | 6fb6e01e2ba1 |
| children | fb4b4d069cc7 |
| rev | line source |
|---|---|
| 2887 | 1 """Simple HTTP Server. |
| 2 | |
| 3 This module builds on BaseHTTPServer by implementing the standard GET | |
| 4 and HEAD requests in a fairly straightforward manner. | |
| 5 | |
| 6 """ | |
| 7 | |
| 8 | |
|
3105
438f88b55154
recognize a few more file types
Guido van Rossum <guido@python.org>
parents:
2887
diff
changeset
|
9 __version__ = "0.3" |
| 2887 | 10 |
| 11 | |
| 12 import os | |
| 13 import sys | |
| 14 import time | |
| 15 import socket | |
| 16 import string | |
| 17 import posixpath | |
| 18 import SocketServer | |
| 19 import BaseHTTPServer | |
| 20 | |
| 21 | |
| 22 class SimpleHTTPRequestHandler(BaseHTTPServer.BaseHTTPRequestHandler): | |
| 23 | |
| 24 """Simple HTTP request handler with GET and HEAD commands. | |
| 25 | |
| 26 This serves files from the current directory and any of its | |
| 27 subdirectories. It assumes that all files are plain text files | |
| 28 unless they have the extension ".html" in which case it assumes | |
| 29 they are HTML files. | |
| 30 | |
| 31 The GET and HEAD requests are identical except that the HEAD | |
| 32 request omits the actual contents of the file. | |
| 33 | |
| 34 """ | |
| 35 | |
| 36 server_version = "SimpleHTTP/" + __version__ | |
| 37 | |
| 38 def do_GET(self): | |
| 39 """Serve a GET request.""" | |
| 40 f = self.send_head() | |
| 41 if f: | |
| 42 self.copyfile(f, self.wfile) | |
| 43 f.close() | |
| 44 | |
| 45 def do_HEAD(self): | |
| 46 """Serve a HEAD request.""" | |
| 47 f = self.send_head() | |
| 48 if f: | |
| 49 f.close() | |
| 50 | |
| 51 def send_head(self): | |
| 52 """Common code for GET and HEAD commands. | |
| 53 | |
| 54 This sends the response code and MIME headers. | |
| 55 | |
| 56 Return value is either a file object (which has to be copied | |
| 57 to the outputfile by the caller unless the command was HEAD, | |
| 58 and must be closed by the caller under all circumstances), or | |
| 59 None, in which case the caller has nothing further to do. | |
| 60 | |
| 61 """ | |
| 62 path = self.translate_path(self.path) | |
| 63 if os.path.isdir(path): | |
| 64 self.send_error(403, "Directory listing not supported") | |
| 65 return None | |
| 66 try: | |
| 67 f = open(path) | |
| 68 except IOError: | |
| 69 self.send_error(404, "File not found") | |
| 70 return None | |
| 71 self.send_response(200) | |
| 72 self.send_header("Content-type", self.guess_type(path)) | |
| 73 self.end_headers() | |
| 74 return f | |
| 75 | |
| 76 def translate_path(self, path): | |
| 77 """Translate a /-separated PATH to the local filename syntax. | |
| 78 | |
| 79 Components that mean special things to the local file system | |
| 80 (e.g. drive or directory names) are ignored. (XXX They should | |
| 81 probably be diagnosed.) | |
| 82 | |
| 83 """ | |
| 84 path = posixpath.normpath(path) | |
| 85 words = string.splitfields(path, '/') | |
| 86 words = filter(None, words) | |
| 87 path = os.getcwd() | |
| 88 for word in words: | |
| 89 drive, word = os.path.splitdrive(word) | |
| 90 head, word = os.path.split(word) | |
| 91 if word in (os.curdir, os.pardir): continue | |
| 92 path = os.path.join(path, word) | |
| 93 return path | |
| 94 | |
| 95 def copyfile(self, source, outputfile): | |
| 96 """Copy all data between two file objects. | |
| 97 | |
| 98 The SOURCE argument is a file object open for reading | |
| 99 (or anything with a read() method) and the DESTINATION | |
| 100 argument is a file object open for writing (or | |
| 101 anything with a write() method). | |
| 102 | |
| 103 The only reason for overriding this would be to change | |
| 104 the block size or perhaps to replace newlines by CRLF | |
| 105 -- note however that this the default server uses this | |
| 106 to copy binary data as well. | |
| 107 | |
| 108 """ | |
| 109 | |
| 110 BLOCKSIZE = 8192 | |
| 111 while 1: | |
| 112 data = source.read(BLOCKSIZE) | |
| 113 if not data: break | |
| 114 outputfile.write(data) | |
| 115 | |
| 116 def guess_type(self, path): | |
| 117 """Guess the type of a file. | |
| 118 | |
| 119 Argument is a PATH (a filename). | |
| 120 | |
| 121 Return value is a string of the form type/subtype, | |
| 122 usable for a MIME Content-type header. | |
| 123 | |
| 124 The default implementation looks the file's extension | |
| 125 up in the table self.extensions_map, using text/plain | |
| 126 as a default; however it would be permissible (if | |
| 127 slow) to look inside the data to make a better guess. | |
| 128 | |
| 129 """ | |
| 130 | |
| 131 base, ext = posixpath.splitext(path) | |
| 132 if self.extensions_map.has_key(ext): | |
| 133 return self.extensions_map[ext] | |
|
3105
438f88b55154
recognize a few more file types
Guido van Rossum <guido@python.org>
parents:
2887
diff
changeset
|
134 ext = string.lower(ext) |
|
438f88b55154
recognize a few more file types
Guido van Rossum <guido@python.org>
parents:
2887
diff
changeset
|
135 if self.extensions_map.has_key(ext): |
|
438f88b55154
recognize a few more file types
Guido van Rossum <guido@python.org>
parents:
2887
diff
changeset
|
136 return self.extensions_map[ext] |
| 2887 | 137 else: |
| 138 return self.extensions_map[''] | |
| 139 | |
| 140 extensions_map = { | |
| 141 '': 'text/plain', # Default, *must* be present | |
| 142 '.html': 'text/html', | |
|
3105
438f88b55154
recognize a few more file types
Guido van Rossum <guido@python.org>
parents:
2887
diff
changeset
|
143 '.htm': 'text/html', |
|
438f88b55154
recognize a few more file types
Guido van Rossum <guido@python.org>
parents:
2887
diff
changeset
|
144 '.gif': 'image/gif', |
|
438f88b55154
recognize a few more file types
Guido van Rossum <guido@python.org>
parents:
2887
diff
changeset
|
145 '.jpg': 'image/jpeg', |
|
438f88b55154
recognize a few more file types
Guido van Rossum <guido@python.org>
parents:
2887
diff
changeset
|
146 '.jpeg': 'image/jpeg', |
| 2887 | 147 } |
| 148 | |
| 149 | |
| 150 def test(HandlerClass = SimpleHTTPRequestHandler, | |
| 151 ServerClass = SocketServer.TCPServer): | |
| 152 BaseHTTPServer.test(HandlerClass, ServerClass) | |
| 153 | |
| 154 | |
| 155 if __name__ == '__main__': | |
| 156 test() |
