HTTP格式

HTTP协议是基于TCP和IP协议的。HTTP协议是一种文本协议。

每个HTTP请求和响应都遵循相同的格式,一个HTTP包含Header和Body两部分,其中Body是可选的。

HTTP请求格式:

GET:

GET /path HTTP/1.1

Header1: Value1

Header2: Value2

Header3: Value3

POST:

POST /path HTTP/1.1

Header1: Value1

Header2: Value2

Header3: Value3

body data goes here...

Header部分每行用\r\n换行,每行里键名和键值之间以:分割,注意冒号后有个空格。

当遇到\r\n\r\n时,Header部分结束,后面的数据全部是Body。

HTTP响应格式:

200 OK

Header1: Value1

Header2: Value2

Header3: Value3

body data goes here...

HTTP响应如果包含body,也是通过\r\n\r\n来分隔的。

请再次注意,Body的数据类型由Content-Type头来确定,如果是网页,Body就是文本,如果是图片,Body就是图片的二进制数据。

Body数据是可以被压缩的,如果看到Content-Encoding,说明网站使用了压缩。最常见的压缩方式是gzip。

WSGI接口

了解了HTTP协议的格式后,我们可以理解一个Web应用的本质:

1、浏览器发送HTTP请求给服务器;

2、服务器接收请求后,生成HTML;

3、服务器把生成的HTML作为HTTP响应的body返回给浏览器;

4、浏览器接收到HTTP响应后,解析HTTP里body并显示。

接受HTTP请求、解析HTTP请求、发送HTTP响应实现起来比较复杂,有专门的服务器软件来实现,例如Nginx,Apache。我们要做的就是专注于生成HTML文档。

Python里也提供了一个比较底层的WSGI(Web Server Gateway Interface)接口来实现TCP连接、HTTP原始请求和响应格式。实现了该接口定义的内容,就可以实现类似Nginx、Apache等服务器的功能。

WSGI接口定义要求Web开发者实现一个函数,就可以响应HTTP请求,示例:

def application(environ, start_response):

start_response('200 OK', [('Content-Type', 'text/html')])

