一、简单web(socket)

在前一篇WEB框架概述一文中已经详细了解了:从浏览器键入一个URL到返回HTML内容的整个过程。说到底,本质上其实就是一个socket服务端,用户的浏览器其实就是一个socket客户端。

最简单的Hello World程序如下:

import socket

HOST = ''
PORT = 80
listen_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
listen_socket.bind((HOST, PORT))
listen_socket.listen(1)
connection, address = listen_socket.accept()
request = connection.recv(1024)
connection.sendall(b"""HTTP/1.1 200 OK
Content-type: text/html <html>
<body>
<h1>Hello, World!</h1>
</body>
</html>""")
connection.close()

 

这个代码接收简单的连接和一个客户端单一的请求,不管请求的 URL 是什么,它都会响应 HTTP 200(所以,这并不是一个真正意义上的 web 服务器)。Content-type:text/html 行代码的是 header 字段,header 用来提供请求或者响应的元信息。

我们从浏览器请求,可以得到如下结果:

这就是最简单的WEB应用。

如果要动态生成HTML,就需要把上述步骤自己来实现,每次定义发送和接受的内容。不过,接受HTTP请求、解析HTTP请求、发送HTTP响应都是苦力活,如果我们自己来写这些底层代码,还没开始写动态HTML呢,就得花个把月去读HTTP规范。正确的做法是底层代码由专门的服务器软件实现,我们用Python专注于生成HTML文档。因为我们不希望接触到TCP连接、HTTP原始请求和响应格式,所以,需要一个统一的接口,让我们专心用Python编写Web业务。这个接口就是前面介绍过的WSGIWeb Server Gateway Interface。WSGI就是一种协议,描述web server(uwsgi)如何与web application(app)通信的规范。serverapplication的规范在PEP 3333中有具体描述。要实现WSGI协议,必须同时实现web server和web application,当前运行在WSGI协议之上的web框架有BottleFlaskDjango

当然,在python中,我们可以通过WSGIref来演示一个WEB框架的实现过程。

二、Web框架实现(Wsgiref)

Wsgiref库我们在前面已经有详细认识,所以这里不再介绍。

通过Wsgiref实现一个简单的WEB sever如下:

from wsgiref.simple_server import make_server
#1、符合WSGI规范的application
def application(environ, start_response):
start_response('200 OK', [('Content-Type', 'text/html')])
return [b'<h1>Hello, world!</h1>']

#2、Wsgiref定义启动server
httpd = make_server('', 80, application)
print('Serving HTTP on port 80...')
#3、开始监听HTTP请求:
httpd.serve_forever()

  用户访问结果如下:

我们从Wsgiref一文中了解到,environ其实是收集了一些环境变量(包括服务端的环境变量、客户端的请求信息以及wsgi信息),我们可以将其打印出来,添加代码:

