mini web框架完整版本 添加 :url编码解码 -- log日志

文件目录:

 

├── dynamic
│   ├── __init__.py
│   ├── __pycache__
│   │   ├── __init__.cpython-37.pyc
│   │   └── mini_frame.cpython-37.pyc
│   └── mini_frame.py
├── new.log
├── static
│   ├── css
│   │   ├── bootstrap.min.css
│   │   ├── main.css
│   │   └── swiper.min.css
│   └── js
│       ├── a.js
│       ├── bootstrap.min.js
│       ├── jquery-1.12.4.js
│       ├── jquery-1.12.4.min.js
│       ├── jquery-ui.min.js
│       ├── jquery.animate-colors-min.js
│       ├── jquery.animate-colors.js
│       ├── jquery.cookie.js
│       ├── server.js
│       ├── swiper.jquery.min.js
│       ├── swiper.min.js
│       └── zepto.min.js
├── templates
│   ├── center.html
│   ├── index.html
│   └── update.html
└── web_server.py

 

 

 

 

web服务器:

import socket
import re
import multiprocessing
import time
import dynamic.mini_frame
import sys


class WSGIServer(object):
    def __init__(self,port):
        # 1. 创建套接字
        self.tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

        # 2. 绑定
        self.tcp_server_socket.bind(("", port))

        # 3. 变为监听套接字
        self.tcp_server_socket.listen(128)

    def service_client(self, new_socket):
        """为这个客户端返回数据"""

        # 1. 接收浏览器发送过来的请求 ,即http请求  
        # GET / HTTP/1.1
        # .....
        request = new_socket.recv(1024).decode("utf-8")
        # print(">>>"*50)
        # print(request)

        request_lines = request.splitlines()
        print("")
        print(">"*20)
        print("request_lines[0]",request_lines[0])

        # GET /index.html HTTP/1.1
        # get post put del
        file_name = ""
        ret = re.match(r"[^/]+(/[^ ]*)", request_lines[0])
        print("ret",ret.group(1))
        if ret:
            file_name = ret.group(1)
            print("ret_group",ret.group(1))
            # print("*"*50, file_name)
            if file_name == "/":
                file_name = "/index.html"

        # 2. 返回http格式的数据,给浏览器
        # 2.1 如果请求的资源不是以.py结尾,那么就认为是静态资源(html/css/js/png,jpg等)
        if not file_name.endswith(".html"):
            try:
                f = open("./static" + file_name, "rb")
            except:
                response = "HTTP/1.1 404 NOT FOUND\r\n"
                response += "\r\n"
                response += "------file not found-----"
                new_socket.send(response.encode("utf-8"))
            else:
                html_content = f.read()
                f.close()
                # 2.1 准备发送给浏览器的数据---header
                response = "HTTP/1.1 200 OK\r\n"
                response += "\r\n"
                # 2.2 准备发送给浏览器的数据---boy
                # response += "hahahhah"

                # 将response header发送给浏览器
                new_socket.send(response.encode("utf-8"))
                # 将response ic.mini_frame.applicationbody发送给浏览器
                new_socket.send(html_content)
        else:
            # 2.2 如果是以.py结尾,那么就认为是动态资源的请求

            env = dict()  # 这个字典中存放的是web服务器要传递给 web框架的数据信息
            env['PATH_INFO'] = file_name
            print("PATH_INFO",env["PATH_INFO"])
            # {"PATH_INFO": "/index.py"}
            body = dynamic.mini_frame.application(env, self.set_response_header)

            header = "HTTP/1.1 %s\r\n" % self.status

            for temp in self.headers:
                header += "%s:%s\r\n" % (temp[0], temp[1])

            header += "\r\n"
           
            response = header+body
       
            # 发送response给浏览器
            new_socket.send(response.encode("utf-8"))


        # 关闭套接
        new_socket.close()

    def set_response_header(self, status, headers):
        self.status = status
        self.headers = [("server", "mini_web v8.8")]
        self.headers += headers
        

    def run_forever(self):
        """用来完成整体的控制"""

        while True:
            # 4. 等待新客户端的链接
            new_socket, client_addr = self.tcp_server_socket.accept()

            # 5. 为这个客户端服务
            p = multiprocessing.Process(target=self.service_client, args=(new_socket,))
            p.start()

            new_socket.close()


        # 关闭监听套接字
        self.tcp_server_socket.close()


