Python之WEB编程入门
2020-12-13 05:43
标签:第三方 == 第一个 ring list centos 报错 流程 __name__ 前面很多内容都是在介绍 Python 的知识点。这些知识点可以说涵盖了 Python 80% 的方面。在接着往下分享的话,那就是 Python 高阶的知识点。比如语言本身的自身能力(反射)、描述器、元编程等内容了。再接着就是 WEB 相关的内容了。 接下来会花很多篇章来介绍 WEB 相关的知识点。然后再介绍如何从零开始实现一个 WEB 框架。内容还是比较多的,请有需要的同学多多关注。 这里从零开始写一个框架出来,目的是为了更好地使用现有的 WEB 框架,了解现有 WEB 框架是如何工作的,这才是我们最终的目的。 最早的时候,WEB就是一些静态文件。由开发人员通过编辑器直接编辑生成静态的HTML页面,如果要修改WEB页面的内容或布局,就得编辑这些静态的HTML文件。早期的时候就是这么来玩的,是不是让人着实不爽? 由于静态WEB页面无法与用户进行交互(提交表单等操作)。为了解决这一问题,人们开发出了一种称为CGI(Common Gateway Interface)的技术,使用 由于WEB应用的特点是频繁更新,用低级语言非常不适合高效地开发。而脚本语言(JSP、PHP)由于开发效率高,与HTML结合紧密,因此,迅速取代了CGI模式。JSP使用Java编写脚本,而PHP则是开源的脚本语言。 最早的动态页面是CGI实现的,CGI是怎么工作的?当请求某个地址的时候,http服务器会启动一个外部程序,并且把外部程序的输出返回给用户。CGI规范了http和外部程序的通信方式。 CGI的缺点: 基于CGI以上的缺点,由此衍生出了FastCGI技术,把进程管理交给其他服务来处理。http服务器把http协议转化成fastcgi协议,通过socket发送给FastCGI守护进程。这样并发模型变得多种多样,进程管理由FastCGI实现,单一原则。 另一个分支就是由cgi发展的wsgi技术。接下来就看看wsgi。 Web框架的主要关键点: Web服务器网关接口(WSGI)是Python Web应用程序框架和Web服务器之间标准接口的规范。 在Python Web应用程序的早期,由于没有统一的标准,将Web应用程序框架连接到Web服务器是不容易的。Python Web应用程序是用于工作的,具体是通过运用现有的CGI、FastCGI或mod_python(Apache)标准之一。这意味着在一个Web服务器上工作的应用程序可能无法在另一个Web服务器上工作。换言之,统一的应用程序与Web服务器之间的互操作性没有了。 WSGI通过在服务器和Web应用框架之间指定一个简单但统一的接口来解决这个问题,从而允许移植Web应用程序。 WSGI指定了两个方面:服务器(或网关)端,以及应用程序或框架端。WSGI请求得到了以下处理: 流程如下: wsgi两部分组成:容器,应用。也可以把容器称为网关或服务器。容器实现了协议转换,由http协议到wsgi协议的转换;应用用来处理业务逻辑。 容器和应用怎么通信呢?FastCGI通过socket;wsgi的容器和应用通过函数调用进行通信。什么情况下可以通过函数调用实现通信?同一进程内可以实现函数调用,wsgi的容器和应用是运行在同一进程之中。 常用的wsgi容器:gunicorn,uWSGI。 说了这么多,还是看个简单的例子吧,看看wsgi是如何工作的。接下来实现一个helloworld的程序。 wsgi application应该是一个callable对象。函数是可调用的,如果一个类有 wsgi函数的书写有一定的要求,它的函数签名一般如下,比较固定: 上述函数传入的参数是有规定的: 要了解更多的WSGI规范,可以看看PEP 3333提案。 开始写: 运行以上代码,并在浏览器上进行访问: 也可以通过curl命令行工具进行访问: 接下来使用gunicorn容器来运行上述代码: 通常在开发的时候,使用wsgiref就行了,如果在生产中,可以使用第三方的wsgi容器。 上面的代码中,如果想看environ中的内容,可以在上述代码中添加如下的代码: 如果再次运行代码,会有如下的输出: environ中有一个QUERY_STRING的key,我们可以打印该信息: 在浏览器的URL地址栏里输入: 运行效果如下: 上面的输出中, 接下来就是解析来自客户端的输入,解析这件事也不是很困难,不过有标准库来处理这个解析的工作,引入标准库: 执行结果如下: 接下来的代码如下: 如果用户在浏览器这样输入,就有可能有问题: 好了,今天就到这里。不知你看了这些内容有什么想法,随时欢迎留言进行讨论、一起学习。 后面会逐步介绍如何在此基础上进行封装,进而做出一个小小的框架。有任何问题欢迎留言交流。 Python之WEB编程入门 标签:第三方 == 第一个 ring list centos 报错 流程 __name__ 原文地址:https://blog.51cto.com/lavenliu/2417870
WEB发展历程
C/C++
编写。
WSGI
一个可工作的HelloWorld
__call__
方法,也是可调用的。def application(environ, start_response):
‘‘‘
# 函数传入的参数是有规定的:
# environ:environ变量是从服务器传递到应用程序的环境变量的字典,如请求内容等;
# 由公共网关接口(CGI)规范定义。WSGI在其规范中规定了一些环境变量受托者
# start_response:一个可调用对象,其提供一个从服务器端到应用程序端的回调,从而开启服务器端的
# 响应处理。它必须有两个位置参数。第一个应该是具有整型状态吗的状态字符串,第二个是一个(header_name, header_value)列表,其是描述HTTP头响应的元组。
‘‘‘
pass
environ
:environ
变量是从服务器传递到应用程序的环境变量的字典,如请求内容等;由公共网关接口(CGI)规范定义。WSGI在其规范中规定了一些环境变量受托者start_response
:一个可调用对象,其提供一个从服务器端到应用程序端的回调,从而开启服务器端的响应处理。它必须有两个位置参数。第一个应该是具有整型状态吗的状态字符串,第二个是一个(header_name, header_value
)列表,其是描述HTTP头响应的元组。def application(environ, start_response):
body = ‘hello world‘
status = ‘200 OK‘
headers = [
(‘content-type‘, ‘text/plain‘),
(‘content-length‘, str(len(body)))
]
start_response(status, headers)
return [body.encode()]
# 以上代码只有应用,没有容器;
if __name__ == ‘__main__‘:
# 引入wsgi容器
from wsgiref.simple_server import make_server
server = make_server(‘0.0.0.0‘, 8000, application)
try:
server.serve_forever()
except KeyboardInterrupt:
server.shutdown()
[lavenliu@VM_113_230_centos 12-web]$ python wsgi01.py
183.192.25.121 - - [13/Oct/2018 18:48:08] "GET / HTTP/1.1" 200 11
183.192.25.121 - - [13/Oct/2018 18:48:09] "GET /favicon.ico HTTP/1.1" 200 11
183.192.25.121 - - [13/Oct/2018 18:48:09] "GET /favicon.ico HTTP/1.1" 200 11
curl -XPOST http://127.0.0.1:8000 -d ‘{"a": 1}‘
# 首先安装gunicorn
pip install gunicorn
# 接着运行wsgi01.py的application应用
[lavenliu@VM_113_230_centos 12-web]$ gunicorn -b 0.0.0.0 wsgi01:application
[2018-10-13 18:55:38 +0800] [18359] [INFO] Starting gunicorn 19.6.0
[2018-10-13 18:55:38 +0800] [18359] [INFO] Listening at: http://0.0.0.0:8000 (18359)
[2018-10-13 18:55:38 +0800] [18359] [INFO] Using worker: sync
[2018-10-13 18:55:38 +0800] [18397] [INFO] Booting worker with pid: 18397
for k, v in environ.items():
print(‘{} => {}‘.format(k, v))
# 完整的代码如下:
# coding: utf-8
def application(environ, start_response):
for k, v in environ.items():
print(‘{} => {}‘.format(k, v))
body = ‘hello world‘
status = ‘200 OK‘
headers = [
(‘content-type‘, ‘text/plain‘),
(‘content-length‘, str(len(body)))
]
start_response(status, headers)
return [body.encode()]
# 以上只有应用代码,没有容器
if __name__ == ‘__main__‘:
from wsgiref.simple_server import make_server
server = make_server(‘0.0.0.0‘, 8000, application)
try:
server.serve_forever()
except KeyboardInterrupt:
server.shutdown()
wsgi.input =>
[lavenliu@VM_113_230_centos 12-web]$ cat wsgi01.py
# coding: utf-8
def application(environ, start_response):
print(environ.get(‘QUERY_STRING‘))
body = ‘hello world‘
status = ‘200 OK‘
headers = [
(‘content-type‘, ‘text/plain‘),
(‘content-length‘, str(len(body)))
]
start_response(status, headers)
return [body.encode()]
# 以上只有应用代码,没有容器
if __name__ == ‘__main__‘:
from wsgiref.simple_server import make_server
server = make_server(‘0.0.0.0‘, 8000, application)
try:
server.serve_forever()
except KeyboardInterrupt:
server.shutdown()
http://115.159.125.96:8000?name=lavenliu&age=25
[lavenliu@VM_113_230_centos 12-web]$ gunicorn -b 0.0.0.0 wsgi01:application
[2018-10-13 19:15:36 +0800] [20609] [INFO] Starting gunicorn 19.6.0
[2018-10-13 19:15:36 +0800] [20609] [INFO] Listening at: http://0.0.0.0:8000 (20609)
[2018-10-13 19:15:36 +0800] [20609] [INFO] Using worker: sync
[2018-10-13 19:15:36 +0800] [20647] [INFO] Booting worker with pid: 20647
name=lavenliu&age=25 # 获得的来自客户端的输入
name=lavenliu&age=25 # 获得的来自客户端的输入
from urllib.parse import parse_qs
from html import escape
parse_qs(‘name=lavenliu&age=25‘)
# 返回的value是列表,因为有可能key有同名的
{‘age‘: [‘25‘], ‘name‘: [‘lavenliu‘]}
[lavenliu@VM_113_230_centos 12-web]$ cat wsgi02.py
# coding: utf-8
from urllib.parse import parse_qs
from html import escape
def application(environ, start_response):
params = parse_qs(environ.get(‘QUERY_STRING‘))
name = params.get(‘name‘, [‘anon‘])[0]
body = ‘hello {}‘.format(name) # 如果用户在浏览器里输入非法的东东时,可能会有问题
status = ‘200 OK‘
headers = [
(‘content-type‘, ‘text/html‘),
(‘content-length‘, str(len(body)))
]
start_response(status, headers)
return [body.encode()]
# 以上只有应用代码,没有容器
if __name__ == ‘__main__‘:
from wsgiref.simple_server import make_server
server = make_server(‘0.0.0.0‘, 8001, application)
try:
server.serve_forever()
except KeyboardInterrupt:
server.shutdown()
http://115.159.125.96:8001?name=
# chrome浏览器则没有问题,它会检测到这个输入有问题;如果在IE6上可能就会执行上述代码。
Navigated to http://115.159.125.96:8001/?%3Cscript%20type=%27text/javascript%27%3Ealert(%27f**k%20it%27)%3C/script%3E
?name=:1 The XSS Auditor refused to execute a script in ‘http://115.159.125.96:8001/?name=%3Cscript%20type=%27text/javascript%27%3Ealert(%27f**k%20it%27)%3C/script%3E‘ because its source code was found within the request. The auditor was enabled as the server sent neither an ‘X-XSS-Protection‘ nor ‘Content-Security-Policy‘ header.
Navigated to http://115.159.125.96:8001/?name=%3Cscript%20type=%27text/javascript%27%3Ealert(%27f**k%20it%27)%3C/script%3E
# 在火狐浏览器就能通过,不会报错
# IE11版本则没有这个问题
下一篇:C# 对象封装为json格式