for k,v in environ.items():
print k,v
TMP C:\Users\admin\AppData\Local\Temp
PYTHONIOENCODING UTF-8
COMPUTERNAME ADMIN-PC
wsgi.multiprocess False
_OLD_VIRTUAL_PATH C:\ProgramData\Oracle\Java\javapath;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;D:\install soft\python2.7
USERDOMAIN admin-PC
SERVER_PROTOCOL HTTP/1.1
SERVER_SOFTWARE WSGIServer/0.1 Python/2.7.15
PSMODULEPATH C:\Windows\system32\WindowsPowerShell\v1.0\Modules\
SCRIPT_NAME
COMMONPROGRAMFILES C:\Program Files\Common Files
PROCESSOR_IDENTIFIER Intel64 Family 6 Model 58 Stepping 9, GenuineIntel
REQUEST_METHOD GET
PROGRAMFILES C:\Program Files
PROCESSOR_REVISION 3a09
PATH C:\ProgramData\Oracle\Java\javapath;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;D:\install soft\python2.7;D:\xuequn\venv\Scripts
QUERY_STRING
SYSTEMROOT C:\Windows
PYTHONUNBUFFERED 1
PROGRAMFILES(X86) C:\Program Files (x86)
WINDOWS_TRACING_FLAGS 3
CONTENT_LENGTH
HTTP_UPGRADE_INSECURE_REQUESTS 1
VIRTUAL_ENV D:\xuequn\venv
HTTP_CACHE_CONTROL max-age=0
HTTP_CONNECTION keep-alive
TEMP C:\Users\admin\AppData\Local\Temp
REMOTE_ADDR 127.0.0.1
COMMONPROGRAMFILES(X86) C:\Program Files (x86)\Common Files
PROCESSOR_ARCHITECTURE AMD64
wsgi.url_scheme http
ALLUSERSPROFILE C:\ProgramData
SERVER_PORT 80
LOCALAPPDATA C:\Users\admin\AppData\Local
HOMEPATH \Users\admin
PYCHARM_MATPLOTLIB_PORT 50538
PROGRAMW6432 C:\Program Files
USERNAME admin
HTTP_ACCEPT text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
LOGONSERVER \\ADMIN-PC
PROMPT (venv) $P$G
COMSPEC C:\Windows\system32\cmd.exe
PROGRAMDATA C:\ProgramData
PYTHONPATH D:\install soft\pycharm\PyCharm 2018.1.4\helpers\pycharm_matplotlib_backend;D:\xuequn
wsgi.multithread True
wsgi.input <socket._fileobject object at 0x0000000002900B10>
HTTP_USER_AGENT Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.84 Safari/537.36
HTTP_HOST localhost
SESSIONNAME Console
PATHEXT .COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC
PATH_INFO /
FP_NO_HOST_CHECK NO
WINDIR C:\Windows
wsgi.file_wrapper wsgiref.util.FileWrapper
HTTP_ACCEPT_ENCODING gzip, deflate, br
wsgi.version (1, 0)
APPDATA C:\Users\admin\AppData\Roaming
HOMEDRIVE C:
SERVER_NAME admin-PC
wsgi.run_once False
REMOTE_HOST admin-PC
SYSTEMDRIVE C:
GATEWAY_INTERFACE CGI/1.1
HTTP_ACCEPT_LANGUAGE zh-CN,zh;q=0.9,en;q=0.8
PYCHARM_HOSTED 1
NUMBER_OF_PROCESSORS 4
_OLD_VIRTUAL_PROMPT $P$G
PROCESSOR_LEVEL 6
CONTENT_TYPE text/plain
wsgi.errors <open file '<stderr>', mode 'w' at 0x0000000001D62150>
COMMONPROGRAMW6432 C:\Program Files\Common Files
OS Windows_NT
PUBLIC C:\Users\Public
USERPROFILE C:\Users\admin
TMP C:\Users\admin\AppData\Local\Temp
PYTHONIOENCODING UTF-8
COMPUTERNAME ADMIN-PC
wsgi.multiprocess False
_OLD_VIRTUAL_PATH C:\ProgramData\Oracle\Java\javapath;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;D:\install soft\python2.7
HTTP_REFERER http://localhost/
USERDOMAIN admin-PC
SERVER_PROTOCOL HTTP/1.1
SERVER_SOFTWARE WSGIServer/0.1 Python/2.7.15
PSMODULEPATH C:\Windows\system32\WindowsPowerShell\v1.0\Modules\
SCRIPT_NAME
COMMONPROGRAMFILES C:\Program Files\Common Files
PROCESSOR_IDENTIFIER Intel64 Family 6 Model 58 Stepping 9, GenuineIntel
REQUEST_METHOD GET
PROGRAMFILES C:\Program Files
PROCESSOR_REVISION 3a09
PATH C:\ProgramData\Oracle\Java\javapath;C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\Windows\System32\WindowsPowerShell\v1.0\;D:\install soft\python2.7;D:\xuequn\venv\Scripts
QUERY_STRING
SYSTEMROOT C:\Windows
PYTHONUNBUFFERED 1
PROGRAMFILES(X86) C:\Program Files (x86)
WINDOWS_TRACING_FLAGS 3
CONTENT_LENGTH
VIRTUAL_ENV D:\xuequn\venv
HTTP_CACHE_CONTROL no-cache
HTTP_CONNECTION keep-alive
TEMP C:\Users\admin\AppData\Local\Temp
REMOTE_ADDR 127.0.0.1
COMMONPROGRAMFILES(X86) C:\Program Files (x86)\Common Files
PROCESSOR_ARCHITECTURE AMD64
wsgi.url_scheme http
ALLUSERSPROFILE C:\ProgramData
SERVER_PORT 80
LOCALAPPDATA C:\Users\admin\AppData\Local
HOMEPATH \Users\admin
PYCHARM_MATPLOTLIB_PORT 50538
PROGRAMW6432 C:\Program Files
USERNAME admin
HTTP_ACCEPT image/webp,image/apng,image/*,*/*;q=0.8
LOGONSERVER \\ADMIN-PC
PROMPT (venv) $P$G
COMSPEC C:\Windows\system32\cmd.exe
PROGRAMDATA C:\ProgramData
PYTHONPATH D:\install soft\pycharm\PyCharm 2018.1.4\helpers\pycharm_matplotlib_backend;D:\xuequn
wsgi.multithread True
wsgi.input <socket._fileobject object at 0x0000000002900B10>
HTTP_USER_AGENT Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.84 Safari/537.36
HTTP_HOST localhost
SESSIONNAME Console
PATHEXT .COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC
PATH_INFO /favicon.ico
FP_NO_HOST_CHECK NO
WINDIR C:\Windows
wsgi.file_wrapper wsgiref.util.FileWrapper
HTTP_ACCEPT_ENCODING gzip, deflate, br
wsgi.version (1, 0)
APPDATA C:\Users\admin\AppData\Roaming
HOMEDRIVE C:
SERVER_NAME admin-PC
wsgi.run_once False
REMOTE_HOST admin-PC
SYSTEMDRIVE C:
GATEWAY_INTERFACE CGI/1.1
HTTP_ACCEPT_LANGUAGE zh-CN,zh;q=0.9,en;q=0.8
PYCHARM_HOSTED 1
NUMBER_OF_PROCESSORS 4
_OLD_VIRTUAL_PROMPT $P$G
PROCESSOR_LEVEL 6
HTTP_PRAGMA no-cache
CONTENT_TYPE text/plain
wsgi.errors <open file '<stderr>', mode 'w' at 0x0000000001D62150>
COMMONPROGRAMW6432 C:\Program Files\Common Files
OS Windows_NT
PUBLIC C:\Users\Public
USERPROFILE C:\Users\admin

  