def main():
    if len(sys.argv) == 2:
        port = int(sys.argv[1])

        """控制整体,创建一个web 服务器对象,然后调用这个对象的run_forever方法运行"""
        wsgi_server = WSGIServer(port)
        wsgi_server.run_forever()
    else:
        print("error")


if __name__ == "__main__":
    main()

 

web框架

# coding=utf-8
import re
from pymysql import connect
import urllib.parse
import logging

ROUTER_DICT = dict()

def route(url):
    def set_func(func):
        ROUTER_DICT[url] = func
        def call_func(*args,**kwargs):
            return func(*args,**kwargs)
        return call_func
    return set_func


@route("/index.html")
def index(res):
    with open("./templates/index.html",encoding="utf-8") as f:
        content = f.read()

    conn = connect(host="localhost",port=3306,user="root",password="",database="stock_db",charset="utf8")
    cs = conn.cursor()
    cs.execute("select * from info")
    info = cs.fetchall()
    cs.close()
    conn.close()


    page_template = """<tr>
            <td>%s</td>
            <td>%s</td>
            <td>%s</td>
            <td>%s</td>
            <td>%s</td>
            <td>%s</td>
            <td>%s</td>
            <td>%s</td>
            <td>
                <a type="button" class="btn btn-default btn-xs" href="/add/%s.html"> <span class="glyphicon glyphicon-start" aria-hidden="true"></span>添加</a>
            </td>
        </tr>"""

    html = ""

    for i in info:
        html +=  page_template % (i[0],i[1],i[2],i[3],i[4],i[5],i[6],i[7],i[1])

    content = re.sub(r"\{%content%\}", html, content)
    return content
     
@route("/center.html")
def center(res):
    with open("./templates/center.html") as f:
        content = f.read()

    # my_stock_info = "这里是从mysql查询出来的数据。。。"

    # content = re.sub(r"\{%content%\}", my_stock_info, content)

    conn = connect(host="localhost",port=3306,user="root",password="",database="stock_db",charset="utf8")
    cs = conn.cursor()
    cs.execute("select i.code,i.short,i.chg,i.turnover,i.price,i.highs,f.note_info from info as i inner join focus as f on i.id = f.info_id;")
    info = cs.fetchall()
    cs.close()
    conn.close()


    page_template = """
        <tr>
            <td>%s</td>
            <td>%s</td>
            <td>%s</td>
            <td>%s</td>
            <td>%s</td>
            <td>%s</td>
            <td>%s</td>
            <td>
                <a type="button" class="btn btn-default btn-xs" href="/update/%s.html"> <span class="glyphicon glyphicon-start" aria-hidden="true"></span>修改</a>
            </td>
            <td>
                <a type="button" class="btn btn-default btn-xs" href="/del/%s.html"> <span class="glyphicon glyphicon-start" aria-hidden="true"></span>删除</a>
            </td>
        </tr>"""

    # <input type="button" value="删除" id="toDel" name="toDel" systemidvaule=%s>

    html = ""

    for i in info:
        html +=  page_template % (i[0],i[1],i[2],i[3],i[4],i[5],i[6],i[0],i[0])
    
    content = re.sub(r"\{%content%\}", html, content)
   
    return content


@route(r"/add/(\d+)\.html")
def add_focus(res):
    #获取股票代码
    stock_code = res.group(1)
    #判断是否有这个股票
    conn = connect(host="localhost",port=3306,user="root",password="",database="stock_db",charset="utf8")
    cs = conn.cursor()
    sql = "select * from info where code=%s"
    cs.execute(sql,(stock_code,))
    if not cs.fetchone():
        cs.close()
        conn.close()
        return "没有这只股票.."
    #判断是否已经关注
    sql = "select * from info as i inner join focus as f on i.id=f.info_id where i.code=%s"
    cs.execute(sql,(stock_code,))
    if cs.fetchone():
        cs.close()
        conn.close()
        return "已经关注过了.."
    #添加关注
    else:
        sql = "insert into focus  (info_id) select id from info where code=%s"
        cs.execute(sql,(stock_code,))
        conn.commit()
        cs.close()
        conn.close()
        return "关注成功.."


