本篇主要介绍WSGI-web-mini框架的基本实现,以及什么是WSGI协议、对于浏览器的资源请求服务端是如何处理的等相关知识;

一、浏览器资源请求

  我们知道浏览器和web服务器之间是基于HTTP协议进行文件的传输的,而根据请求消息的不同,服务器处理的流程也是不同的;如下图:

  通常而言:

   对于浏览器请求的静态资源,服务器在收到请求消息时(处理完后),会直接在服务器的本地磁盘中将信息(index.html页面)读取出来,直接发送给web浏览器;

   而对于动态资源的请求,服务器通常会调用web框架来处理,而web框架会根据用户的请求不同,从数据库中读取不同的信息将其替换自HTML模板中,并且返回给HTTP服务器,最后由服务器将消息发送给web浏览器;

二、WSGI协议

 2.1 为什么要使用WSGI协议呢?

  思考:在以前,选择  Python-web架构 会受制于可用的 web服务器,反之亦然。为了让web架构和服务器可以协同工作,但有可能面对(或者曾有过)下面的问题,当要把一个服务器和一个架构结合起来时,却发现他们不是被设计成协同工作的;

  那么,怎么可以不修改服务器和架构代码而确保可以在多个架构下运行web服务器呢?

      

  答案就是 Python Web Server Gateway Interface (或简称 WSGI,读作“wizgy”)。

  WSGI允许开发者将选择web框架和web服务器分开。可以混合匹配web服务器和web框架,选择一个适合的配对。比如,可以在Gunicorn 或者 Nginx/uWSGI 或者 Waitress上运行 Django, Flask, 或 Pyramid。真正的混合匹配,得益于WSGI同时支持服务器和架构;

 2.2 WSGI接口

  而通常web服务器必须具备WSGI接口,所有的现代Python Web框架都已具备WSGI接口,它让你不对代码作修改就能使服务器和特点的web框架协同工作。

  WSGI由web服务器支持,而web框架允许你选择适合自己的配对,但它同样对于服务器和框架开发者提供便利使他们可以专注于自己偏爱的领域和专长而不至于相互牵制。其他语言也有类似接口:java有Servlet API,Ruby 有 Rack。

  我们需在web框架内定义一个WSGI接口函数,而web服务器与框架进行协同工作时,只需通过该接口函数即可,其他的实现均封装在该框架的底部;该接口函数如下:

# WSGI接口函数
def application(environ, start_response):
start_response('200 OK', [('Content-Type', 'text/html')])
return 'Hello World!'

 参数:

  environ  :一个包含所有HTTP请求信息的dict对象;即告诉框架需要调取哪些动态资源页面;

  start_response :一个发送HTTP响应的函数。该函数相当于HTTP服务器给与框架的一个容器,而框架将头部信息通过参数的方式存放在该函数内,最后服务器再从中取出;

 返回值:

  返回的是请求的动态资源的响应消息的body部分;通常web框架将动态资源替换HTML模板的消息返回给服务器;

三、实例:

  其大致结构如下:

  

  web服务器:

import socket
import multiprocessing
import re
# import dynamic.mini_frame
import sys class WSGIServer(object):
def __init__(self,port,app,static_path):
# 1.创建监听套接字
self.server_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
# 2.为了服务端先断开时,客户端马上能链接
self.server_socket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) # 3.绑定本地端口
self.server_socket.bind(("",port))
# 4.监听
self.server_socket.listen(128) self.port = port
self.application = app
self.static_path = static_path def deal_with_static(self,new_socket):
# 如果不是以.py结尾的文件,当成静态页面处理
try:
f=open("static"+ self.file_name,"rb")
except:
header = "HTTP/1.1 404 NOT FOUND FILE\r\n"
header += "\r\n"
body = "<h1>not found file <\h1>"
response = header+body
new_socket.send(response.encode("utf-8"))
else:
header="HTTP/1.1 200 OK\r\n"
header += "\r\n"
body = f.read()
response = header.encode("utf-8") + body
new_socket.send(response) def deal_with_dynamic(self,new_socket):
"""处理动态页面"""
env = dict()
env["PATH_INFO"] = self.file_name # web框架的接口函数
body = self.application(env,self.set_response_header) # headr部分的拼接成指定格式
header= "HTTP/1.1 %s"%self.status
for temp in self.header:
header += "%s:%s\r\n" % (temp[0], temp[1])
header+="\r\n"
print(header) new_socket.send(header.encode("utf-8"))
new_socket.send(body.encode("utf-8")) def set_response_header(self,status,header):
"""作为接口函数的参数,相当于容器接收web框架返回的头部信息"""
self.status = status;
self.header = header; def serve_client(self,new_socket):
"""接收请求消息和发送相应消息"""
# 1.接受请求消息 GET / HTTP/1.1
request = new_socket.recv(1024).decode("utf-8") # 2.解析请求消息
request_lines = request.splitlines()
ret = re.match(r"[^/]+(/[^ ]*)",request_lines[0])
if ret:
self.file_name = ret.group(1)
if self.file_name =="/":
self.file_name = "/index.html"
# print(file_name) # 3.尝试打开文件,若文件存在则能打开,否则发送404
if not self.file_name.endswith(".py"):
# 处理静态网页
self.deal_with_static(new_socket) # new_socket.close()
else:
# 处理动态网页
self.deal_with_dynamic(new_socket) new_socket.close() def run_forever(self):
"""当成主函数"""
while True:
new_socket,client_addr = self.server_socket.accept()
p = multiprocessing.Process(target=self.serve_client,args=(new_socket,))
p.start()
p.join() new_socket.close()
self.server_socket.close() def main():
# 运行服务器时,给出指定的 端口和运行的框架
if len(sys.argv)==3:
try:
port=int(sys.argv[1]) #
frame_app_name = sys.argv[2] # mini_frame:application
except Exception as e:
print("输入方式有误,请按照以下方式运行:")
print("python3 web_server.py 6968 mini_frame:application")
return
ret = re.match(r"([^:]+):(.*)",frame_app_name) # 获取框架文件名
if ret:
frame_name = ret.group(1)
app_name = ret.group(2)
else:
print("您的输入方式有误,请按照上述方式运行")
return with open("./web_server.conf","r") as f:
conf_info = eval(f.read()) # 将字符串转为字典类型 # 将导入动态数据的模块添加到python解释器的环境变量中
sys.path.append(conf_info["dynamic_path"])
print(sys.path) frame =__import__(frame_name) # 导入指定的模块
app = getattr(frame,app_name) # 反射出该模块下的指定的函数app_name wsgi_server = WSGIServer(port,app,conf_info["static_path"])
wsgi_server.run_forever() if __name__ == '__main__':
main()

