• 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

  • 相关阅读:
    list for循环中删除元素
    XMLFeedSpider例子
    myeclipse一直卡在loading workbench解决方法
    代码
    在Github上面搭建Hexo博客(一):部署到Github
    RegEX正则表达式截取字符串
    将后台值传单前台js接收
    C# List<T>泛型用法
    基于jQuery——TreeGrid
    在线编程学习网站
  • 原文地址:https://www.cnblogs.com/zyb993963526/p/8476363.html
Copyright © 2020-2023  润新知