以上是实现了一个简单的请求和响应的过程,但是每次请求都是响应的固定不变的内容(hello world!)。现实当中,我们肯定希望是动态的内容,而且一般是通过请求不同的URL来返回不同的HTML内容。

所以,我们需要解决动态路由的问题。

从上面的基本信息中我们可以找到一个非常有用的信息:PATH_INFO。其实,这个变量就是代表了当前请求的URL。返回的内容我们可以很容易解决,通过函数返回不同的HTML内容就可以了。

#coding:utf-8
from wsgiref.simple_server import make_server def user():
return ['<h1>hello jay!</h1>'] def test():
return ['<h1>Just a test</h1>'] url_map = {'user':user,'test':test} #Flask里面就是通过url_map进行URL对象保存 def application(environ, start_response):
path=environ['PATH_INFO'].split('/')[1]
start_response('200 OK', [('Content-Type', 'text/html')]) if path in url_map: #这里比较LowB了,Flask里面会把URL和视图函数进行绑定。
return url_map[path]()
else:
return ["<h1>Page 404,not found!</h1>".encode("utf8")] httpd = make_server('', 80, application)
print('Serving HTTP on port 80...')
# 开始监听HTTP请求:
httpd.serve_forever()

  

  这样,我们就把用户通过不同URL访问的内容进行了不同的响应,效果如下:

当然,如果是真实环境下,我们会从数据库中获取数据,把固定的内容替换成可变的HTML内容,这样一个简单的web框架就成型了,是不是So easy?

