纯手撸web框架

纯手撸web框架

一、Web应用的组成

接下来我们学习的目的是为了开发一个Web应用程序,而Web应用程序是基于B/S架构的,其中B指的是浏览器,负责向S端发送请求信息,而S端会根据接收到的请求信息返回相应的数据给浏览器,需要强调的一点是:S端由server和application两大部分构成,如图所示:

上图:Web应用组成

二、手鲁web应用

2.1 基本版

import socket

"""
@author RansySun
@create 2019-10-18-11:59
"""

# 创建服务端
server = socket.socket()
server.bind(("127.0.0.1", 8080))
server.listen(5)

while True:
    # 等待连接
    conn, addr = server.accept()

    # 接收浏览器发送的消息
    data = conn.recv(1024)
    print(data)
    # 请求行 请求头  空行 请求体, 返回响应首行
    conn.send(b'HTTP/1.1 200 OK \r\n\r\n Hello web')
    conn.close()

2.2 根据请求地址,返回请求内容

import socket

"""
@author RansySun
@create 2019-10-18-11:59
"""

# 创建服务端
server = socket.socket()
server.bind(("127.0.0.1", 8080))
server.listen(5)

while True:

    # 等待连接
    conn, addr = server.accept()

    # 接收服务端发送消息
    data = conn.recv(1024)

    # 获取请求内容
    data = str(data, encoding="utf8").split(" ")[1]

    # 发送请求头
    conn.send(b'HTTP/1.1 200 OK \r\n\r\n ')
    print(data)

    data = bytes(data, encoding="utf8")
    # 响应客户端
    conn.send(data)

2.3 根据请求地址返回响应html

<!-- index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>首页</h1>
</body>
</html>
<!-- index.html -->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>欢迎来到鸡公煲, baby</h1>
</body>
</html>
import socket

"""
@author RansySun
@create 2019-10-19-9:54
"""

# 创建连接对象
server = socket.socket()
server.bind(("127.0.0.1", 8080))
server.listen(4)

while True:

    # 等待连接
    conn, addr = server.accept()
    data = conn.recv(1024)

    # 接收客户端请求
    data = str(data, encoding="utf8").split(" ")[1]

    print(data)

    # 发送请求头
    conn.send(b"HTTP//1.1 200 OK \r\n\r\n")

    # 判断请求对象
    if data == '/index':

        # 返回页面请求
        with open("index.html", "rb") as fr:
            conn.send(fr.read())
    elif data == '/login':
        with open("login.html", "rb") as fr:
            conn.send(fr.read())
    else:
        conn.send(b"<h1 style='color:red'>404 error</h1>")

到此为止.....

三、Web框架的由来

综上案例我们可以发现一个规律,在开发S端时,server的功能是复杂且固定的(处理socket消息的收发和http协议的处理),而业务逻辑却各不相同(不同的软件就应该有不同的业务逻辑),重复开发复杂且固定的server是毫无意义的,有一个wsgiref模块帮我们写好了server的功能,这样我们便只需要专注于功能的编写

3.1 简易版

from wsgiref.simple_server import make_server

"""
@author RansySun
@create 2019-10-19-10:20
"""

def run(env, response):
    """

    :param env: 请求相关的所有数据
    :param response: 对页面做出相关响应
    :return:
    """

    # 发送请求
    response("200 OK \r\n\r\n", [])

    # 响应页面
    res = 'hello web'
    print(env.get("PATH_INFO"))
    return [res.encode('utf8')]

if __name__ == '__main__':
    server = make_server("127.0.0.1", 8080, run)

    # 实时监听地址,只要有客户端来连接, 统一交给run函数处理
    server.serve_forever()

3.2 根据请求做出响应

<!-- index -->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>首页</h1>
</body>
</html>
<!-- login -->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>欢迎来到鸡公煲, baby</h1>
</body>
</html>
<!-- get_time -->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
time
<body>

</body>
</html>
<!-- get_user -->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<p>{{ user }}</p>
<p>{{ user.name }}</p>
<p>{{ user['pwd'] }}</p>
<p>{{ user.get('hobby') }}</p>
<h1></h1>
<h1></h1>
</body>
</html>
<!-- get_db -->
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
    <link href="https://cdn.bootcss.com/twitter-bootstrap/3.3.1/css/bootstrap.min.css" rel="stylesheet">
    <script src="https://cdn.bootcss.com/twitter-bootstrap/3.3.1/js/bootstrap.min.js"></script>
