1 #coding = utf-8 2 from http.server import BaseHTTPRequestHandler, HTTPServer 3 4 class RequestHandler(BaseHTTPRequestHandler): 5 Page = ''' 6 <html> 7 <body> 8 <p>Hello, world!</p> 9 </body> 10 </html> 11 ''' 12 #重载do_GET方法 13 def do_GET(self): 14 self.send_response(200) #发送状态码,200是ok 15 self.send_header('Content-Type', 'text/html') 16 ''' 17 发送http头部信息,text/html指HTML格式 18 另外还有诸如text/plain纯文本格式,image/gif GIF图片格式 19 通过头部信息浏览器就知道如何处理所发来的内容了 20 另外还有self.send_header('Content-Encoding','gzip')是指让浏览器按照压缩方式处理内容 21 另外还有很多。。。 22 ''' 23 self.end_headers() 24 self.wfile.write(self.Page.encode()) 25 26 #---------------------------------------------------------------------- 27 28 if __name__ == '__main__': 29 serverAddress = ('', 8080) 30 server = HTTPServer(serverAddress, RequestHandler) 31 server.serve_forever()
如果我把self.send_response(200)状态码改为404,那么就会出现下述情况:
1 #coding = utf-8 2 from http.server import BaseHTTPRequestHandler, HTTPServer 3 4 class RequestHandler(BaseHTTPRequestHandler): 5 #<tr>代表一行,<td>代表一列 6 Page = ''' 7 <html> 8 <body> 9 <table> 10 <tr> <td>Header</td> <td>Value</td> </tr> 11 <tr> <td>Date and time</td> <td>{date_time}</td> </tr> 12 <tr> <td>Client host</td> <td>{client_host}</td> </tr> 13 <tr> <td>Client port</td> <td>{client_port}</td> </tr> 14 <tr> <td>Command</td> <td>{command}</td> </tr> 15 <tr> <td>Path</td> <td>{path}</td> </tr> 16 </table> 17 </body> 18 </html> 19 ''' 20 21 def do_GET(self): 22 page = self.create_page() 23 self.send_content(page) 24 25 def send_content(self, page): 26 self.send_response(200) 27 self.send_header('Content-Type', 'text/html') 28 self.end_headers() 29 self.wfile.write(page.encode()) 30 31 def create_page(self): 32 values = { 33 'date_time': self.date_time_string(), 34 'client_host': self.client_address[0], 35 'client_port': self.client_address[1], 36 'command': self.command, 37 'path': self.path 38 } 39 page = self.Page.format(**values) 40 ''' 41 字符串格式化函数 42 通过字典设置参数 43 site = {'name': '菜鸟教程', 'url': 'www.runoob.com'} 44 print('网站名:{name}, 地址:{url}'.format(**site)) 45 ''' 46 return page 47 48 #---------------------------------------------------------------------- 49 50 if __name__ == '__main__': 51 serverAddress = ('', 8080) 52 server = HTTPServer(serverAddress, RequestHandler) 53 server.serve_forever()
1 #coding = utf-8 2 from http.server import BaseHTTPRequestHandler, HTTPServer 3 import sys, os 4 5 6 class serverException(Exception): 7 '''服务器内部错误''' 8 pass 9 10 class RequestHandler(BaseHTTPRequestHandler): 11 errorPage = """ 12 <html> 13 <body> 14 <h1>Error accessing {path}</h1> 15 <p>{msg}</p> 16 </body> 17 </html> 18 """ 19 20 def do_GET(self): 21 try: 22 fullPath = os.getcwd() + self.path 23 if not os.path.exists(fullPath): #不存在就报错 24 raise serverException("'{0}' not found".format(self.path)) 25 elif os.path.isfile(fullPath): #如果是文件,则打开 26 self.handle_file(fullPath) 27 else: #其余情况 28 raise serverException("Unknown object '{0}'".format(self.path)) 29 except Exception as msg: 30 self.handle_error(msg) 31 32 def handle_error(self, msg): 33 content = self.errorPage.format(path=self.path, msg=msg) 34 self.send_content(content, 404) 35 36 def send_content(self, page, status=200): 37 self.send_response(status) 38 self.send_header('Content-Type', 'text/html') 39 self.end_headers() 40 self.wfile.write(page.encode()) 41 42 def handle_file(self, fullPath): 43 try: 44 f = open(fullPath, 'r') #python3要注意是以r读还是rb读 45 content = f.read() 46 self.send_content(content) 47 except IOError as msg: 48 msg = "'{0}' cannot be read: {1}".format(self.path, msg) 49 self.handle_error(msg) 50 51 #---------------------------------------------------------------------- 52 53 if __name__ == '__main__': 54 serverAddress = ('', 8080) 55 server = HTTPServer(serverAddress, RequestHandler) 56 server.serve_forever()
在这里的话需要把plain.html这个文件放在代码相同目录下。
测试情况如下:
1 #coding = utf-8 2 from http.server import BaseHTTPRequestHandler, HTTPServer 3 import sys, os 4 5 6 class serverException(Exception): 7 '''服务器内部错误''' 8 pass 9 10 ''' 11 将不同的情况单独写成一个类,最后将这些类保存在一个列表之中,这样最后遍历列表即可,不需要if-elif了 12 ''' 13 class case_no_file(object): 14 '''路径不存在''' 15 def test(self, handler): 16 return not os.path.exists(handler.fullPath) 17 def act(self, handler): 18 raise serverException("'{0}' not found".format(handler.path)) 19 20 class case_is_file(object): 21 '''路径是文件''' 22 def test(self, handler): 23 return os.path.isfile(handler.fullPath) 24 def act(self, handler): 25 handler.handle_file(handler.fullPath) 26 27 class case_always_fail(object): 28 '''不满足时的默认处理类''' 29 def test(self, handler): 30 return True 31 def act(self, handler): 32 raise serverException("Unknown object '{0}'".format(handler.Path)) 33 34 class case_directory_index_file(object): 35 '''进入根目录时显示主页''' 36 def index_path(self, handler): 37 return os.path.join(handler.fullPath, 'index.html') #前后合并 38 def test(self, handler): 39 return os.path.isdir(handler.fullPath) and os.path.isfile(self.index_path(handler)) 40 def act(self, handler): 41 handler.handle_file(self.index_path(handler)) 42 43 class RequestHandler(BaseHTTPRequestHandler): 44 caseList = [case_no_file(), 45 case_is_file(), 46 case_directory_index_file(), 47 case_always_fail()] 48 49 errorPage = """ 50 <html> 51 <body> 52 <h1>Error accessing {path}</h1> 53 <p>{msg}</p> 54 </body> 55 </html> 56 """ 57 58 def do_GET(self): 59 try: 60 self.fullPath = os.getcwd() + self.path 61 for case in self.caseList: 62 if case.test(self): 63 case.act(self) 64 break 65 except Exception as msg: 66 self.handle_error(msg) 67 68 def handle_error(self, msg): 69 content = self.errorPage.format(path=self.path, msg=msg) 70 self.send_content(content, 404) 71 72 def send_content(self, page, status=200): 73 self.send_response(status) 74 self.send_header('Content-Type', 'text/html') 75 self.end_headers() 76 self.wfile.write(page.encode()) 77 78 def handle_file(self, fullPath): 79 try: 80 f = open(fullPath, 'r') #python3要注意是以r读还是rb读 81 content = f.read() 82 self.send_content(content) 83 except IOError as msg: 84 msg = "'{0}' cannot be read: {1}".format(self.path, msg) 85 self.handle_error(msg) 86 87 #---------------------------------------------------------------------- 88 89 if __name__ == '__main__': 90 serverAddress = ('', 8080) 91 server = HTTPServer(serverAddress, RequestHandler) 92 server.serve_forever()
之前所做的是静态页面的显示,如果要显示动态页面的话就不能写成html的文件了,在这里可以使用CGI协议与脚本来实现动态页面。
服务器在收到客户端的请求后执行指定的CGI应用程序,CGI应用程序执行后再转换成服务器和浏览器能够理解的内容,比如说HTML页面。
下面的例子就是做一个展示当前时间的页面,先是用python实现了一个CGI脚本time.py,当浏览器请求这个CGI脚本的时候,服务器就会去执行time.py,然后得到执行结果的一段HTML形式的字符,最后就输出即可。
在这里就用到了python库中的subprocess模块,它的功能使fork一个子进程,然后运行一个外部程序。
subprocess.check_output(args, *, stdin=None, stderr=None, shell=False, universal_newlines=False)
它的作用是执行args中的命令,并将其输出成字符串返回。
1 #!/usr/bin/env python 2 import time 3 4 print(''' 5 <html> 6 <body> 7 <p>Generated {0}</p> 8 </body> 9 </html> 10 '''.format(time.asctime()))
1 #coding = utf-8 2 from http.server import BaseHTTPRequestHandler, HTTPServer 3 import sys, os 4 import subprocess 5 6 7 class serverException(Exception): 8 '''服务器内部错误''' 9 pass 10 11 ''' 12 将不同的情况单独写成一个类,最后将这些类保存在一个列表之中,这样最后遍历列表即可,不需要if-elif了 13 ''' 14 class case_no_file(object): 15 '''路径不存在''' 16 def test(self, handler): 17 return not os.path.exists(handler.fullPath) 18 def act(self, handler): 19 raise serverException("'{0}' not found".format(handler.path)) 20 21 class case_is_file(object): 22 '''路径是文件''' 23 def test(self, handler): 24 return os.path.isfile(handler.fullPath) 25 def act(self, handler): 26 handler.handle_file(handler.fullPath) 27 28 class case_always_fail(object): 29 '''不满足时的默认处理类''' 30 def test(self, handler): 31 return True 32 def act(self, handler): 33 raise serverException("Unknown object '{0}'".format(handler.Path)) 34 35 class case_directory_index_file(object): 36 '''进入根目录时显示主页''' 37 def index_path(self, handler): 38 return os.path.join(handler.fullPath, 'index.html') #前后合并 39 def test(self, handler): 40 return os.path.isdir(handler.fullPath) and os.path.isfile(self.index_path(handler)) 41 def act(self, handler): 42 handler.handle_file(self.index_path(handler)) 43 44 class case_cgi_file(object): 45 '''脚本文件处理''' 46 def test(self, handler): 47 return os.path.isfile(handler.fullPath) and handler.fullPath.endswith('.py') 48 def act(self, handler): 49 handler.run_cgi(handler.fullPath) 50 51 class RequestHandler(BaseHTTPRequestHandler): 52 caseList = [case_no_file(), 53 case_cgi_file(), 54 case_is_file(), 55 case_directory_index_file(), 56 case_always_fail()] 57 58 errorPage = """ 59 <html> 60 <body> 61 <h1>Error accessing {path}</h1> 62 <p>{msg}</p> 63 </body> 64 </html> 65 """ 66 67 def do_GET(self): 68 try: 69 self.fullPath = os.getcwd() + self.path 70 for case in self.caseList: 71 if case.test(self): 72 case.act(self) 73 break 74 except Exception as msg: 75 self.handle_error(msg) 76 77 def handle_error(self, msg): 78 content = self.errorPage.format(path=self.path, msg=msg) 79 self.send_content(content, 404) 80 81 def send_content(self, page, status=200): 82 self.send_response(status) 83 self.send_header('Content-Type', 'text/html') 84 self.end_headers() 85 self.wfile.write(page.encode()) 86 87 def handle_file(self, fullPath): 88 try: 89 f = open(fullPath, 'r') #python3要注意是以r读还是rb读 90 content = f.read() 91 self.send_content(content) 92 except IOError as msg: 93 msg = "'{0}' cannot be read: {1}".format(self.path, msg) 94 self.handle_error(msg) 95 96 def run_cgi(self, fullPath): 97 data = subprocess.check_output(['python', fullPath]) 98 self.send_content(data.decode()) 99 100 #---------------------------------------------------------------------- 101 102 if __name__ == '__main__': 103 serverAddress = ('', 8080) 104 server = HTTPServer(serverAddress, RequestHandler) 105 server.serve_forever()