return [b'

Hello, web!

']

这是一个简单的文本版本的Hello, web!。

上面的application()函数就是符合WSGI标准的一个HTTP处理函数,它接收两个参数:

environ:一个包含所有HTTP请求信息的dict对象;

start_response:一个发送HTTP响应的函数。

有了WSGI,我们关心的就是如何从environ这个dict对象拿到HTTP请求信息,然后构造HTML,通过start_response()发送Header,最后返回Body。

整个application()函数本身没有涉及到任何解析HTTP的部分,即底层代码不需要自己编写,只负责在更高层次上考虑如何响应请求就可以了。

但是,application()函数由谁来调用呢?因为这里的参数environ、start_response我们没法提供,返回的bytes也没法发给浏览器。

application()函数必须由WSGI服务器来调用。

有很多符合WSGI规范的服务器,Python提供了一个最简单的WSGI服务器,可以把我们的Web应用程序跑起来。这个模块叫wsgiref,它是用纯Python编写的WSGI服务器的参考实现。所谓“参考实现”是指该实现完全符合WSGI标准,但是不考虑任何运行效率,仅供开发和测试使用。

运行WSGI服务

有了wsgiref,我们可以非常快的实现一个简单的web服务器:

# coding: utf-8

from wsgiref.simple_server import make_server

def application(environ, start_response):

print(environ)

start_response('200 OK', [('Content-Type', 'text/html')])

return [b'

Hello web!

']

print('HTTP server is running on http://127.0.0.1:9999')

# 创建一个服务器,IP地址可以为空,端口是9999,处理函数是application:

httpd = make_server('', 9999, application)

httpd.serve_forever()

运行后访问http://127.0.0.1:9999/,会看到:

Hello web!

扩展知识:

make_server()里第一个参数如果为空,实际等效于0.0.0.0,表示监听本地所有ip地址(包括127.0.0.1)。

通过Chrome浏览器的控制台,我们可以查看到浏览器请求和服务器响应信息:

# 请求信息:

GET / HTTP/1.1

Host: 127.0.0.1:9999

Connection: keep-alive

Cache-Control: max-age=0

Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8

Upgrade-Insecure-Requests: 1

User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36

Accept-Encoding: gzip, deflate, sdch

Accept-Language: zh-CN,zh;q=0.8,en;q=0.6

Cookie: _ga=GA1.1.948200530.1463673425

# 响应信息:

HTTP/1.0 200 OK

Date: Sun, 12 Feb 2017 05:20:31 GMT

Server: WSGIServer/0.2 CPython/3.4.3

Content-Type: text/html

Content-Length: 19

Hello web!

我们再看终端的输出信息:

$ python user_wsgiref_server.py

HTTP server is running on http://127.0.0.1:9999

127.0.0.1 - - [12/Feb/2017 13:18:38] "GET / HTTP/1.1" 200 19

127.0.0.1 - - [12/Feb/2017 13:18:39] "GET /favicon.ico HTTP/1.1" 200 19

如果我们打印environ参数信息,会看到如下值:

{

"SERVER_SOFTWARE": "WSGIServer/0.1 Python/2.7.5",

"SCRIPT_NAME": "",

"REQUEST_METHOD": "GET",

"SERVER_PROTOCOL": "HTTP/1.1",

"HOME": "/root",

"LANG": "en_US.UTF-8",

"SHELL": "/bin/bash",

"SERVER_PORT": "9999",

"HTTP_HOST": "dev.banyar.cn:9999",

"HTTP_UPGRADE_INSECURE_REQUESTS": "1",

"XDG_SESSION_ID": "64266",

"HTTP_ACCEPT": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",

"wsgi.version": "0",

"wsgi.errors": "",

"HOSTNAME": "localhost",

"HTTP_ACCEPT_LANGUAGE": "zh-CN,zh;q=0.8,en;q=0.6",

"PATH_INFO": "/",

"USER": "root",

"QUERY_STRING": "",

"PATH": "/usr/local/php/bin:/usr/local/php/sbin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin",

"HTTP_USER_AGENT": "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36",

"HTTP_CONNECTION": "keep-alive",

"SERVER_NAME": "localhost",

"REMOTE_ADDR": "192.168.0.101",

"wsgi.url_scheme": "http",

"CONTENT_LENGTH": "",

"GATEWAY_INTERFACE": "CGI/1.1",

"CONTENT_TYPE": "text/plain",

"REMOTE_HOST": "",

"HTTP_ACCEPT_ENCODING": "gzip, deflate, sdch"

}

为显示方便,已精简部分信息。有了环境变量信息,我们可以对程序做些修改,可以动态显示内容:

def application(environ, start_response):

print(environ['PATH_INFO'])

start_response('200 OK', [('Content-Type', 'text/html')])

body = '

Hello %s!

' % (environ['PATH_INFO'][1:] or 'web' )

return [body.encode('utf-8')]

以上使用了environ里的PATH_INFO的值。我们在浏览器输入http://127.0.0.1:9999/python,浏览器会显示:

Hello python!

终端的输出信息:

$ python user_wsgiref_server.py

HTTP server is running on http://127.0.0.1:9999

/python

127.0.0.1 - - [12/Feb/2017 13:54:57] "GET /python HTTP/1.1" 200 22

/favicon.ico

127.0.0.1 - - [12/Feb/2017 13:54:58] "GET /favicon.ico HTTP/1.1" 200 27

web框架

实际项目开发中,我们不可能使用swgiref来实现服务器,因为WSGI提供的接口虽然比HTTP接口高级了不少,但和Web App的处理逻辑比,还是比较低级。我们需要使用成熟的web框架。

由于用Python开发一个Web框架十分容易,所以Python有上百个开源的Web框架。部分流行框架:

Flask:轻量级Web应用框架;

Django:全能型Web框架;

web.py:一个小巧的Web框架;

Bottle:和Flask类似的Web框架;

Tornado:Facebook的开源异步Web框架

Flask

Flask是一个使用 Python 编写的轻量级 Web 应用框架。其 WSGI 工具箱采用 Werkzeug ,模板引擎则使用 Jinja2 。

安装非常简单:

pip install flask

控制台输出:

Collecting flask

Downloading Flask-0.12-py2.py3-none-any.whl (82kB)

100% |████████████████████████████████| 92kB 163kB/s

Collecting itsdangerous>=0.21 (from flask)

Downloading itsdangerous-0.24.tar.gz (46kB)

100% |████████████████████████████████| 51kB 365kB/s

Collecting click>=2.0 (from flask)

Downloading click-6.7-py2.py3-none-any.whl (71kB)

100% |████████████████████████████████| 71kB 349kB/s

Collecting Jinja2>=2.4 (from flask)

Downloading Jinja2-2.9.5-py2.py3-none-any.whl (340kB)

100% |████████████████████████████████| 348kB 342kB/s

Collecting Werkzeug>=0.7 (from flask)

Downloading Werkzeug-0.11.15-py2.py3-none-any.whl (307kB)

100% |████████████████████████████████| 317kB 194kB/s

Collecting MarkupSafe>=0.23 (from Jinja2>=2.4->flask)

Downloading MarkupSafe-0.23.tar.gz

Building wheels for collected packages: itsdangerous, MarkupSafe

Running setup.py bdist_wheel for itsdangerous ... done

Successfully built itsdangerous MarkupSafe

Installing collected packages: itsdangerous, click, MarkupSafe, Jinja2, Werkzeug, flask

Successfully installed Jinja2-2.9.5 MarkupSafe-0.23 Werkzeug-0.11.15 click-6.7 flask-0.12 itsdangerous-0.24

安装完flask会同时安装依赖模块:itsdangerous, click, MarkupSafe, Jinja2, Werkzeug。

现在我们来写个简单的登录功能,主要是三个页面:

首页,显示home字样;

登录页,地址/login,有登录表单;

登录后的欢迎页面,如果登录成功,提示欢迎语,否则提示用户名不正确。

那么一共有3个URL:

GET /:首页,返回Home;

GET /login:登录页,显示登录表单;

POST /login:处理登录表单,显示登录结果。

user_flask_app.py

# coding: utf-8

from flask import Flask

from flask import request

app = Flask(__name__)

# 首页

@app.route('/', methods=['GET', 'POST'])

def home():

return '

Home

去登录

'

# 登录页

@app.route('/login', methods=['get'])

def login():

return '''

用户名:

密码:

登录

'''

# 登录页处理

@app.route('/login', methods=['post'])

def do_login():

# 从request对象读取表单内容:

param = request.form

if(param['username'] == 'yjc' and param['password'] == 'yjc'):

return '欢迎您 %s !' % param['username']

else:

return '用户名或密码不正确。'

pass

if __name__ == '__main__':

# run()方法参数可以都为空,使用默认值

app.run('', 5000)

我们可以打开:http://localhost:5000/ 看效果。实际的Web App应该拿到用户名和口令后,去数据库查询再比对,来判断用户是否能登录成功。

通过代码我们可以发现,Flask通过Python的装饰器在内部自动地把URL和函数给关联起来。

注意代码里同一个URL/login分别有GET和POST两种请求,可以映射到两个处理函数中。

使用模板

Web框架让我们从编写底层WSGI接口拯救出来了,极大的提高了我们编写程序的效率。

但代码里嵌套太多的html让整个代码易读性变差,使程序变得复杂。我们需要将后端代码逻辑与前端html分离出来。这就是传说中的MVC:Model-View-Controller,中文名“模型-视图-控制器”。

Controller负责业务逻辑,比如检查用户名是否存在,取出用户信息等等;

View负责显示逻辑,通过简单地替换一些变量,View最终输出的就是用户看到的HTML。

'Model'负责数据的获取,如从数据库查询用户信息等。Model简单可以理解为数据。

那么就是:Model获取数据,Controlle处理业务逻辑,View显示数据。

现在,我们把上次直接输出字符串作为HTML的例子用MVC模式改写一下:

# coding: utf-8

from flask import Flask,request,render_template

app = Flask(__name__)

# 首页

@app.route('/', methods=['GET', 'POST'])

def home():

return render_template('home.html')

# 登录页

@app.route('/login', methods=['get'])

def login():

return render_template('login.html', param = [])

# 登录页处理

@app.route('/login', methods=['post'])

def do_login():

param = request.form

if(param['username'] == 'yjc' and param['password'] == 'yjc'):

return render_template('welcome.html', username = param['username'])

else:

return render_template('login.html', msg = '用户名或密码不正确。', param = param)

pass

if __name__ == '__main__':

app.run('', 5000)

Flask通过render_template()函数来实现模板的渲染。和Web框架类似,Python的模板也有很多种。Flask默认支持的模板是jinja2。

模板页面:

home.html

Home

去登录

login.html

{% if msg %}

{{ msg }}

{% endif %}

用户名:

密码:

登录

welcome.html

欢迎您, {{ username }} !

项目目录:

user_flask_app

|-- templates

|-- home.html

|-- login.html

|-- welcome.html

|-- user_flask_app.py

render_template()函数第一个参数是模板名,默认是templates目录下。后面的参数是传给模板的变量。变量的值可以是数字、字符串、列表等等。

在Jinja2模板中,我们用{{ name }}表示一个需要替换的变量。很多时候,还需要循环、条件判断等指令语句,在Jinja2中,用{% ... %}表示指令。

比如循环输出页码:

{% for i in page_list %}

{{ i }}

{% endfor %}

除了Jinja2,常见的模板还有:

Mako:用和${xxx}的一个模板;

Cheetah:也是用和${xxx}的一个模板;

Django:Django是一站式框架,内置一个用{% ... %}和{{ xxx }}的模板。

学习pythonweb开发_Python学习--20 Web开发相关推荐

  1. 《msdn开发精选》“高性能Web开发技术”网上聊天活动

    <msdn开发精选>"高性能Web开发技术"网上聊天活动 本期嘉宾:郭红俊(ghj1976),孟宪会(孟子E章) ,刘如鸿(策划编辑) 聊天主题:高性能的Web应用程序 ...

  2. chatgpt赋能python:Python是一门非常流行的编程语言,它被广泛应用于不同领域的软件开发中,包括Web开发、数据科学、人工智能等。虽然Python本身非常强大和灵活,但是要让自己的Pyt

    Python是一门非常流行的编程语言,它被广泛应用于不同领域的软件开发中,包括Web开发.数据科学.人工智能等.虽然Python本身非常强大和灵活,但是要让自己的Python代码在互联网上被搜索引擎优 ...

  3. python web开发要学什么_Python WEB开发 用Python开展web开发必须学习什么?

    用Python开展web开发必须学习哪些? 针对新手想更轻轻松松的学好Python开发技术性,Python网络爬虫,Python数据分析,人工智能技术等技术性,这儿给大伙儿共享一套系统软件教育资源,加 ...

  4. 学习前端开发,可提高Web开发效率的15类工具

    Web的发展日新月异,这也使得Web开发者不得不加快脚步,学习新的技术和编程语言.尤其是对于那些大量流量入口的网站来说,跟上技术发展趋势更是尤为重要.为了使得Web开发人员能够更加专注于业务层面的开发 ...

  5. python容器开发_python学习之容器化管理docker

    Docker简介 1.1 什么是虚拟化 在计算机中,虚拟化(英文: Virtualization)是一种资源管理技术,是将计算机的各种实体资源(如: 服 务器.网络.内存及存储等)予以抽象.转化后呈现 ...

  6. python网页运行环境_Python小牛叔Web开发1:安装Visual Studio Code配置Python运行环境...

    本系列是Python小牛叔Web开发系列,以Django为框架介绍如何使用Python来开发Web应用,本教程适合对于Web开发有基本知识的入门者. 1.安装Visual Studio Code编辑器 ...

  7. c mysql web开发实例教程_java web 开发入门实例

    学习是个技巧活,关键是要找到重点的地方,新手在这方面的坑尤其多.看别人的教程一步一步的跟着做,隔几步就遇到一个新知识点,忍不住就百度往深处了解,一晃半天就过去了. 有的知识点要深入学习的,有的是了解下 ...

  8. devops开发模式流程图_2020 Web开发人员路线图–成为前端,后端或DevOps开发人员的视觉指南

    devops开发模式流程图 There are many ways you can go about picking up the skills you need to become a develo ...

  9. php三种web开发技术,三种WEB开发主流技术ASP-PHP-JSP的评价

    三种Web开发主流技术ASP-PHP-JSP的评价 [摘要]本文从程序开发者的角度,对现今社会盛行的WEB开发技术进行了分析,旨在让WEB 开发人员.使用者.准备学习的人对WEB开发技术有更加深入的了 ...

  10. python运维系统开发_Python系统运维开发实战

    课程主题: Python 高级运维开发实战 课程讲师: Alex 老师, triaquae python 开源运维管理软件创始人,知名 IT 公司运维开发架构师 课程安排: 每周六一天全天(早 9:0 ...

最新文章

  1. 张一鸣的微博世界-产品篇二
  2. 动态规划法(九)想要更多例子?
  3. bzoj2161 布娃娃
  4. excel中如何将时间戳转换为日期格式
  5. 28. LAST() 函数
  6. 3分钟了解“关联规则”推荐
  7. 操作系统之I/O管理:2、SPOOLing技术(假脱机技术)
  8. 企业库(V4.1)入门学习手记
  9. python os.system
  10. 计算机应用能力考试初级,河北省职称计算机应用能力考试初级
  11. 微信通讯协议。自动加人
  12. 圆的半径java_计算圆的半径
  13. android百度地图公交路线,android百度地图api实现查询经过某站点的所有公交路线...
  14. Django之Form表单验证组件Tyrion
  15. 永磁同步电机矢量控制中的双闭环是什么意思_STM32 TALK | 无感FOC方案原理机器控制难点分析...
  16. Qt资源文件.qrc
  17. 理解前端框架、前端库,两者有什么区别
  18. 最大似然估计(Maximum Likelihood,ML)
  19. js第三章简答题5(制作如图所示的Tab切换效果)
  20. faker和劫的图片_faker劫反杀ryu第一视角完整视频和gif,慢动作回放两个劫之间的较量分析...

热门文章

  1. 审计计算机考试报名,审计业务考试计算机(5页)-原创力文档
  2. open cv+C++错误总结(一)
  3. [Latex排版]之visio图转成eps的方法
  4. RabbitMQ connection.CreateModel() 分析
  5. js 事件模型 + ( 事件类型 )
  6. 模拟任务调度算法 C语言 【留学生作业】
  7. iptables的nat规则骚操作
  8. html5中本地存储概念是什么?
  9. request之额外路径
  10. gevent 协程 使用