python写web服务器

 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()
简单的web服务器

如果我把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()
在url根目录显示主页

之前所做的是静态页面的显示,如果要显示动态页面的话就不能写成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()))
time.py
  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()
main.py

原文地址:https://www.cnblogs.com/zyb993963526/p/8476363.html