HTTP1.1 基础: 请求和响应的消息交互细节

HTTP1.1 基础概念

HTTP/2在2015年已推出,本文主要介绍的是HTTP1.1。下面是RFC2616对HTTP1.1的描述:

The Hypertext Transfer Protocol (HTTP) is an application-level protocol for distributed, collaborative, hypermedia information systems. It is a generic, stateless, protocol which can be used for many tasks beyond its use for hypertext, such as name servers and distributed object management systems, through extension of its request methods, error codes and headers.

HTTP1.1 作为一个应用层协议,有如下的一些特点:

  • 报文头是约定格式的纯文本,报文头指定了方法、内容格式、缓存等meta信息;
  • 无状态的请求响应,即当前的请求跟之前的请求无联系;
  • 承载在传输层TCP之上,HTTPS又在TCP之上增加了TLS安全层;

当前大部分网站都已经切换到HTTPS, 并且Chrome 68正式版会把所有潜在不安全的HTTP网站标记为不安全。HTTPS是在HTTP下加入SSL/TLS安全层,增强了网络访问的安全性。TLS(Transport Layer Security)是SSL的v3.0升级版,已经是HTTPS的标准。HTTP和HTTPS有如下的区别:

  • HTTPS协议需要到ca申请证书,需要一定费用;
  • HTTP信息是明文传输,HTTPS则是具有安全性的TLS加密传输;
  • HTTP默认使用80端口,HTTPS默认使用是443端口;

一个典型交互场景如下:
这里写图片描述

HTTP1.1 报文格式

学习网络协议细节时,一个很重要的手段就是看RFC(Request For Comments),基本的互联网通信协议都有在RFC里详细说明。下面是HTTP的RFC:

HTTP访问从URL开始,Uniform Resource Locator (URL)的格式为:

protocol://hostname:port/path-and-file-name
# port: server监听的TCP port,http缺省是80
# path-and-file-name: server的文件路径

在浏览器输入URL,浏览器会发起一个http request,使用Chrome或者Firefox开发者工具的Network选项可以查看HTTP请求与响应头内容。

HTTP的报文结构如下图,左右分别是请求和响应报文的结构:
这里写图片描述
详细说明可以看RFC的对应章节。

http request

这里写图片描述
上面 Request Line 的标准格式为:

# request line
request-method-name request-URI HTTP-version
#  method举例: GET, POST
#  request-URI: 指定请求的资源
#  HTTP-version: HTTP/1.0 or HTTP/1.1

当request消息到达server时,服务器会做以下处理中的一项:

  1. server解析request消息,映射request到对应文件目录,返回请求的文件给client;
  2. server解析request消息,映射request到server的一个程序,执行程序,把程序输出返回给client;
  3. server发现request无法被完成,返回携带错误码的error msg给client;

http response

这里写图片描述
上面 Status Line 的标准格式为:

# Status Line
HTTP-version status-code reason-phrase
# HTTP-version: HTTP/1.0 or HTTP/1.1
# status-code: 三位数字的返回码, 如: 200 ok, 403 Forbidden, 404 Not Found
# reason-phrase: 返回码的简短解释

然后client(通常就是浏览器)收到server的response消息,会把内容显示在页面,浏览器会渲染HTML并执行JS.

HTTP 方法:GET和POST

每个 http request 请求都可以携带一个方法,最常见的就是 GET 和 POST,还有其他方法这里不做介绍,可以看RFC。

GET method

GET request-URI HTTP-version
(optional request headers)

(optional request body)
  • GET 必须大写
  • request-URI:resource路径,必须以root “/" 开始,server指定的,非OS文件系统的根目录;
  • client使用request headers 里的Accept, Accept-Language等协商交互内容;
  • GET请求消息有一个可选的 request body,携带查询字符串
Request Header 里的host字段

请求header里如果携带了 Connection: Keep-Alive,那么要求server不要马上关闭TCP连接。HTTP/1.1 默认指定 keep-alive,可以提高网络效率。并且 HTTP/1.1 server支持虚拟主机,即同一个host有不同的hostname,不同host有各自指定的不同的根目录,因此 HTTP/1.1 默认要求request header指定host字段。

