本篇主要介绍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. 时间工具类DateUtil

    import java.sql.Timestamp; import java.text.ParseException; import java.text.SimpleDateFormat; impor ...

  2. 【Linux】walle 部署上线单报错:mv: cannot overwrite directory ‘/www’ with non-directory

    错误截图 问题分析:项目设置中. 目标集群部署路径错误, 举例: 假设你 项目名称:laofan 在目标服务器的路径: /www/wwwdata/laofan 那么你在标集群部署路径 就可以写: /w ...

  3. TypeScript 菜鸟教程

    非常好的Js教程,web api,canvas API教程 https://wangdoc.com/ 语法基础 https://www.runoob.com/typescript/ts-install ...

  4. 基于EasyNVR摄像机流媒体服务器实现RTSP或Onvif监控摄像头Web无插件化直播监控

    前言介绍 随着互联网的发展,尤其是移动互联网基于H5.微信的应用越来越多,企业也更多地想基于H5.微信公众号来快速开发和运营自己的产品,而传统的安防IPC所输出的各种RTSP.GB28181.SDK视 ...

  5. 查看rpm包spec文件

    $ rpm --scripts -qp kernel-2.6.32-431.el6.x86_64.rpm

  6. [资料]ObjectARX 2020参考指南翻译中文版

    chm使用Google Chrome浏览器翻译,有些翻译不是很理想,因为2万5千多个html文件, 修正难度太大,所以只处理了一部分. 非常感谢 gzxl 辛苦肉眼修正一些翻译问题. 欢迎进入QQ群: ...

  7. springboot统一返回json数据格式并配置系统异常拦截

    本文链接:https://blog.csdn.net/syystx/article/details/82870217通常进行前后端分离开发时我们需要定义统一的json数据交互格式并对系统未处理异常进行 ...

  8. word 转化为PDF 目录没了

    https://jingyan.baidu.com/article/ca00d56c5d5f8de99febcf54.html 点文件-->导出-->创建PDF-->选项--> ...

  9. 数据结构-二叉树的遍历实现笔记C++

    二叉树的遍历实现,可以用递归的方法也可以用非递归的方法.非递归的方法可以借助栈(前序遍历,中序遍历,后序遍历),也可以借助队列(层次遍历).本次笔记只使用了递归的方法来进行前序遍历,中序遍历,后序遍历 ...

  10. 基于 Docker 和 GitLab 的前端自动化部署实践笔记

    基于 Docker 和 GitLab 的前端自动化部署 实践笔记 随着接触的项目越来越多,在部署测试流程上重复耗时工作也越来越多,所以对前端工作的CI/CD实现愈发迫在眉睫. 前端开发由于三大框架的崛 ...