python之web框架(3):WSGI之web应用完善

python之web框架(3):WSGI之web应用完善

1.上篇的web框架太low,只能实现回应固定页面。现在将它进行完善。首先将wsgi和web服务器进行分离,并给予它回复静态页面的能力。

  • web_server.py
#!/usr/bin/env python3
# coding:utf-8

from test_frame import app
from socket import *
from multiprocessing import Process


class MyWebServer(object):
    def start_response(self, status, head_list):
        self.response_head = 'HTTP/1.1 ' + status + ' \r\n'
        self.response_head = self.response_head.encode()
        # print(self.response_head)

    def deal(self, conn):
        recv_data = conn.recv(1024).decode('utf-8')
        recv_data_head = recv_data.splitlines()[0]
        # print('------recv_data_head: ', recv_data_head)
        request_method, request_path, http_version = recv_data_head.split()
        request_path = request_path.split('?')[0]  # 去掉url中的?和之后的参数

        env = {'request_method': request_method, 'request_path': request_path}

        # 这里是wsgi接口调用的地方
        response_body = app(env, self.start_response)

        response_data = self.response_head + b'\r\n' + response_body
        conn.send(response_data)
        # print('response_data = ', response_data)

    def __init__(self):
        self.s = socket(AF_INET, SOCK_STREAM)
        self.s.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
        self.s.bind(('', 8000))
        self.s.listen(1023)
        self.response_head = ''

    def start(self):
        while 1:
            conn, user_info = self.s.accept()
            print(user_info, '接入')
            p = Process(target=self.deal, args=(conn,))
            p.start()
            conn.close()  # 进程会复制出一个新的conn,所以这里的conn需要关闭


s = MyWebServer()
s.start()

  • test_frame.py
def app(env, start_response):
    file_name = env['request_path']
    if file_name == '/':
        file_name = '/index.html'
    try:
        f = open('.' + file_name, 'rb')
    except IOError:
        status = '404 error'
        head_list = [("name", "wanghui")]
        start_response(status, head_list)
        return b'<h1>File not found</h1>'

    status = '200 OK'
    head_list = [("name", "wanghui")]
    start_response(status, head_list)
    read_data = f.read()
    f.close()
    return read_data


2.框架已经提供了静态页面的能力。下面对框架进一步完善。

  • web_server.py
#!/usr/bin/env python3
# coding:utf-8

from testframe import app
from socket import *
from multiprocessing import Process


class MyWebServer(object):
    def start_response(self, status, head_list):
        self.response_head = 'HTTP/1.1 ' + status + ' \r\n'
        self.response_head = self.response_head.encode()

    def deal(self, conn):
        recv_data = conn.recv(1024).decode('utf-8')
        recv_data_head = recv_data.splitlines()[0]
        request_method, request_path, http_version = recv_data_head.split()
        request_path = request_path.split('?')[0]  # 去掉url中的?和之后的参数

        env = {'request_method': request_method, 'request_path': request_path}

        # 这里是wsgi接口调用的地方
        response_body = self.app(env, self.start_response)

        response_data = self.response_head + b'\r\n' + response_body
        conn.send(response_data)
        conn.close()

    def __init__(self, app, port=8000):
        self.s = socket(AF_INET, SOCK_STREAM)
        self.s.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
        self.s.bind(('', port))
        self.s.listen(1023)
        self.response_head = ''
        self.app = app

    def start(self):
        while 1:
            conn, user_info = self.s.accept()
            print(user_info, '接入')
            p = Process(target=self.deal, args=(conn,))
            p.start()
            conn.close()  # 进程会复制出一个新的conn,所以这里的conn需要关闭


s = MyWebServer(app)
s.start()

  • test_frame.py
import time


class Application(object):
    def __init__(self, url_list):
        self.url_list = url_list

    def __call__(self, env, start_response):
        file_name = env['request_path']
        if file_name == '/':
            file_name = '/index.html'

        try:
            f = open('.' + file_name, 'rb')
        except IOError:
            get_name = url_list.get(file_name, 'say_error')
            return eval(get_name)(start_response)

        status = '200 OK'
        head_list = [("name", "wanghui")]
        start_response(status, head_list)
        read_data = f.read()
        f.close()
        return read_data


def say_error(start_response):
    status = '404 error'
    head_list = [("name", "wanghui")]
    start_response(status, head_list)
    return b'<h1>File not found</h1>'


def say_time(start_response):
    status = '200 OK'
    head_list = [("name", "wanghui")]
    start_response(status, head_list)
    return time.ctime().encode()


def say_hello(start_response):
    status = '200 OK'
    head_list = [("name", "wanghui")]
    start_response(status, head_list)
    return b'<h1>hello world</b>'


url_list = {'/time.py': 'say_time',
            '/error.py': 'say_error',
            '/hello.py': 'say_hello',
            }
app = Application(url_list)

  • 此时如果访问http://localhost/time.py,则会动态的将当前时间返回给客户。
  • 不过功能还不够完善,像不支持长连接,还不能支持外部py文件动态解析。

posted @ 2017-04-25 00:40  王辉辉的猫  阅读(309)  评论(0编辑  收藏  举报