HTTP协议是应用层协议, 全称是HyperText Transfer Protocol
HTTP协议是一种请求回应式的, 一个Request一定会有一个Response
格式
HTTP的一次请求或者一次应答所发送的包为一个HTTP Message,
HTTP Message当然分为Request和Response, 两者都可以分为三个部分
- 起始行 Start Line
- 消息头 Message Headers
- 消息体 Message Body 或 Message entity
下面我用chrome做的测试
我在浏览器地址栏输入www.douban.com, 从我的Request中摘取部分
GET / HTTP/1.1 Host: www.douban.com Connection: keep-alive
请求行有三部分:
- GET 方法,GET和POST是我们最常见的
- / 要请求的资源的URI
- HTTP/1.1 使用的HTTP协议版本
GET 请求是不会有Message Body的
我在请求www.douban.com后, 豆瓣服务器返回的Response中, 摘取状态行和部分header fields
HTTP/1.1 200 OK Server: nginx Content-Type: text/html; charset=utf-8 Content-Length: 15597 Connection: keep-alive
Response的状态行有三段:
- HTTP/1.1 使用的协议版本
- 200 状态码
- OK 状态描述, 计算机并不解析这个,这是给人看的
HTTP 与 form元素
URI
URI就是Uniform Resource Identifier, 用来定位web上的唯一资源, 而这个Request就是针对对这个资源实施的. <关于URI及其相关的名称其实很多, 对于有有些强迫症患者,确实要考究其准确定义,可以参考 RFC2396 和 RFC2616>
URI可以带query parameter请求参数, 就是?之后的部分
当我们用豆瓣的搜索,在豆瓣网任何地方搜索"world", Request请求行如下
GET /search?source=suggest&q=world HTTP/1.1
搜索框的部分是一个<form>,其html为(丢掉不相关的部分)
<form action="http://www.douban.com/search" method="get"> <input type="hidden" name="source" value="suggest"> <input name="q" > </form>
可以看到这个<form>属性 method="get" , 它指示Request使用GET方法, <form>中的参数会被放到URI的 ?query 部分.
[??]那如果<form>的 method="post" 会是什么情况呢
用http://www.douban.com/accounts/login 页面测试, 帐号密码当然不能显示在URI中了. Request为(去掉不太相关的)
POST /accounts/login HTTP/1.1
Host: www.douban.com
Connection: keep-alive
Content-Length: 51
form_email=wangyu%40gmail.com&form_password=1234567
这里是以字节的ASCII码来显示的, "%40"指的 "@"
可以看到<form>中的数据放到了Request的body里面, Request的方法为POST
方法为POST的Request是有body的, body就是 &分隔的一个个 key-value
HTTP Message Headers
headers的keys是预先定义好的, 做为协议的一部分,都有各自的用途, 我们不能在headers中自己加名字. 当然POST的数据不会放在headers中了
headers分为4类
- general header
- request header
- response header
- entity header
general header修饰整个message, 不分是Request还是Response, 如
- Connection:keep-alive
request header修饰Request, 如:
- Host: www.douban.com
- User-Agent : .....
- Cookie : .....
response header修饰Response, 如:
- Server : nginx
entity header 修饰 Message body, 如:
- Content-Length :
- Content-Type : text/html; charset=utf-8
对于Message headers, 协议并没有规定顺序, 但是协议上建议以上面的分类的顺序写.
Django的HttpRequest
如果用Django我们会知道, 每一次请求都会被django封装在一个request传进我们的函数
request是一个HttpRequest类对象, 定义在django.http.request模块中, 封装了一个HTTP Request的信息
HttpRequest的__init__函数:
def __init__(self): self.GET, self.POST, self.COOKIES, self.META, self.FILES = {}, {}, {}, {}, {} self.path = ''
可以看到这里有五个字典
request.GET中是URI的query参数
当请求方法为POST时, 其body中的key-value值会放在request.POST中
request.META 中存放了Request Headers.
--------------
参考:
RFC2616中描述了HTTP/1.1 , 很多东西都是在上面看的 http://tools.ietf.org/html/rfc2616
Django的Request and Response https://docs.djangoproject.com/en/1.6/ref/request-response/