python 搭建web伺服器
阿新 • • 發佈:2019-02-13
使用 httpie 在命令列進行測試
1、最基本的:
# _*_coding :utf-8 _*_ import httpie from http.server import BaseHTTPRequestHandler,HTTPServer class RequestHandler(BaseHTTPRequestHandler): '''處理請求並返回頁面''' # 頁面模板 Page = '''\ <html> <body> <p>Hello, web!</p> </body> </html> ''' def do_GET(self): self.send_response(200) self.send_header("Content-type","text/html") self.send_header("Content-length",str(len(self.Page))) #字串型別 self.end_headers() self.wfile.write(self.Page.encode()) if __name__ == '__main__': print("server start...") serverAddr = ('',9999) #連結不上可能是埠號被佔用 換個試試 server = HTTPServer(serverAddr,RequestHandler) server.serve_forever()
2、封裝建立page,傳送報文的方法
# _*_coding :utf-8 _*_ import httpie from http.server import BaseHTTPRequestHandler,HTTPServer class RequestHandler(BaseHTTPRequestHandler): '''處理請求並返回頁面''' # 頁面模板 Page = ''' <html> <body> <table> <tr> <td>Header</td> <td>Value</td> </tr> <tr> <td>Date and time</td> <td>{date_time}</td> </tr> <tr> <td>Client host</td> <td>{client_host}</td> </tr> <tr> <td>Client port</td> <td>{client_port}</td> </tr> <tr> <td>Command</td> <td>{command}</td> </tr> <tr> <td>Path</td> <td>{path}</td> </tr> </table> </body> </html> ''' def do_GET(self): page = self.create_page() self.send_content(page) def create_page(self): values = { 'date_time': self.date_time_string(), 'client_host': self.client_address[0], 'client_port': self.client_address[1], 'command': self.command, 'path': self.path } page = self.Page.format(**values) #dict為引數的傳遞方式 ** return page def send_content(self,page): self.send_response(200) self.send_header("Content-type", "text/html") self.send_header("Content-length", str(len(self.Page))) # 字串型別 self.end_headers() self.wfile.write(page.encode()) #這裡必須轉化威位元組(bytes)型別 否則報錯 if __name__ == '__main__': print("server start...") serverAddr = ('',9999) #連結不上可能是埠號被佔用 換個試試 server = HTTPServer(serverAddr,RequestHandler) server.serve_forever()
3、增加了對路徑的異常處理:
# _*_coding :utf-8 _*_ import httpie import sys,os from http.server import BaseHTTPRequestHandler,HTTPServer class RequestHandler(BaseHTTPRequestHandler): '''處理請求並返回頁面''' # 頁面模板 Page = ''' <html> <body> <table> <tr> <td>Header</td> <td>Value</td> </tr> <tr> <td>Date and time</td> <td>{date_time}</td> </tr> <tr> <td>Client host</td> <td>{client_host}</td> </tr> <tr> <td>Client port</td> <td>{client_port}</td> </tr> <tr> <td>Command</td> <td>{command}</td> </tr> <tr> <td>Path</td> <td>{path}</td> </tr> </table> </body> </html> ''' Error_Page = """\ <html> <body> <h1>Error accessing {path}</h1> <p>{msg}</p> </body> </html> """ def do_GET(self): try: #檔案完整路徑 full_path = os.getcwd() + self.path #如果該路徑不存在... if not os.path.exists(full_path): # 丟擲異常:檔案未找到 raise ServerException("'{0}' not found".format(self.path)) # 如果該路徑是一個檔案 elif os.path.isfile(full_path): # 呼叫 handle_file 處理該檔案 self.handle_file(full_path) # 如果該路徑不是一個檔案 # 丟擲異常:該路徑為不知名物件 else: raise ServerException("Unknown object '{0}'".format(self.path)) except Exception as msg: #msg則是上面丟擲的資訊 self.handle_error(msg) def create_page(self): values = { 'date_time': self.date_time_string(), 'client_host': self.client_address[0], 'client_port': self.client_address[1], 'command': self.command, 'path': self.path } page = self.Page.format(**values) #dict為引數的傳遞方式 ** return page def send_content(self,page): #這裡不再是個server1一樣了 需要傳引數page self.send_response(200) self.send_header("Content-type", "text/html") self.send_header("Content-length", str(len(self.Page))) # 字串型別 self.end_headers() self.wfile.write(page.encode()) #這裡必須轉化威位元組(bytes)型別 否則報錯 def handle_file(self,full_path): try: with open(full_path,"r") as reader: #讀位元組 故在sent_content()中不需要轉化為bytes了 content = reader.read() self.send_content(content) except IOError as msg: msg = "'{0}' cannot be read :{1}".format(self.path,msg) self.handle_error(msg) def handle_error(self,msg): content = self.Error_Page.format(path = self.path,msg = msg) self.send_content(content) class ServerException(Exception): '''伺服器內部錯誤''' pass if __name__ == '__main__': print("server start...") serverAddr = ('',9999) #連結不上可能是埠號被佔用 換個試試 server = HTTPServer(serverAddr,RequestHandler) server.serve_forever()
plain.html為自己建立的靜態網頁
4、增加了程式碼的重構,更加簡明,易擴充套件
#-*- coding:utf-8 -*-
import sys, os, subprocess
from http.server import HTTPServer,BaseHTTPRequestHandler
#-------------------------------------------------------------------------------
class ServerException(Exception):
'''伺服器內部錯誤'''
pass
#-------------------------------------------------------------------------------
class base_case(object):
'''條件處理基類'''
def handle_file(self, handler, full_path):
try:
with open(full_path, 'r') as reader: #這裡不要直接讀城b 的否則會與下面的decode衝突
content = reader.read()
handler.send_content(content)
except IOError as msg:
msg = "'{0}' cannot be read: {1}".format(full_path, msg)
handler.handle_error(msg)
def index_path(self, handler):
return os.path.join(handler.full_path, 'index.html')
def test(self, handler):
assert False, 'Not implemented.'
def act(self, handler):
assert False, 'Not implemented.'
#-------------------------------------------------------------------------------
class case_no_file(base_case):
'''檔案或目錄不存在'''
def test(self, handler):
return not os.path.exists(handler.full_path)
def act(self, handler):
raise ServerException("'{0}' not found".format(handler.path))
#-------------------------------------------------------------------------------
class case_cgi_file(base_case):
'''可執行指令碼'''
def run_cgi(self, handler):
data = subprocess.check_output(["python", handler.full_path])
handler.send_content(data)
def test(self, handler):
return os.path.isfile(handler.full_path) and handler.full_path.endswith('.py')
def act(self, handler):
self.run_cgi(handler)
#-------------------------------------------------------------------------------
class case_existing_file(base_case):
'''檔案存在的情況'''
def test(self, handler):
return os.path.isfile(handler.full_path)
def act(self, handler):
self.handle_file(handler, handler.full_path)
#-------------------------------------------------------------------------------
class case_directory_index_file(base_case):
'''在根路徑下返回主頁檔案'''
def test(self, handler):
return os.path.isdir(handler.full_path) and os.path.isfile(self.index_path(handler))
def act(self, handler):
self.handle_file(handler, self.index_path(handler))
#-------------------------------------------------------------------------------
class case_always_fail(base_case):
'''預設處理'''
def test(self, handler):
return True
def act(self, handler):
raise ServerException("Unknown object '{0}'".format(handler.path))
#-------------------------------------------------------------------------------
class RequestHandler(BaseHTTPRequestHandler):
'''
請求路徑合法則返回相應處理
否則返回錯誤頁面
'''
Cases = [case_no_file(),
case_cgi_file(),
case_existing_file(),
case_directory_index_file(),
case_always_fail()]
# 錯誤頁面模板
Error_Page = """
<html>
<body>
<h1>Error accessing {path}</h1>
<p>{msg}</p>
</body>
</html>
"""
def do_GET(self):
try:
# 得到完整的請求路徑
self.full_path = os.getcwd() + self.path
# 遍歷所有的情況並處理
for case in self.Cases:
if case.test(self):
case.act(self)
break
# 處理異常
except Exception as msg:
self.handle_error(msg)
def handle_error(self, msg):
content = self.Error_Page.format(path=self.path, msg=msg)
self.send_content(content, 404)
# 傳送資料到客戶端
def send_content(self, content, status=200):
self.send_response(status)
self.send_header("Content-type", "text/html")
self.send_header("Content-Length", str(len(content)))
self.end_headers()
self.wfile.write(content.encode())
#-------------------------------------------------------------------------------
if __name__ == '__main__':
print("server start...")
serverAddress = ('', 9999)
server = HTTPServer(serverAddress, RequestHandler)
server.serve_forever()
此時的 狀態為 404了
參考:https://zhuanlan.zhihu.com/p/21323273?utm_source=qq&utm_medium=social