HTTP必知必会

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

HTTP消息HTTP请求消息HTTP响应消息
消息首行请求行响应行
消息头部请求头请求头
消息正文请求正文响应正文

Web服务器把接收到的HTTP请求消息封装成request对象,作为service的参数传入service函数,service函数会被调用多次,每访问一次Servlet,它的servlet就会被调用一次。

Web服务器收到客户端的HTTP请求,会针对每一次请求,分别创建一个用于代表请求的request对象、和代表响应的response对象。

request和response对象即代表请求和响应,那我们要获取客户机提交过来的数据,只需要找request对象就行了。要向客户机输出数据,只需要找response对象就行了。

HTTP协议作为网络传输的基本协议,有着广泛的应用。HTTP协议的完整内容很多,但是其核心知识却又简单精炼。学习者应该掌握其基本结构,并且能够举一反三。这篇文章所列的,就是在实际开发中必须知道必须掌握的HTTP知识。

HTTP协议

HTTP协议:消息的分类

HTTP消息(有的文章称之为报文)分为请求消息响应消息两种基本分类。其中请求消息是客户端发送给服务器的用于请求服务资源的消息,响应消息是服务器对请求消息的应答。一般来说,一个响应对应一个请求,不多也不少。

HTTP协议:特点

HTTP协议被人总结为无连接无状态的特点:

  1. 无连接:无连接的含义是限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。采用这种方式可以节省传输时间。

  2. 无状态:HTTP协议是无状态协议。无状态是指协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。另一方面,在服务器不需要先前信息时它的应答就较快。

HTTP协议:消息的基本格式