二、Web框架实现的更多相关文章

  1. 蜗牛历险记(二) Web框架(中)

    上篇简单介绍了框架所使用的Autofac,采用Autofac提供的Ioc管理整个Web项目中所有对象的生命周期,实现框架面向接口编程.接下来介绍框架的日志系统. 一.介绍之前 框架日志是否有存在的必要 ...

  2. 蜗牛历险记(二) Web框架(下)

    Web框架第三篇--缓存篇 缓存的优劣很大程度上决定了框架的效率,一个有节操的缓存它应该是高效的,利用率高的,具备更多扩展功能的. 一.介绍之前 计算机各个硬件的运行效率是不一样的,CPU>&g ...

  3. 蜗牛历险记(二) Web框架(上)

    接上篇所说,本篇主要内容是讲述如何使用Autofac来管理整个平台的生命周期(初级). 一.简述 插件式Web开发的同学应该还会记得PreApplicationStartMethod这个Assembl ...

  4. Python之Web框架

    Python之Web框架: 一.  Web框架的本质: 对于所有的Web应用,本质上其实就是一个socket服务端,用户的浏览器其实就是一个socket客户端. #!/usr/bin/env pyth ...

  5. Python开发【第二十二篇】:Web框架之Django【进阶】

    Python开发[第二十二篇]:Web框架之Django[进阶]   猛击这里:http://www.cnblogs.com/wupeiqi/articles/5246483.html 博客园 首页 ...

  6. 一步一步实现web程序信息管理系统之二----后台框架实现跳转登陆页面

    SpringBoot springboot的目的是为了简化spring应用的开发搭建以及开发过程.内部使用了特殊的处理,使得开发人员不需要进行额外繁锁的xml文件配置的编写,其内部包含很多模块的配置只 ...

  7. Python web框架 Tornado(二)异步非阻塞

    异步非阻塞 阻塞式:(适用于所有框架,Django,Flask,Tornado,Bottle) 一个请求到来未处理完成,后续一直等待 解决方案:多线程,多进程 异步非阻塞(存在IO请求): Torna ...

  8. web框架-(二)Django基础

    上面我们已经知道Python的WEB框架有Django.Tornado.Flask 等多种,Django相较与其他WEB框架其优势为:大而全,框架本身集成了ORM.模型绑定.模板引擎.缓存.Sessi ...

  9. 手把手和你一起实现一个Web框架实战——EzWeb框架(二)[Go语言笔记]Go项目实战

    手把手和你一起实现一个Web框架实战--EzWeb框架(二)[Go语言笔记]Go项目实战 代码仓库: github gitee 中文注释,非常详尽,可以配合食用 上一篇文章我们实现了框架的雏形,基本地 ...

随机推荐

  1. 【[NOI2010]超级钢琴】

    我竟然又在写主席树 现在可是九月啦,我却还在写这种noip不可能考的算法 我觉得我真的要凉 题意很明确,就是给你一个序列,让从中选择\(k\)段连续的序列,长度必须大于等于\(L\)小于等于\(R\) ...

  2. mysql备份数据库脚本

    mysqldump.exe -uroot -proot mydb > D:\backup_script\bak-tmp\mydb.sql 备注:把mysql的bin下的mysqldump.exe ...

  3. linq的左连接右连接内连接用法

    1.左连接: var LeftJoin = from e in ListOfEmployees join d in ListOfDepartment on e.DeptID equals d.ID i ...

  4. 32位 的变量 用于表示 ms ,可以表示多少天那?

    1.在  TI  的 BLE 协议栈 中,即 OSAL 中 获取当前 系统 tick 的方法如下 /* * Read the system clock - returns milliseconds * ...

  5. Intellij IDEA 2018.2.2 SpringBoot热启动 (Maven)

    一.IDEA 工具配置 1. 打开IDEA 设置界面,选择编译,按图打勾. 2 . 然后 Shift+Ctrl+Alt+/,选择Registry 3 . compiler.automake.allow ...

  6. redis单节点集群

    一.概念 redis是一种支持Key-Value等多种数据结构的存储系统.可用于缓存.事件发布或订阅.高速队列等场景.该数据库使用ANSI C语言编写,支持网络,提供字符串.哈希.列表.队列.集合结构 ...

  7. PLSQL Developer 12 注册码

    PLSQL Developer 12 注册码product code: 4vkjwhfeh3ufnqnmpr9brvcuyujrx3n3le serial Number:226959 password ...

  8. macOS:按钮类型

    for (int i = 0; i < 10; i++) { for (int j = 1; j < 16; j++) { NSButton *btn = [[NSButton alloc ...

  9. Android Studio 2.3.3 出现Error:(26.13) Fail to resole: com.android.support.appcompat永久解决方法

    Android Studio 出现Error(26.13):Fail to resole:com.android.support.appcompat-v7.28_ Install Repository ...

  10. T+固定资产二维码管理(生成,打印)

    先 来几句生硬的开场白. 不知不觉中,二维码慢慢的取代了传统的条码.原因之一就是二维码更加的时尚,原因之二便是二维码可以存储更多的信息.......... 企业的固定资产,直接贴个二维码,然后用手机扫 ...