web服务端

 解析:

  1、在web服务器中,我们首先根据资源的请求不同,给出的处理方式不同即静态资源直接从本地磁盘读取,而动态资源交给web框架处理。

  2、在与web框架进行交互,调用了wsgi接口函数,传入了字典env,用来告诉服务器需求页面;以及函数set_response_header用来获取web框架传递的头部信息;并且将返回值作为body;整个与web框架的交互均是围绕着wsgi接口函数来实现的;

  3、随后便是让我们的服务器运行可以指定端口和web框架来运行,则定义了main函数下面的一些代码,通过sys.argv来获取到指定的端口和web_frame:application等,再将这些作为参数传入类 WSGIServer中来执行;

  mini-web框架

import re

def index():
"""显示index.py动态数据"""
with open("./templates/index.html","r") as f:
content=f.read()
# print(content)
my_stock_info = "这是是数据库的数据,未完待续。"
content = re.sub(r"\{%content%\}", my_stock_info, content)
return content def center():
"""显示center动态数据"""
with open("./templates/center.html","r") as f:
content = f.read()
# print(content)
mys_stock_info = "这是数据库的数据,未完待续。"
content = re.sub(r"\{%content%\} ",mys_stock_info,content)
return content def application(environ,start_response):
start_response("200 OK\r\n",[('Content-Type', 'text/html;charset=utf8')])
file_name=environ["PATH_INFO"]
if file_name == "/index.py":
return index()
elif file_name == "/center.py":
return center()
else:
start_response("400 NOT FOUND FILE\r\n",[('Content-Type', 'text/html;charset=utf8')])
return "Sorry,the file you want get have not found;"

web—mini框架

  在该框架内:定义了wsgi接口函数,以及获取指定页面的函数,在下篇中我们将会介绍如何将数据库的内容导入;

  

  web_frame.conf 配置文件

{
"static_path":"./static",
"dynamic_path":"./dynamic"
}

  配置文件主要用来指定:动态资源及静态资源存储位置,当请求动态资源时,将这些路径添加至python解释器的环境变量中去,方便web框架模块的导入;

  run.sh脚本运行文件

python3 web_server.py 6868 mini_frame:application

  定义脚本运行文件,主要是方便运行,不至于每次写一大坨东西去执行;

  over~~~ 下篇中会实现路由的功能,并且替换成数据库中的数据~~~