@route(r"/del/(\d+)\.html")
def del_focus(res):
    #获取股票代码
    stock_code = res.group(1)
    #判断是否有这个股票
    conn = connect(host="localhost",port=3306,user="root",password="",database="stock_db",charset="utf8")
    cs = conn.cursor()
    sql = "select * from info where code=%s"
    cs.execute(sql,(stock_code,))
    if not cs.fetchone():
        cs.close()
        conn.close()
        return "没有这只股票.."
    #判断是否已经关注
    sql = "select * from info as i inner join focus as f on i.id=f.info_id where i.code=%s"
    cs.execute(sql,(stock_code,))
    #如果没有关注过,表示非法请求
    if not cs.fetchone():
        cs.close()
        conn.close()
        return "没有关注这只股票.."
    #取消关注
    else:
        sql = "delete from focus where info_id=(select id from info where code=%s);"
        cs.execute(sql,(stock_code,))
        conn.commit()
        cs.close()
        conn.close()
        return "取消关注成功.."


@route(r"/update/(\d+)\.html")
def show_update_page(res):
    #备注修改页面

    #打开修改模版
    with open("./templates/update.html") as f:
        content = f.read()
    
    #股票代码
    stock_code = res.group(1)

    #根据股票代码查询备注信息
    conn = connect(host="localhost",port=3306,user="root",password="",database="stock_db",charset="utf8")
    cs = conn.cursor()
    sql = "select note_info from focus inner join info on info.id=focus.info_id where info.code=%s"
    cs.execute(sql,(stock_code,))
    stock_info = cs.fetchone()
    cs.close()
    conn.close()

    content = re.sub(r"\{%note_info%\}",stock_info[0],content)
    content = re.sub(r"\{%code%\}",stock_code,content)

    return content

@route(r"/update/(\d+)/(.*)\.html")
def change_note(res):
    stock_code = res.group(1)
    note_info = res.group(2)
    print("old note_info",note_info)

    #URL解码后再存储
    note_info = urllib.parse.unquote(note_info)
    print("new note_info",note_info)
 
    conn = connect(host="localhost",port=3306,user="root",password="",database="stock_db",charset="utf8")
    cs = conn.cursor()
    sql="update focus set note_info=%s where info_id=(select id from info where code=%s)"
    cs.execute(sql,(note_info,stock_code))
    conn.commit()
    cs.close()
    conn.close()

    return "修改成功!"
def application(env, start_response):
    start_response('200 OK', [('Content-Type', 'text/html;charset=utf-8')])
    
    file_name = env['PATH_INFO']
    # file_name = "/index.py"
    # print("app_file_name",file_name)
    # print("dict",ROUTER_DICT)


# ROUTER_DICT = {
#   "r'/index.html'":index',
#   "r'/center.html'":center,
#   "r'/update/(\d*)\.html':add_focus
#.  "r'/del/(\d+)\.html':del_focus"
# }
    #添加log日志
    logging.basicConfig(level=logging.INFO,#控制台打印的日志级别
                    filename='./new.log',
                    filemode='a',##模式,有w和a,w就是写模式,每次都会重新写日志,覆盖之前的日志
                    #a是追加模式,默认如果不写的话,就是追加模式
                    format=
                    '%(asctime)s - %(pathname)s[line:%(lineno)d] - %(levelname)s: %(message)s'
                    #日志格式
                    )
    #记录访问的文件
    logging.info("访问的是:%s"%file_name)

    try:

        for url,func in ROUTER_DICT.items():
            #字典中的键url有"/index.html"、"/center.html"和正则"/add/\(d+)\.html"
            res = re.match(url,file_name)
           
            if res:
                print("res is true",res,func)
                return func(res)
        else:
            #记录错误
            logging.warning("没有对应的函数..")
            return "%s has not found..[未匹配]"%file_name
        

    except Exception as e:
        return "%s has not found[捕获异常]" % file_name

 

 

 

 

 

posted @ 2019-02-07 19:04  greenfan  阅读(189)  评论(0)    收藏  举报