URL Encoded 编码特殊字符

URL无法携带特殊字符,遇到特殊字符用%xx编码,xx是ASCII hex coe,如空格可被编码为 %20+.

GET 携带查询参数, 是在URL里传参的,比如如下form制定GET方法提交

<html>
<body>
<form method="get" action="/bin/login">
    Username: <input type="text" name="user" size="25" /><br/>
    Password: <input type="password" name="pw" size="10" /><br/>
    <input type="hidden" name="action" value="login" />
    <input type="submit" value="SEND" />
</form>
</body>
</html>

点击提交,浏览器生成的request消息如下:

GET /bin/login?user=Peter+Lee&pw=123456&action=login HTTP/1.1
Accept: image/gif, image/jpeg, */*
Referer: http://127.0.0.1:8000/login.html
Accept-Language: en-us
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)
Host: 127.0.0.1:8000
Connection: Keep-Alive

上面request line的URI传参:?user=Peter+Lee&pw=123456&action=login ,然后server可以解析这个字符串获取对应的参数。

POST method

POST方法可以post额外的数据到server,如提交表单或上传文件,一个POST请求如下:

POST request-URI HTTP-version
Content-Type: mime-type
Content-Length: number-of-bytes
(other optional request headers)

(URL-encoded query string)

对于POST, request header 里的Content-TypeContent-Length is necessary是必选字段,指定post数据的类型和长度。

<html>
<body>
<form method="post" action="/bin/login">
    Username: <input type="text" name="user" size="25" /><br/>
    Password: <input type="password" name="pw" size="10" /><br/>
    <input type="hidden" name="action" value="login" />
    <input type="submit" value="SEND" />
</form>
</body>
</html>

提交表单,产生如下的http request请求

POST /bin/login HTTP/1.1
Host: 127.0.0.1:8000
Accept: image/gif, image/jpeg, */*
Referer: http://127.0.0.1:8000/login.html
Accept-Language: en-us
Content-Type: application/x-www-form-urlencoded  # type, post必选字段
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)
Content-Length: 37  # length, post必选字段, 下面post数据37个字符
Connection: Keep-Alive
Cache-Control: no-cache

User=Peter+Lee&pw=123456&action=login

POST request提交的数据没有大小限制,并且不会再浏览器地址栏显示,适合敏感或大量数据提交。对于上面里子,post携带的参数就是最后的 User=Peter+Lee&pw=123456&action=login , server 解析这个字符串即可获取对应数据。

HTTP 常用工具

  • chrome: chrome浏览器的开发者工具,调试前端DOM/JS,查看报文都很方便;
  • wget: 非交互式的web文件下载工具,支持HTTP, HTTPS和FTP等协议;
  • netcat: 网络安全界的瑞士军刀, 可以建立TCP或UDP连接来收发报文;
  • curl: 利用URL语法在命令行方式下工作的开源文件传输工具;

如使用curl查看一次http的请求响应,内容如下:

root@ubuntu:~# curl -v www.baidu.com
* Rebuilt URL to: www.baidu.com/
* Hostname was NOT found in DNS cache
*   Trying 115.239.211.112...
* Connected to www.baidu.com (115.239.211.112) port 80 (#0)
> GET / HTTP/1.1
> User-Agent: curl/7.35.0
> Host: www.baidu.com
> Accept: */*
>
< HTTP/1.1 200 OK
< Accept-Ranges: bytes
< Cache-Control: private, no-cache, no-store, proxy-revalidate, no-transform
< Connection: Keep-Alive
< Content-Length: 2381
< Content-Type: text/html
< Date: Sun, 26 Aug 2018 05:40:50 GMT
< Etag: "58860504-94d"
< Last-Modified: Mon, 23 Jan 2017 13:28:36 GMT
< Pragma: no-cache
* Server bfe/1.0.8.18 is not blacklisted
< Server: bfe/1.0.8.18
< Set-Cookie: BDORZ=27315; max-age=86400; domain=.baidu.com; path=/
<
<!DOCTYPE html><head>...</head><body>...</body></html>

极简HTTP1.1 Server的C实现

可以看这篇:HTTP1.1 基础: 用C语言实现200行内的极简http server

参考

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值