HTTP协议的请求消息和响应消息的格式及其相似。提炼出它们的共性,可以指出,HTTP消息(包括HTTP请求消息、HTTP响应消息)分为三个部分:

  1. 消息首行

  2. 消息头部(Header)(包括请求头响应头

  3. 消息正文(Body)

其中,头部用来指出HTTP消息的一些属性,它们有固定的格式;正文部分是传输的实际内容,它们的格式是任意的,通常在消息头部中用Content-Type头来指定。消息首行在HTTP请求消息和HTTP响应消息中的具体格式略有区别,它们表示的按理说应该是HTTP消息最基本的部分。不论是HTTP请求消息还是HTTP响应消息,消息首行都是有的,否则会出现不可饶恕的解析错误;然而消息头部和消息正文是可选的,不过在实际过程中,多多少少都要包含一些基本的消息头部。

HTTP消息主要是基于ASCII编码的消息实体。主要的意思是指消息首行和消息头部都是以ASCII编码,而消息正文部分的编码就显得任意了。在实际的开发中,发送的文本消息时常会碰到乱码的问题。一种解决办法是,对于文本消息,约定以UTF-8格式进行编码解码

知道的人也许知道,HTTP消息是基于TCP协议的应用层协议。TCP协议是网络流协议一种。抽象地讲,就是从一台主机一个字节一个字节有序地传输到另一台主机。对于HTTP协议来说,自然保持了这种有序性,即按照消息首行、消息头部、消息正文的顺序进行传输。消息首行和消息头部都是ASCII文本流,正文是字节流。一个特殊的控制结构CRLF用来控制每个部分的结束。

CRLF是回车符和换行符的意思,它们是两个特殊的ASCII字符。CR是回车符(\r),在ASCII中的编码是13;LF是换行符(\n),在ASCII中的编码是10.

下面通过一个例子来解释CRLF在HTTP请求消息中的控制。

GET /simple.html HTTP/1.1<CRLF>     ----- HTTP请求消息的消息首行:请求行
Accept: text/html<CRLF>             --|
Accept-Language: zh-cn<CRLF>          |
Accept-Encoding: gzip, deflate<CRLF>  |-- 消息头部
User-Agent: Mozilla/4.0<CRLF>         |
Host: localhost:8080<CRLF>            |
Connection: Keep-Alive<CRLF>        --|
<CRLF>                              ----- 空白行表示头部的结束----- 接下来的内容是消息正文的部分

这是一个简单的HTTP请求消息。我在其中做了一些必要的删减,以便每个头足够短都能在一行中显示。记住消息首行消息头部ASCII流消息正文字节流,它们在消息实体中是连续的片段并不像代码中所示那样有换行的结构。换句话说,原始的消息应该是如下形式:

GET /simple.html HTTP/1.1
<CRLF>       // 这一行是HTTP请求消息的消息首行:请求行
Accept: text/html
<CRLF>
Accept-Language: zh-cn
<CRLF>
Accept-Encoding: gzip, deflate
<CRLF>
User-Agent: Mozilla/4.0
<CRLF>
Host: localhost:8080
<CRLF>
Connection: Keep-Alive
<CRLF>
<CRLF>

回到之前有换行符的代码例子中去。将每个CRLF单独列为一行是为了便于观察组织。可以清楚地看到,第一行是请求行,以CRLF标志其结束;接下来是头部,含有多个消息头,每行定义一个消息头,以CRLF标志其结束;一个单独的CRLF(紧接着上一个CRLF)表示整个头部的结束,接下来是正文部分。在 这个示例中,正文部分为空。

另外,可以看到每个HTTP消息的消息头部的格式都是一致的,Key:Value的形式。其中Key表示消息头部,Value表示消息头部

HTTP请求消息

接下来具体讲讲HTTP请求消息。诚心而论,光是写上面这么点内容就花费了我好久。每每想到写博客耗费的精力和时间,都会影响到我写博客的动力。

之前已经说过,HTTP请求消息也分为三个部分:

  1. 请求行(属于消息首行)

  2. 请求头(属于消息头部)

  3. 请求正文(属于消息正文)

其中请求头的格式我们已经见过。请求行的基本格式为:

方法 路径 版本

例如下面的具体例子:

GET /simple.html HTTP/1.1

就有对应关系:

  • 方法:GET

  • 路径:/simple.html

  • 版本:HTTP/1.1

请求行是HTTP请求消息的最基本要素。版本是用来声明HTTP消息的解析规则,不同的版本在某些地方的表现是不同的,这里不作过多拆解了。现在实际应用中最新的HTTP协议版本就是HTTP/1.1。路径可以理解成该请求消息发往服务器的入口,一般来讲,同一个路径应该代表同一个资源实体。方法表示对该资源实体进行的操作,例如上述的GET方法,其含义就是请求获取该资源的内容。这些都是通常的解释,但不是必然的要求。实际上,服务器会解析方法路径,根据方法和路径做出自己相应的响应。这种响应的规则,可以遵循某些规范,也可以完全不考虑这些规范,是任意的。市面上已经存在一些约定俗成的规范了,比如Restful。Restful是非常优秀的基于HTTP协议的WEB API设计理念,很值得讲,但在这里就不讲了。

HTTP请求:方法

首先列出最常用的HTTP方法:

  1. GET

  2. POST

  3. PUT

  4. PATCH

  5. DELETE

  6. HEAD

  7. OPTIONS

之前说过,服务器对于方法的处理,是没有强制的规范的。这句话说得并不全对。其实每个HTTP方法,都是有一些HTTP协议要求的。比如说GET方法请求的资源,浏览器端一般都会有缓存,下次请求的时候可能从缓存中去取就够了,服务器不用再重复发送相同的资源了;但是服务器如果将获取资源的接口的方法定义为POST,那么浏览器端就不会再对资源进行缓存了,即使每次取到的都是同样地内容,都会请求服务器重新发送一遍。所以说,将请求资源的接口方法定义为POST而不是GET,就是一种不合理的设计。

再比如,GET方法的请求消息是不能定义消息体的,HEAD方法的请求其响应消息是不包含消息体的,这些都是HTTP协议对于HTTP方法的约束。

HTTP请求:路径

方法和路径的组合构成WEB API的入口,路径也是很关键的。路径的基本格式一般是:

basic-path[?query-string]

其中[]中的内容表示可选的。在上例中,basic-path就是/simple.html,但不包含query-string的内容。basic-path形式很像UNIX中绝对路径的样式,要以/打头。单独的/表示一种路径,/a/a/b/a/b/c都是合理的路径表示。不推荐使用/a//a/b//a/b/c/这样/后面不跟任何其他内容的形式(/除外)。优秀的API设计者会利用不同的路径层级来合理地组织资源。

问号后面的部分就是query-string。它的格式是任意的,只要客户端和服务器约定好一定的形式即可。这个部分一般是请求参数的附加。之前说过,GET方法是不包含请求体的,所以GET方法的HTTP请求想要附加参数只能使用这种方式。当然其他方法也是可以使用这种方式附加参数,只要服务器同意就可以了。query-string的格式任意,但在客户端和服务器之间也有预先定好的约定,即键值对的形式。query-string可以表示成一系 列键值对的集合,用以下方式表示:

k1=v1&k2=v2&k3=&k4

在这里,&分隔不同的键值对,=表示的关系。可以看到一共有四个键值对关系,它们是:

  • k1: v1

  • k2: v2

  • k3: 空字符串

  • k4: 起码该键被定义了

一般来说,键值对要写成k=v的形式,但是k=和仅仅一个k都是允许的,前者表示键k的值是空字符串,后者表示k定义了,但是其值是什么并不关心。

从上面的例子中发现,在query-string中&=被用于特殊的用途了,我们不能再在其中从容地使用这两个符号了。如果我们要在值中包含这两个符号,那咋办呢?方法就是,编码

在实际的HTTP请求消息中,对于如下的键值关系

k1: &k2: =

具体的query-string要写成:

k1=%26&k2=%3D

这是因为在ASCII编码中,&的16进制表示是26=的16进制表示是3D。对于需要的编码,就要表示成其实际编码的16进制表示,每个字节都用一个%XX三个字符进行表示。这样,%本身也就要进行编码了,它的编码是%25。除了这些控制字符的编码,还可以进行中文等非英语语言的编码。

对于编码部分,我推荐阮一峰的一篇博文:

关于URL编码

虽然看了也未必懂了,但是最起码知道编码不是一件简单的事情。

HTTP请求消息消息头部

HTTP请求消息消息头部格式与之前所说的消息头格式没什么两样,就是以冒号分隔的键值对。HTTP请求消息的请求头中,既包含预定义头(如Content- Type、Content-Length等),也支持自定义头。原本打算多列出几个常见的请求头的,但限于精力,不打算这样做了。我只说说我最常用的Content-Type头吧。

Content-Type头,既可用于HTTP请求消息,也可用于HTTP响应消息,是规定请求正文内容格式的头部。例如利用这个头部,我们可以规定正文格式为纯文本格式、表单格式、XML格式、JSON格式、图像格式等。例如Content-Type: application/json就表示JSON文本格式。

在小节的末尾,我良心地给出一个关于HTTP预定义头的参考网址:

HTTP消息头大全

HTTP响应消息

HTTP响应消息的基本格式也是一样的,包含三个部分:

  1. 响应行(属于首行)

  2. 响应头(属于头部)

  3. 响应正文(属于正文)

响应头部响应正文我觉得不需要再多说了。

需要注意的是:当一个浏览器给服务器发送请求后,无论服务器页面有没有out.println()方法中有没有要打印的东西,HTTP响应消息都会返回,只不过是响应的内容是空的。

响应行的基本格式是:

版本号 状态码 状态文本

例如下面的响应行:

HTTP/1.1 200 OK

其对应关系为:

  • 版本号:HTTP/1.1

  • 状态码:200

  • 状态文本:OK

HTTP状态码主要表示应答的状态。状态码是由3个数字表示,其中第一个数字表示一个大状态,后面两个数字表示该大状态的一个子状态。200就表示操作成功,还有其他常见的如403表示不能浏览目录,404表示对象未找到,500表示服务器错误等等。

状态码一共分为五个大状态,它们是:

  • 1xx

  • 2xx:请求成功处理

  • 3xx

  • 4xx:客户端出错

  • 5xx:服务器端出错

HTTP状态码大全

HTTP协议示例

接下来的所有示例中,我们将代码都写成前面的一行一行的模式,但略去。这时只要记住每行的结尾都暗含一个CRLF控制就可以了。例如:

GET /simple.html?bg=white HTTP/1.1
Accept: text/html
Accept-Language: zh-cn
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0
Host: localhost:8080
Connection: Keep-Alive

GET请求没有请求正文,但可以包含query-string。

POST请求可以包含请求正文,例如下面带JSON格式正文的POST请求:

POST /test/demo_form.asp HTTP/1.1
Host: w3schools.com
Content-Type: application/json
Content-Length: 38{"name1": "value1", "name2": "value2"}

一个返回404错误的响应示例:

HTTP/1.1 404 Not Found
Date: Mon, 06 Mar 2006 09:03:14 GMT
Server: Apache/2.0.55 (Unix) PHP/5.0.5
Content-Length: 291
Keep-Alive: timeout=15, max=100
Connection: Keep-Alive
Content-Type: text/html; 
charset=iso-8859-1 
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head><title>404 Not Found</title></head><body><h1>Not Found</h1><p>The requested URL /notexist was not found on this server.</p><hr><address>Apache/2.0.55 (Unix) PHP/5.0.5 Server at localhost Port 8080</address></body>
</html>

 

转载于:https://my.oschina.net/wangsifangyuan/blog/650991

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/458902.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

float数据在计算机内存中的存储方法

*************************************************** 更多精彩&#xff0c;欢迎进入&#xff1a;http://shop115376623.taobao.com *************************************************** 浮点型变量在计算机内存中占用4字节&#xff08;Byte&#xff09;,即32-bit。遵循IEEE…

Geometric Shapes - POJ 3449(多边形相交)

题目大意&#xff1a;给一些几何图形的编号&#xff0c;求出来这些图形都和那些相交。分析&#xff1a;输入的正方形对角线上的两个点&#xff0c;所以需要求出来另外两个点&#xff0c;公式是&#xff1a;x2:(x1x3y3-y1)/2; y2:(y1y3x1-x3)/2;x4:(x1x3-y3y1)/2; y4:(y1y3-x1x3…

更新10_linux,时隔十年,QQ更新了Linux版本

昨天1024程序员节&#xff0c;QQ悄悄地更新了QQ for Linux&#xff0c;也许是给各位一个惊喜吧。官网及其的简陋。和一个Word文档似的。十年一更&#xff0c;有网友称&#xff0c;瞬间回到QQ2006&#xff0c;确实界面功能有些落后&#xff0c;相信QQ可以跟上潮流的&#xff0c;…

[渗透测试]扫目录,Sqlmap利用均超时,利用dirb扫描

今天碰到一个网友传来的Webshell地址&#xff0c;问我对方如何取得webshell。 网站为阿里云服务器&#xff0c;存在明显的注入漏洞&#xff0c;但是任何语句都会令网页报错&#xff0c;sqlmap一直超时&#xff0c;御剑扫描目录1个线程也会导致被屏蔽IP。 经一学长提点&#xff…

x = x+1,x+=1,x++那个的执行效率高

*************************************************** 更多精彩&#xff0c;欢迎进入&#xff1a;http://shop115376623.taobao.com *************************************************** x x1的效率最低 1&#xff09;读取右边x的地址 2&#xff09;执行x13&#xff09;读…

修正线性单元(Rectified linear unit,ReLU)

修正线性单元&#xff08;Rectified linear unit&#xff0c;ReLU&#xff09; Rectified linear unit 在神经网络中&#xff0c;常用到的激活函数有sigmoid函数f(x)11exp(−x)、双曲正切函数f(x)tanh(x)&#xff0c;今天要说的是另外一种activation function&#xff0c;recti…

C语言综合期末作业,内蒙古农业大学2010年期末c语言综合作业.doc

内蒙古农业大学2010年期末c语言综合作业综合练习作业#includeint main(void){int choice,i;void shuai();void ge();void wang();void bing();for(i1;i<5;i){printf("[1]统计字符个数\n");printf("[2]判断素数\n");printf("[3]求斐波那契数列\n&qu…

链表创建、逆置、删除详解

*************************************************** 更多精彩&#xff0c;欢迎进入&#xff1a;http://shop115376623.taobao.com *************************************************** 对链表的理解&#xff1a;http://www.nowamagic.net/librarys/veda/detail/2220 #inc…

python与shell的3种交互方式介绍

【目录】 1.os.system(cmd) 2.os.popen(cmd) 3.利用subprocess模块 4.subprocessor模块进阶 【概述】 考虑这样一个问题&#xff0c;有hello.py脚本&#xff0c;输出”hello, world!”&#xff1b;有testinput.py脚本&#xff0c;等待用户输入&#xff0c;然后打印用户输入的数…

C语言里if语句变量作为判断条件,C语言教学(九-上)if else判断语句

原标题&#xff1a;C语言教学(九-上)if else判断语句今天讲if else判断语句&#xff0c;简单理解就是进行条件判断&#xff0c;如果条件达到则执行if 里或else里的语句。先来看if。if的写法和for差不多,就是不用括号里的两个分号&#xff0c;if (条件) { }&#xff0c;if加括号…

const修饰指针和引用的用法【转贴】

*************************************************** 更多精彩&#xff0c;欢迎进入&#xff1a;http://shop115376623.taobao.com *************************************************** const修饰的指针会额外的占内存吗&#xff1f; 仍然是4&#xff0c;不会占额外的…

调整linux系统时区

cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime 好吧&#xff0c;使用tzselect又靠谱些&#xff0c;使用前把/etc/localtime删除了。 执行上前那个告诉我文件重新了&#xff0c;所以就没有搞了转载于:https://www.cnblogs.com/hark0623/p/4807426.html

stm32c语言设计以及注释,13个基于STM32的经典项目设计实例,全套资料~-嵌入式系统-与非网...

STM32单片机现已火遍大江南北&#xff0c;各种教程资料也是遍布各大网站论坛&#xff0c;可谓一抓一大把&#xff0c;但大部分都差不多。今天总结了几篇电路城上关于STM32 的制作&#xff0c;不能说每篇都是经典&#xff0c;但都是在其他地方找不到的&#xff0c;很有学习参考意…

memcpy,strcpy,strncpy

*************************************************** 更多精彩&#xff0c;欢迎进入&#xff1a;http://shop115376623.taobao.com *************************************************** memcpy c和c使用的内存拷贝函数.从源src所指的内存地址的起始位置开始拷贝n个字节…

二维数组联通子数组和最大

题目要求&#xff1a; 返回一个二维整数数组中最大联通子数组的和。输入一个二维整形数组&#xff0c;数组里有正数也有负数。文件输出。思路:和之前的动态规划相识&#xff0c;把二维数组转换为一维数组&#xff0c;先求每一个列的子数组和最大&#xff0c;最后在用正数就加&a…

c语言如何给变量加锁,C语言互斥锁-条件变量实现公共缓存区数据读写

#include char buffer[128];int has_data0;pthread_mutex_t mutex;pthread_cond_t cond;pthread_cond_t cond2;void read_buf(void){do{pthread_mutex_lock(&mutex);//锁定互斥锁if(has_data0){/*阻塞线程,等待另外一个线程发送信号&#xff0c;同时为公共数据区解锁*/pthr…

view-activity跟控件在onkey事件上的传递关系

android 中Activity跟View对于键盘的监听&#xff0c;主要有以下几个方法 //按键按下 public boolean onKeyDown(int keyCode, KeyEvent event) {} //按键弹起 public boolean onKeyUp(int keyCode, KeyEvent event) {} //常按 public boolean onKeyLongPress(int keyCode, Ke…

PMP考试的过与不过

*************************************************** 更多精彩&#xff0c;欢迎进入&#xff1a;http://shop115376623.taobao.com *************************************************** 我在一年多时间里参加了三次PMP考试&#xff0c;前两次都失败&#xff0c;直到第三次才…

JPA一对多循环引用的解决

说是解决&#xff0c;其实不是很完美的解决的&#xff0c;写出来只是想记录一下这个问题或者看一下有没有哪位仁兄会的&#xff0c;能否知道一二。 下面说说出现问题&#xff1a; 问题是这样的&#xff0c;当我查询一个一对多的实体的时候&#xff0c;工具直接就爆了&#xff0…

太原理工大学c语言课程设计报告,[太原理工大学C语言实验报告.doc

[太原理工大学C语言实验报告本科实验报告课程名称&#xff1a; 程序设计技术B实验项目&#xff1a;实验地点&#xff1a; 明向校区软件学院机房专业班级&#xff1a; 学号&#xff1a;学生姓名&#xff1a;指导教师&#xff1a; 呼克佑2014年 12月 日实验名称 实验一 C语言的运…