web-mini框架的基本实现(一)的更多相关文章

  1. 国产 WEB UI 框架 (收费)-- Quick UI,Mini UI

    国产 WEB UI 框架 (收费)-- Quick UI,Mini UI : http://www.uileader.com/ http://www.miniui.com/

  2. React 还是 Vue: 你应该选择哪一个Web前端框架?

    学还是要学的,用的多了,也就有更多的认识了,开发中遇到选择的时候也就简单起来了. 本文作者也做了总结: 如果你喜欢用(或希望能够用)模板搭建应用,请使用Vue    如果你喜欢简单和“能用就行”的东西 ...

  3. 学习ASP.NET Web API框架揭秘之“HTTP方法重写”

    最近在看老A的<ASP.NET Web API 框架揭秘>,这本书对于本人现阶段来说还是比较合适的(对于调用已经较为熟悉,用其开发过项目,但未深入理解过很多内容为何可以这样“调用”).看到 ...

  4. L20n – Mozilla 推出的 Web 本地化框架

    L20n是 Mozilla 开发的用于 Web 开发的本地化框架.它允许本地化开发者把逻辑细分为本地化的资源. L20n 的框架不再需要开发人员深入理解自然语言的具体细节,并提供了机会为本地化创造更好 ...

  5. tornado 学习笔记2 Python web主流框架

    2.1 Django 官方网址:https://www.djangoproject.com/ 简介:Django is a high-level Python Web framework that e ...

  6. 【转】谈谈Google Polymer以及Web UI框架的未来

    原文转自:http://www.csdn.net/article/2013-05-27/2815450-google-polymer 摘要:开发者Axel Rauschmayer在自己的博客上详解了G ...

  7. Spring 4 官方文档学习(十一)Web MVC 框架之配置Spring MVC

    内容列表: 启用MVC Java config 或 MVC XML namespace 修改已提供的配置 类型转换和格式化 校验 拦截器 内容协商 View Controllers View Reso ...

  8. Node.js简单介绍并实现一个简单的Web MVC框架

    编号:1018时间:2016年6月13日16:06:41功能:Node.js简单介绍并实现一个简单的Web MVC框架URL :https://cnodejs.org/topic/4f16442cca ...

  9. Web自动化框架LazyUI使用手册(2)--先跑起来再说(第一个测试用例-百度搜索)

    作者:cryanimal QQ:164166060 上篇文章中,简要介绍了LazyUI框架,本文便来演示,如何从无到有快速搭建基于lazyUI的工程,并成功运行第一个测试用例. 本文以百度搜索为例,选 ...

  10. 【JavaScript】谈谈Google Polymer以及Web UI框架的未来

    摘要:开发者Axel Rauschmayer在自己的博客上详解了Google Polymer的设计理念与组成架构,深得Polymer开发者的认同.他认为Polymer这样高互操作性的设计才应该是Web ...

随机推荐

  1. 转 : 请问mysql如何确定一个库是主库还是从库。

    select user,host from mysql.user;SELECT Repl_slave_priv,Repl_client_priv,super_priv,host FROM mysql. ...

  2. spring boot 配置虚拟目录

    如上图,关键地方有两个: 1.下方的 web.upload-path (配置本地文件路径) 2.上方一串配置,具体代码如下: profiles: include: paperIdentify acti ...

  3. ActiveMQ学习教程

    一.activemq安装 官网地址:https://activemq.apache.org/ 具体安装过程不赘述,解压即安装, 二.使用 activemq有queue和topic两种模式, 我们以qu ...

  4. LeetCode 788. 旋转数字(Rotated Digits) 36

    788. 旋转数字 788. Rotated Digits 题目描述 我们称一个数 X 为好数, 如果它的每位数字逐个地被旋转 180 度后,我们仍可以得到一个有效的,且和 X 不同的数.要求每位数字 ...

  5. 《算法 - 一致性 (hash) 算法》

    图片摘自: 每天进步一点点——五分钟理解一致性哈希算法(consistent hashing) 一:背景 - 一致性哈希算法在1997年由麻省理工学院的Karger等人在解决分布式Cache中提出的. ...

  6. 树卷积神经网络Tree-CNN: A Deep Convolutional Neural Network for Lifelong Learning

    树卷积神经网络Tree-CNN: A Deep Convolutional Neural Network for Lifelong Learning 2018-04-17 08:32:39 看_这是一 ...

  7. 系统开启UAC情形下开机自启动程序如何以管理员权限启动

    系统开启UAC情形下开机自启动程序如何以管理员权限启动 题记:本文阐述的是在Windows系统开启UAC的情况下,开机自启动程序需要以管理员权限启动, 系统弹出UAC对话框,用户同意的情形下启动程序 ...

  8. UnityShader - 渲染管线

    定义: 显卡内部处理图像信号的并行处理单元,也称为渲染流水线 发生位置: CPU和GPU 渲染机理: 将图像所具备的图形信息(顶点.纹理.材质.摄像机位置等)经过一系列阶段的处理,最终转换为屏幕上的图 ...

  9. 手写RPC框架(netty+zookeeper)

    RPC是什么?远程过程调用,过程就是业务处理.计算任务,像调用本地方法一样调用远程的过程. RMI和RPC的区别是什么?RMI是远程方法调用,是oop领域中RPC的一种实现,我们熟悉的restfull ...

  10. CCF 2016-09-2 火车购票

    CCF 2016-09-2 火车购票 题目 问题描述 请实现一个铁路购票系统的简单座位分配算法,来处理一节车厢的座位分配. 假设一节车厢有20排.每一排5个座位.为方便起见,我们用1到100来给所有的 ...