</head>
<body>
<div class="container">
    <div class="row">
        <div class="col-md-6 col-md-offset-2">
            <h1 class="text-center"></h1>
            <table class="table table-bordered table-striped table-hover">
               <thead>
                    <tr>
                        <th>id</th>
                        <th>x</th>
                        <th>y</th>
                    </tr>
                </thead>
                <tbody>
                <tbody>
                    {% for user_dict in user %}
                        <tr>
                            <td>{{ user_dict.id }}</td>
                            <td>{{ user_dict.x }}</td>
                            <td>{{ user_dict.y }}</td>
                        </tr>
                    {% endfor %}
                </tbody>
                </tbody>
            </table>
        </div>
    </div>
</div>
</body>
</html>
# url.py
from views import *
"""
@author RansySun
@create 2019-10-19-10:49
"""
urls = [
    ('/index', index),
    ('/login', login),
    ('/xxx', xxx),
    ('/get_time', get_time),
    ('/get_user', get_user),
    ('/get_db', get_db),
]
# views.py
from datetime import datetime

"""
@author RansySun
@create 2019-10-19-10:49
"""

def index():
    return "index"

def login():
    return "login"

def xxx():
    return "xxx"

def error(env):
    return '404 error'

def get_time():
    """
    获取时间
    :return:
    """
    data_time = datetime.now().strftime('%Y-%m-%d %X')
    with open(r"templates\time.html", 'r', encoding='utf8') as fr:
        data = fr.read()
    data = data.replace("time", data_time)
    return data

from jinja2 import Template

def get_user():
    """
    前端通过字典获取用户信息
    :return:
    """
    dic = {'name': 'randy', 'pwd': '123123', 'hobby': ['read', 'running', 'music']}
    with open(r'templates/user.html', 'r', encoding="utf-8") as fr:
        data = fr.read()
    temp = Template(data)
    # 将字典dic传递给前端页面 页面上通过变量名user就能够获取到该字典
    res = temp.render(user=dic)
    return res

import pymysql

def get_db():
    mysql = pymysql.connect(
        host="127.0.0.1",
        user="root",
        password="root",
        charset="utf8",
        db="db1",
        autocommit=True
    )

    sql = "select * from a1"

    cursor = mysql.cursor(pymysql.cursors.DictCursor)
    cursor.execute(sql)

    res = cursor.fetchall()
    with open("templates/get_db.html", "r", encoding='utf8') as fr:
        data = fr.read()
    # print(res)

    temp = Template(data)
    data = temp.render(user=res)
    return data
# wsgiref.py

from wsgiref.simple_server import make_server
from url import *
from views import *

"""
@author RansySun
@create 2019-10-19-10:20
"""

def run(env, response):
    """

    :param env: 请求相关的所有数据
    :param response: 对页面做出相关响应
    :return:
    """

    # 发送请求
    response("200 OK", [])

    # 获取连接请求后缀
    resp = env.get("PATH_INFO")

    # 用来存储后续匹配到的函数名
    func = None

    # 查找匹配的后缀函数
    for url in urls:
        if resp == url[0]:
            func = url[1]
            break

    # 判断func是否有值
    if func:
        res = func()
    else:
        res = error(env)

    return [res.encode('utf8')]

if __name__ == '__main__':
    server = make_server("127.0.0.1", 8080, run)

    # 实时监听地址,只要有客户端来连接, 统一交给run函数处理
    server.serve_forever()

至此,我们就针对web开发的开发自定义了一个框架,所以说框架的本质就是一系列功能的集合体、不同的功能放到不同的文件中。有了该框架,可以让我们专注于业务逻辑的编写,极大的提高了开发web应用的效率(开发web应用的框架可以简称为web框架),比如我们新增一个业务逻辑,要求为:浏览器输入http://127.0.0.1:8011/home 就能访问到home.html页面,在框架的基础上具体开发步骤如下:

步骤一:在templates文件夹下新增home.html

步骤二:在url.py的urls中新增一条映射关系

urls = [
    ('/index', index),
    ('/timer', timer),
    ('/home', home), # 新增的映射关系
]

步骤三:在views.py中新增一个名为home的函数

def home(environ):
    with open('templates/home.html', 'r',encoding='utf-8') as f:
        data = f.read()
    return data.encode('utf-8')

我们自定义的框架功能有限,在Python中我们可以使用别人开发的、功能更强大的Django框架

原文地址:https://www.cnblogs.com/randysun/p/11708708.html

时间: 2024-10-08 06:13:16

纯手撸web框架的相关文章

Python Django前奏手撸web框架 基于wsgiref的web框架

