寫一個最簡單的web框架

本篇文章是爲了後面的Django做準備的,這是學習web框架的底層知識,沒有直接用到socket,而是用Python自帶的庫wsgiref。
1、wsgiref模塊
它就相當於是一個服務器,會幫我們做解析,內部已經封裝好了socket等多項功能。

2、框架主要分爲五部分
1)導入模塊

from wsgiref.simple_server import make_server

2)自定義處理函數

def foo1(req):
    f=open("index1.html","rb")  # 讀取文件
    data=f.read()
    return data

3)路由分發函數
即分發其他函數的一個函數,所有的要實現的功能都可以放在這裏面傳輸到服務器,這樣每一個路徑都可以對應一個函數。

def router():
    url_patterns=[
        ("/login",login),
        ("/register",register),
        ("/Viewin", foo1),
        ("/Zoro", foo2),
        ("/show_time",show_time),
    ]
    return url_patterns

4)應用函數
框架本體,可以直接套用。一但有端口連接進入後,就會運行application函數,environ是wsgiref服務器處理傳入的請求信息,是一個大字典,取值用鍵值對來取。

def application(environ, start_response):
    # 在application函數內,則需要作出響應操作

    #通過environ來取路徑上輸入的值
    print("path",environ["PATH_INFO"])
    path= environ["PATH_INFO"]

    # start_response設置響應頭:狀態碼爲200,狀態碼解析是OK,文本內容,文本格式...
    start_response('200 OK', [('Content-Type', 'text/html')])
    
	# return返回響應體
    return [b"<h1>Hello, web!</h1>"]

5)創建鏈接並監聽HTTP請求
參數:IP地址,端口,應用函數
注意:這裏的IP地址會默認獲取本機的IP地址

# 創建鏈接
httpd = make_server('', 8080, application)

# 開始監聽HTTP請求:
httpd.serve_forever()

3、前端代碼body部分
1)show_time

<body>

<h1>時間:{{time}}</h1>
<!--自定義語法{{}}-->

</body>

2)login

<form action="http://192.168.43.247:8080/login" method="get">
    <p>用戶:<input type="text" name="user"> </p>
    <p>密碼:<input type="password" name="pwd"> </p>
    <p><input type="submit">提交</p>
</form>

3)index1

<h1>Hello ViewIn!</h1>

4)index2

<h1>Hello Zoro!</h1>

4、參考效果
在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述

5、完整web框架

# 導入wsgiref模塊(不會直接使用socket),
# 它相當於是一個服務器,會幫我們做解析,內部已經封裝好了socket等多項功能
from wsgiref.simple_server import make_server
import time

# 自定義處理函數
def foo1(req):
    f=open("index1.html","rb")  # 讀取文件
    data=f.read()
    return data

def foo2(req):
    f = open("index2.html", "rb")  # 讀取文件
    data = f.read()
    return data

def login(req):
    # print(req)  #找到user和pwd所在的大的鍵爲QUERY_STRING
    print(req["QUERY_STRING"])

    return b"Welcome to my web!"

def register(req):
    pass

def show_time(req):
    times=time.ctime()  # 獲取時間的字符串
    f= open("show_time.html","rb")
    data= f.read().decode("utf8")

    # 自定義語法{{}},來找到我們需要的時間
    # 用變量times(準確的時間)去替換頁面內的time
    data= data.replace("{{time}}",str(times))
    # 此處替換後的內容是字符串,因此需要轉碼一下
    return data.encode("utf8")


# 路由分發的函數:即分發其他函數的一個函數,所有的要實現的功能都可以放在這裏面傳輸到服務器
# 這樣每一個路徑都可以對應一個函數
def router():
    url_patterns=[
        ("/login",login),
        ("/register",register),
        ("/Viewin", foo1),
        ("/Zoro", foo2),
        ("/show_time",show_time),
    ]
    return url_patterns

# 應用函數:一但有端口連接進入後,就會運行application函數
# environ是wsgiref服務器處理傳入的請求信息,是一個大字典,取值用鍵值對來取
def application(environ, start_response):
    # 在application函數內,則需要作出響應操作

    #通過environ來取路徑上輸入的值
    print("path",environ["PATH_INFO"])
    path= environ["PATH_INFO"]

    # start_response設置響應頭:狀態碼爲200,狀態碼解析是OK,文本內容,文本格式...
    start_response('200 OK', [('Content-Type', 'text/html')])

    '''
    if path=="/Viewin":
        return[foo1()]
        # return[b"<h1>Hello ViewIn!</h1>"]  # 傳入網頁的應該是字節類型(二進制),並且最終應該包含在一個大字典裏
    elif path=="/Zoro":
        return[foo2()]
        # return[b"<h1>Hello Zoro!</h1>"]
    '''

    # 接收路由分發函數
    url_patterns=router()
    func=None  # 用來裝中間函數的
    # 遍歷路由分發裏的函數
    for item in url_patterns:
        # 如果遍歷的對象和路徑輸入一致,則執行這個路徑對應的函數
        if item[0]==path:
            func=item[1]
            break

    # 因爲默認的None,所以需要判斷一下是否爲空
    if func:
        return[func(environ)]  # 執行中間函數,並將路徑上獲取的信息作爲參數傳入
    else:
        return [b"<h1>404</h1>"]

    # return返回響應體
    return [b"<h1>Hello, web!</h1>"]


# 參數:IP地址,端口,應用函數
# 注意:這裏的IP地址會默認獲取本機的IP地址
httpd = make_server('', 8080, application)

print('Serving HTTP on port 8080...')

# 開始監聽HTTP請求:
httpd.serve_forever()
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章