【django学习-01】基于wsgi自制一个web框架

  • 什么是web框架
    • 框架,即farmework。特指为解决一个开放性问题而设计的具有一定约束性的支撑结构,使用框架可以帮你快速开发特定的系统,简单地说,就是你用别人搭建好的舞台来做表演。
    • 对于所有的web应用,本质上其实就是一个socket服务端,用户的浏览器其实就是一个socket客户端
import socket

def handle_request(client):
    buf = client.recv(1024)
    client.send("HTTP/1.1 200 OK\r\n\r\n".encode("utf8"))
    # client.send("<h1 style='color:red'>Hello, yuan</h1>".encode("utf8"))
    
    #读取html文件
    with open('index.html','rb') as f:
        data = f.read()
    client.send(data)

def main():

    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.bind(('localhost',8001))
    sock.listen(5)

    while True:
        connection, address = sock.accept()
        handle_request(connection)
        connection.close()

if __name__ == '__main__':
    main()
  • 最简单的Web应用就是先把HTML用文件保存好,用一个现成的HTTP服务器软件,接收用户请求,从文件中读取HTML,返回。
  • 如果要动态生成HTML,就需要把上述步骤自己来实现。不过,接受HTTP请求、解析HTTP请求、发送HTTP响应都是苦力活,如果我们自己来写这些底层代码,还没开始写动态HTML呢,就得花个把月去读HTTP规范。
  • 正确的做法是底层代码由专门的服务器软件实现,我们用Python专注于生成HTML文档。因为我们不希望接触到TCP连接、HTTP原始请求和响应格式,所以,需要一个统一的接口,让我们专心用Python编写Web业务。
  • 这个接口就是WSGI:Web Server Gateway Interface。
    • 1、最基础的,直接给浏览器返回固定值
from wsgiref.simple_server import make_server
def application(environ, start_response):
    #通过enciron封装成一个所有请求信息的对象
    #start_response 可以很方便的设置响应头
    start_response('200 OK', [('Content-Type', 'text/html')])
    print(environ)
    return [b'<h1>Hello, web!</h1>']

#封装socket对象以及准备过程(socket,bind,listen)
httpd = make_server('localhost', 8080, application)

print('Serving HTTP on port 8000...')
# 开始监听HTTP请求:
httpd.serve_forever()
  • 2、根据浏览器传的不同路径,返回不同内容
from wsgiref.simple_server import make_server

def f1(request):    #request:形参,根据传入的environ获取请求参数,从而按不同逻辑处理
    return [b'<h1>Hello, web!</h1>']
def f2(request):
    return [b'<h1>Hello, book!</h1>']
def application(environ, start_response):
    # print(environ['PATH_INFO'])
    start_response('200 OK', [('Content-Type', 'text/html')])
    path = environ['PATH_INFO']

    if path == '/web':
        return f1(environ)
        # return [b'<h1>Hello, web!</h1>']
    elif path == '/book':
        return f2(environ)
        # return [b'<h1>Hello, book!</h1>']
    else:
        return [b'<h1>404!</h1>']

httpd = make_server('localhost', 8080, application)

print('Serving HTTP on port 8000...')
# 开始监听HTTP请求:
httpd.serve_forever()
  • 3、如上所示,如果有很多个路径,这样写就不适合了,于是我们通过循环的方式获取
from wsgiref.simple_server import make_server
import time
def router():
    urlpath = (
        ('/book',f1),
        ('/web',f2),
        ('/curtime',f3),
    )
    return urlpath

def f1(request):
    return [b'<h1>Hello, book!</h1>']
def f2(request):
    return [b'<h1>Hello, web!</h1>']
def f3(request):
    cur_time = time.ctime(time.time())
    with open('cur_time.html','rb') as f:    
        data = f.read()
        data = str(data,'utf8').replace('!curtime!',str(cur_time))    #返回当前时间
    return [data.encode('utf8')]

def application(environ, start_response):
    # print(environ['PATH_INFO'])
    start_response('200 OK', [('Content-Type', 'text/html')])
    path = environ['PATH_INFO']

    urlpatterns = router()
    func = None
    for item in urlpatterns:
        if item[0] == path:
            func = item[1]
            break
    if func:
        return func(environ)
    else:
        return ["<h1>404</h1>".encode("utf8")]

httpd = make_server('localhost', 8080, application)

print('Serving HTTP on port 8080...')
# 开始监听HTTP请求:
httpd.serve_forever()
//cur_time.html
<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Title</title>
</head>
<body>
<h3>current_time: !curtime!</h3>
</body>
</html>
  • 伙计们,不知不觉我们自己已经写出一个web框架啦!
posted @ 2022-08-28 19:34  Tony_xiao  阅读(49)  评论(0编辑  收藏  举报