基于socke手撸web框架 # 请求首行 b'GET / HTTP/1.1\r\n #GET /index HTTP/1.1\r\n (index)为浏览器请求地址) # 请求头 Host: 127.0.0.1:8080\r\n Connection: keep-alive\r\n Cache-Control: max-age=0\r\n Upgrade-Insecure-Requests: 1\r\n # User-Agent用来标识是不是浏览器 User-Agent: Mozilla/5.

手撸WEB框架

手撸web框架 软件开发的架构 C/S架构: 客户端 / 服务端 B/S架构: 浏览器 / 服务端 bs的本质也是cs HTTP协议 http是一种超文本传输协议 1.四大特性 基于TCP/I P之上作用于应用层 基于请求响应 无状态 (cookie session token..) 无连接 (长连接 websocket ( http 协议的大补丁)) 2.数据格式 请求格式 请求首行(请求方式, 协议版本.) 请求头(是一大堆k: v键值对) 注意请求头和请求体之间的空格\r\n 请求体(真正

纯手写SpringBoot框架之注解方式启动SpringMVC容器

使用Java语言创建Tomcat容器,并且通过Tomcat执行Servlet,接下来,将会使用Java语言在SpringBoot创建内置Tomcat,使用注解方式启动SpringMVC容器. 代码实现.1.pom.xml文件,需要依赖的jar包. <dependencies> <!--Java语言操作Tomcat--> <dependency> <groupId>org.apache.tomcat.embed</groupId> <arti

手写web框架之加载配置项目

一  定义框架配置项 在项目的src/main/resources目录下创建一个名为smart.propertiesd的文件,文件的内容如下: 1 smart.framework.jdbc.driver=com.mysql.jdbc.Driver 2 smart.framework.jdbc.url=jdbc:mysql://localhost:3306/jack 3 smart.framework.jdbc.username=root 4 smart.framework.jdbc.passwo

手写web框架之实现Bean容器

实现Bean容器 使用ClassHelper可以获取所加载的类,但无法通过类来实例化对象,因此我们需要提供一个反射工具类,让它封装java反射相关的API,对外提供更好用的工具方法.将该类命名为ReflectionUtil,代码如下: 1 package org.smart4j.framework.org.smart4j.framework.util; 2 3 import org.slf4j.Logger; 4 import org.slf4j.LoggerFactory; 5 import

真&#183;纯手撸高精度模板

耗时(50分钟)不压位 内容只有高精度+-*,因为其他我不会写QAQ~ 均ACluogu,codevs #include<bits/stdc++.h> using namespace std; const int N =(int)1e5+10; struct bignum { int m[N],len; char str[N]; int ok; bignum() {ok=1;len=1,memset(m,0, sizeof(m));} void in() {scanf("%s&quo

web框架基础

HTTP协议(超文本协议) 四大特性 基于TCP/IP之上作用于应用层 基于请求响应 发是请求,给是响应 无状态 不保存用户状态,连一次就给忘了 无连接 eg:one night love 数据格式 请求格式 请求首行(请求方式,协议版本等) 请求头(一大堆K:V键值对) \r\n 请求头(真正的数据 发post请求的时候才有 如果get请求不会有) 响应格式 响应首行 响应头 \r\n 响应体 响应状态码 用特定的数字表示一些数据 ? 1xx:服务端已经接收到了你的数据 正在处理 你可以提交其

web框架学习

目录 web框架学习 HTTP协议(超文本协议) 四大特性 数据格式 请求方式 纯手撸web框架 简单c/s连接 稍微复杂web框架 基于wsgiref 客户端通过访问服务器获取字典 动静态页面 客户端通过访问服务器获取当前时间 客户端通过访问服务器获取数据库数据 python三大主流web框架 web框架学习 HTTP协议(超文本协议) 四大特性 基于TCP/IP之上作用于应用层 基于请求响应 发是请求,给是响应 无状态 不保存用户状态,连一次就给忘了 无连接 eg:one night lov

Django框架介绍 python三大主流web框架之一

一.学习准备 1.下载安装Django(建议安装1.x版本) 方法:终端cmd输入命令:pip install django==1.11.11  然后回车即可 校验是否安装成功:django-admin 二.纯手撸web框架 1.纯手撸web框架 软件开发架构 c/s架构 b/s架构 本质bs也是cs web后端 需求: 1.根据用户输入不同的后缀返回不同的内容 从符合http协议格式的数据中获取用户输入的后缀 不足之处: 1.socket代码是我们自己写的 2.http数据也是我们自己处理的