HTTP协议

简介: HTTP协议


什么是HTTP?

       HTTP全称"超文本传输协议",是一种应用非常广泛的应用层协议.

理解"应用层协议"

       我们学过TCP/IP协议, 已经知道目前数据可以从客户端进程经过路径算则, 跨网络传输到服务器进程, 可是, 仅仅是把数据从A传输到B点就完事了吗?

       这就好比, 在饿了吗上面点了一个手抓饼, 卖家通过联系外卖员来将其送到买家手上, 这就完事了吗? 当然不是, 买家还要品尝这个手抓饼, 看味道是否正常,质量是否过关, 吃完之后还可以给卖家打分评论.

       所以,我们把数据从A端传送到B端, TCP/IP协议实现的是卖家联系外卖员送外卖这个过程, 但是两端还要对数据进行加工或者使用, 所以我们还需要一层协议, 这个协议不必在意数据传输的细节, 而是关心应用的细节.

       这层协议就叫做应用层协议, 而应用是有不同场景的,所以应用层的协议是具有很多种类的, 其中这类协议中的HTTP就是这一类http协议的佼佼者.

http协议工作过程

       例如我们在浏览器中搜索一个网址, 此时浏览器接收到这个HTTP请求,就会通过各种路由选择传输给对方的服务器, 经过对方服务器的处理之后, 服务器就会返回一个http响应:

HTTP的格式

        http是一个文本格式的协议,可以通过chrome开发者工具或者Fiddler抓包,分析HTTP请求/响应的细节

抓包工具的使用(Fiddler)

       使用Fiddler为例子, 下载链接: 显示如下官网页面

选择Fiddler Classic进行下载.

打开Fiddler:

选择Tools -> option:

选择HTTPS, 并将其全部勾选:

注意: 勾选的时候会弹出一个弹窗,此时选择"yes", 否则就只能重装Fiddler了

抓包工具原理

        浏览器访问baidu.com的时候, 就会把HTTP请求先发送给Fiddler, Fiddler再把请求转发给百度的服务器, 搜狗返回数据的时候, Fiddler就会拿到返回的数据, 再将其交给浏览器.

       因此Fiddler对于浏览器和百度服务器之间交互的数据细节, 都是非常清楚的.

抓包的结果

       以访问百度的主页为例子:

首先我们清空Fiddler的内容(ctrl + A + DELETE):

然后我们访问百度的主页, Fiddler就会自动抓取:

可以看见里面有很多颜色的表示, 具体含义如下:

'

HTTP请求

我们点开一个蓝色的HTTP的文件, 选择raw查看原始报文:

点击view in notepad就会在记事本中打开 .

解释如下:

  1. 首行: [方法] + [url] + [版本]
  2. Header: 请求的属性, 为冒号分割的键值对, 每组属性直接使用'\n'来分隔, 遇到空行表示Header部分结束
  3. Body: 空行后面的内容, Body允许使用空字符串, 如果Body存在, 则header中会有Content-Length属性来表示Body的长度.

HTTP响应

解释如下:

  1. 首行: [版本号] + [状态码] + [状态码解释]
  2. Header: 请求的属性, 为冒号分割的键值对, 每组属性直接使用'\n'来分隔, 遇到空行表示Header部分结束
  3. Body: 空行后面的内容, Body允许使用空字符串, 如果Body存在, 则header中会有Content-Length属性来表示Body的长度.

协议格式总结

HTTP请求

URL

URL基本格式

        我们平时说的网址, 其实就是说的URL, 也就是统一资源定位符, 英文全称Uniform Resource Locator.

       互联网上每一个文件都有唯一的URL, 他包含的信息指出文件的位置, 以及浏览器应该怎么处理他.

       URL详细规则由因特网标准rfc1738进行约定.

关于 URL encode

       像 / ? : 等这样的字符, 已经被url当做特殊意义理解了. 因此这些字符不能随意出现.

比如, 某个参数中需要带有这些特殊字符, 就必须先对特殊字符进行转义.

一个中文字符由 UTF-8 或者 GBK 这样的编码方式构成, 虽然在 URL 中没有特殊含义, 但是仍然需要进行转义. 否则浏览器可能把 UTF-8/GBK 编码中的某个字节当做 URL 中的特殊符号.

转义的规则如下: 将需要转码的字符转为16进制,然后从右到左,取4位(不足4位直接处理),每2位做一位,前面加上%,编码成%XY格式:

方法

方法, 也就是HTTP请求的首行中的类似于GET和POST等字眼:

下面我们介绍几个最常用的方法, 他们使用的频率站全部方法的90%左右,

GET

       一般大部分请求都是Get, GET是http最长用的方法, 常用于获取服务器上的某个资源.在浏览器中直接输入URL,此时浏览器就会发送一个get请求,另外,HTML中的link, img, script等标签,也会触发get请求.

get请求的特点:

  1. 首行的第一部分为GET
  2. URL的query string可以为空,也可以不为空
  3. header部分有若干个键值对结构
  4. bofy部分为空

关于get请求的URL长度问题:

       其实网上描述的get请求最长1024kb这样的说法是错误的,HTTP协议由RFC2616标准定义, 标准中明确定义对URL的长度没有任何限制, 时间URL的长度取决于浏览器的实现, 和HTTP服务器端的实现, 在浏览器端, 不同的浏览器最大长度是不同的, 但是现代浏览器支持的长度一般很长,在服务器端, 一般这个长度是可以配置的.

POST

       POST 方法也是一种常见的方法. 多用于提交用户输入的数据给服务器(例如登陆页面).

通过 HTML 中的 form 标签可以构造 POST 请求, 或者使用 JavaScript 的 ajax 也可以构造 POST 请求.

使用 Fiddler 观察 POST 方法:

在某登录系统中:输入用户名, 密码, 验证码之后, 点击登陆, 就可以看到 POST 请求:

POST https://xxxxx/login HTTP/1.1

Host: v.bitedu.vip

Connection: keep-alive

Content-Length: 105

sec-ch-ua: " Not;A Brand";v="99", "Google Chrome";v="91", "Chromium";v="91"

sec-ch-ua-mobile: ?0

User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML,

like Gecko) Chrome/91.0.4472.77 Safari/537.36

Access-Control-Allow-Methods: PUT,POST,GET,DELETE,OPTIONS

Content-Type: application/json;charset=UTF-8

Access-Control-Allow-Origin: *

Accept: application/json, text/plain, */*

Access-Control-Allow-Headers: Content-Type, Content-Length, Authorization,

Accept, X-Requested-With , yourHeaderFeild

Origin: https://v.bitedu.vip

Sec-Fetch-Site: same-origin

Sec-Fetch-Mode: cors

Sec-Fetch-Dest: empty

Referer: https://v.bitedu.vip/login

Accept-Encoding: gzip, deflate, br

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

Cookie: username=123456789; rememberMe=true

{"username":"123456789","password":"xxxx","code":"jw7l","uuid":"d110a05ccde64b16

a861fa2bddfdcd15"}

一般什么时候能看到POST?

  • 登录
  • 上传文件

post请求的特点:

  1. 首行的第一部分为POST
  2. URL的query string 一般为空(也可以不为空)
  3. header部分有若干个键值对结构
  4. body部分一般补位空, body内的数据格式通过header中的content-Type来指定,body的长度有header中的Content-Length指定
GET个POST的区别

       get / post 表示的是不同的语义, 但是实际上也并非需要严格遵守, http的语义, 只是一种建议, 程序员使用的时候也不一定非得遵守,对于body有没有的问题, 也不是绝对的, get也可能有body, post也可能没有body, 但是这都是少见的.

       那这两有啥区别? 本质上是没有区别的, 使用get的场景, 替换成post一般也可以使用, 使用post的场景换成get也可以.

       但是二者还是存在使用上的区别的:

  1. get习惯上用来表示获取数据, 而post用来表示提交数据
  2. get一般没有body, 需要携带数据则需要放到URL中, post一般有body
  3. get请求通常会设计成幂等的, post则无要求
  4. get可缓存, post不能
  5. get可以被浏览器搜藏, post不能

幂等

       幂等是一种学术用于, 也就是如果输入是一定的, 那么得到的输出也是一定的, 这种情况就是幂等的.

       幂等在服务器开发是很关键的, 因为设计成幂等之后就可以设计缓存了, 例如我需要知道5的阶乘是多少, 那么我将这个请求发送给服务器, 服务器计算得到的结果为120后, 先缓存这个结果然后再把结果响应给我们, 下次有人去问5!是多少的时候, 他就会直接回答是120, 这就有点类似于我们的乘法口诀表,当别人问我们9*9是多少的时候, 我们大脑中已经缓存了9*9的结果, 也就是81此时就直接使用不需要计算, 这也就节约了计算资源.

       我们得到结果之后, 也可以吧计算结果保存下来, 这样下次再遇到需要计算5!的请求,我们就不必要发送给服务器计算, 直接那结果就行.

header的格式就是键值对的结构,每一个键值对占一行, 键值对之间使用分号分割.

Host

       表示服务器主机的地址和端口.

Content-Length

       表示body中的数据的长度

Content-Type

       表示请求的body中的数据格式, 常见选项如下:

  • application/x-www-form-urlencoded:form 表单提交的数据格式, 此时body格式如下:

title=test&content=hello

  • multipart/form-data: form 表单提交的数据格式(在form标签中加上,enctyped="multipart/form-data"). 通常用于提交图片,文件, body格式如下

Content-Type:multipart/form-data; boundary=----WebKitFormBoundaryrGKCBY7qhFd3TrwA

------WebKitFormBoundaryrGKCBY7qhFd3TrwA

Content-Disposition: form-data; name="text"

title

------WebKitFormBoundaryrGKCBY7qhFd3TrwA

Content-Disposition: form-data; name="file"; filename="chrome.png"

Content-Type: image/png

PNG ... content of chrome.png ...

------WebKitFormBoundaryrGKCBY7qhFd3TrwA--

  • application/json: 数据格式为json格式, body的格式如下:

{"username":"123456789","password":"xxxx","code":"jjjss"}

User-Agent

表示浏览器/操作系统的属性, 形如:

Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko)

Chrome/91.0.4472.77 Safari/537.36

其中:

  • 其中 Windows NT 10.0; Win64; x64 表示操作系统信息
  • AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.77 Safari/537.36 表示浏览器信
    息.
Referer

表示这个页面是从哪个页面跳转过来的.

https://v.bitedu.vip/login

如果直接在浏览器中输入URL, 或者直接通过收藏夹访问页面时是没有 Referer 的

body

       body的格式和header中的Content-Type 密切相关, 罗列三种常见的情况

①application/x-wwwx-form-urlencoded

        抓取码云上传头像的请求:

POST https://gitee.com/profile/upload_portrait_with_base64 HTTP/1.1
Host: gitee.com
Connection: keep-alive
Content-Length: 107389
sec-ch-ua: " Not;A Brand";v="99", "Google Chrome";v="91", "Chromium";v="91"
Accept: */*
X-CSRF-Token: 6ROfZGr4Y7Qx8td1TuKCnrG8gbODLCSUqUBZSw2b+ac=
X-Requested-With: XMLHttpRequest
sec-ch-ua-mobile: ?0
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML,
like Gecko) Chrome/91.0.4472.101 Safari/537.36
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
Origin: https://gitee.com
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: cors
Sec-Fetch-Dest: empty
Referer: https://gitee.com/HGtz2222
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
Cookie: oschina_new_user=false; user_locale=zh-CN; yp_riddler_id=1ce4a551-a160-
4358-aa73-472762c79dc0; visit-gitee--2021-05-06%2010%3A12%3A24%20%2B0800=1;
sensorsdata2015jssdkcross=%7B%22distinct_id%22%3A%22726826%22%2C%22first_id%22%3
A%22175869ba5888b6-0ea2311dc53295-303464-2073600-
175869ba5899ac%22%2C%22props%22%3A%7B%22%24latest_traffic_source_type%22%3A%22%E
7%9B%B4%E6%8E%A5%E6%B5%81%E9%87%8F%22%2C%22%24latest_search_keyword%22%3A%22%E6%
9C%AA%E5%8F%96%E5%88%B0%E5%80%BC_%E7%9B%B4%E6%8E%A5%E6%89%93%E5%BC%80%22%2C%22%2
4latest_referrer%22%3A%22%22%7D%2C%22%24device_id%22%3A%22175869ba5888b6-
0ea2311dc53295-303464-2073600-175869ba5899ac%22%7D; remote_way=svn;
tz=Asia%2FShanghai;
Hm_lvt_24f17767262929947cc3631f99bfd274=1622637014,1622712683,1622863899,1623298
442; gitee_user=true; Hm_lpvt_24f17767262929947cc3631f99bfd274=1623298560; giteesessionn=c0hXQ0I5SjR1bWg5M01IR3RYS3hLT0RhelN1aFVuMExKdEdSSmRaQWIwRy9QWFUwV0thdzV1alIzYj
RaOU9ZeDdkZEJZK2RtTVRNeTNFRHNYVW9ha2hEcWJyclIwS1NVRG1EL0xxTmJXSGxvSzh3c28zOHBia1
pIOFQrU3RYeWE0bE13S09DTm5MZWZ5WW5WUVFpSzFiMGFWbHRDQ0xRakc1Um5yY21HQllqeUpNLzBvZF
gxbHVhN09uK2h1VVVmRHZkS3BmVGEwcDhyNjJVb1p0RFRLY0VOem5vNEEvd0FuYzJJYlhZcGlyenZQc3
dSbXBNUWI3UUwrRDBrV2N0UHZRdjFBUXF5b0Y0L1Vrd09pQVBKNkdjZmY5cHlDTCtMWG4ya0tIaW5LcE
tBTkw4cGFGVjhUQ0djMWhkOXI0bUFteUY4VW80RHl2T2Q2YmxwR1d3M3Rad1RhZWhhdnNiTTNrcE1RV2
NyZ1dYeDRoR0dpanh4bERNMTBuenB1NkgxLS16QUdJS3NlZG9mTVBtYlVlREppck1BPT0%3D-
-898d1284181ca494918d29ac44f9a3a79d448a9b
avatar=data%3Aimage%2Fpng%3Bbase64%2CiVBORw0KGgoAAAANSUhEUgAAAPgAAAD4CAYAAADB0Ss
LAAAg......

       抓包的结果比较长, 就没有全部贴出

②application/json

       例如我们抓取某个登录页面的请求:

{"username":"123456789","password":"xxxx","code":"u58u","uuid":"9bd8e09ea27b48cd
acc6a6bc41d9f462"}
③multipart/form-data

HTTP响应

状态码

  • 200 OK : 表示访问成功
  • 404 Not Found : 没有找到资源
  • 403 Forbidden : 表示被拒绝访问, 没有特定的权限
  • 405 Method Not Allowed : 服务器不支持当前的方法
  • 500 Internal Server Error : 服务器内部错误
  • 504 Gateway Timeout : 服务器负载比较大的时候 就可能出现超时的情况
  • 302 Move temporary : 临时重定向
  • 301 Moved Permanently : 永久重定向, 后续的请求都是指定搞得新地址

状态码小结:

状态码 类别 原因
1xx Informatioanl (信息性状态码) 接收的请求正在处理
2xx Success(成功状态码) 请求正常处理完毕
3xx Redirection (重定向状态码) 需要进行附加操作完成请求
4xx Client Error(客户端错误状态码) 服务器无法处理请求
5xx Server  Error( 服务器错误状态码) 服务器处理请求出错


header

        响应报头header 的基本格式和请求报头 格式基本一致

       类似于Content-Type, Content-Length 等属性的含义也和请求中的含义一致.

对于Content-Type 常见取值有以下几种:

  • text/html : body 数据格式为 HTML
  • text/css : body 数据格式为CSS
  • application/javascript : body的数据格式为javascript
  • applicationj/json : body的数据格式是JSON

body

       也就是header里面对应的Content-Type 对应的内容

text/html

Server: nginx/1.17.3
Date: Thu, 10 Jun 2021 07:25:09 GMT
Content-Type: text/html; charset=utf-8
Last-Modified: Thu, 13 May 2021 09:01:26 GMT
Connection: keep-alive
ETag: W/"609ceae6-3206"
Content-Length: 12806
<!DOCTYPE html><html><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible
content="IE=edge,chrome=1"><meta name=renderer content=webkit><meta name=viewport
content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,userscalable=no"><link rel=icon href=/favicon.ico><title id=bodyTitle>比特教务管理系统
</title><link href=https://cdn.bootcss.com/jquerydatetimepicker/2.5.20/jquery.datetimepicker.css rel=stylesheet><script
src=https://cdn.bootcss.com/highlight.js/9.1.0/highlight.min.js></script><script
src=https://cdn.bootcss.com/highlightjs-line-numbers.js/2.5.0/highlightjs-linenumbers.min.js></script><style>html,
body,
#app {
height: 100%;
margin: 0px;
padding: 0px;
}
.chromeframe {
margin: 0.2em 0;
background: #ccc;
color: #000;
padding: 0.2em 0;
}
#loader-wrapper {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 999999;
}

text/css

HTTP/1.1 200 OK
Server: nginx/1.17.3
Date: Thu, 10 Jun 2021 07:25:09 GMT
Content-Type: text/css
Last-Modified: Thu, 13 May 2021 09:01:26 GMT
Connection: keep-alive
ETag: W/"609ceae6-3cfbe"
Content-Length: 249790
@font-face{font-family:element-icons;src:url(../../static/fonts/elementicons.535877f5.woff) format("woff"),url(../../static/fonts/elementicons.732389de.ttf) format("truetype");font-weight:400;font-style:normal}
[class*=" el-icon-"],
......

application/javascript

HTTP/1.1 200 OK
Server: nginx/1.17.3
Date: Thu, 10 Jun 2021 07:25:09 GMT
Content-Type: application/javascript; charset=utf-8
Last-Modified: Thu, 13 May 2021 09:01:26 GMT
Connection: keep-alive
ETag: W/"609ceae6-427d4"
Content-Length: 272340
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["app"],
{0:function(t,e,n){t.exports=n("56d7")},"00b3":function(t,e,n){},"
......

applicationj/json

HTTP/1.1 200
Server: nginx/1.17.3
Date: Thu, 10 Jun 2021 07:25:10 GMT
Content-Type: application/json;charset=UTF-8
Connection: keep-alive
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
vary: accept-encoding
Content-Length: 12268
{"msg":"操作成功","code":200,"permissions":[] }

通过form表单构造HTTP请求

       form 是HTML里面常用的标签,  可以用于给服务器发送get  或者POST请求"::"

此处需要注意的是不要把form 拼写成了 from

form 发送get请求

       form 的重要参数

  • action : 构造的HTTP请求的 URL 是什么
  • method : 够早的 HTTP请求的方法是get 还是 Post ( form 表单只支持get和 post)

        input 的重要参数:

  • type : 表示 输入框的类型.... text 表示 文本, password 表示密码, submit 表示提交按钮
  • name : 表示构造出的 HTTP请求的 query String 的 key, querystring 的value 就是输入框的用户输入的内容
  • value : input 标签的值, 对于 type' 为submit 的类型来说 , value 就对应了按键上显示的文本

例如, 下面是一个form 表单::

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>test</title>
</head>
<body>
    <form action="http://abcdef.com/myPath" method="get">
        <input type="text" name="userId">
        <input type="text" name="classId">
        <input type="submit" value="提交">
    </form>
</body>
</html>

下面是发送出去的HTTP请求:

GET http://abcdef.com/myPath?userId=100&classId=200 HTTP/1.1
Host: abcdef.com
Proxy-Connection: keep-alive
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML,
like Gecko) Chrome/91.0.4472.114 Safari/537.36
Accept:
text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,imag
e/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8

GET http://abcdef.com/myPath?userId=100&classId=200 HTTP/1.1

Host: abcdef.com

Proxy-Connection: keep-alive

Upgrade-Insecure-Requests: 1

User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML,

like Gecko) Chrome/91.0.4472.114 Safari/537.36

Accept:

text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,imag

e/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9

Accept-Encoding: gzip, deflate

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

他们是一一对应的::

form 发送post请求

        发送post请求只需要把form表单里面的 method修改为post:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>test</title>
</head>
<body>
    <form action="http://abcdef.com/myPath" method="post">
        <input type="text" name="userId">
        <input type="text" name="classId">
        <input type="submit" value="提交">
    </form>
</body>
</html>

构造的 HTTP 请求

POST http://abcdef.com/myPath HTTP/1.1
Host: abcdef.com
Proxy-Connection: keep-alive
Content-Length: 22
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Origin: null
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML,
like Gecko) Chrome/91.0.4472.114 Safari/537.36
Accept:
text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,imag
e/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
userId=100&classId=200

主要的区别:

  • method 从get变成了 get了
  • 数据从queryString 移动到了 body中去了

使用form 表单还可以提交文件

通过ajax 构造http请求

       从前端角度, 除了浏览器地址栏能构造 GET 请求, form 表单能构造 GET 和 POST 之外, 还可以通过 ajax的方式来构造 HTTP 请求. 并且功能更强大....

ajax 全称 Asynchronous Javascript And XML, 是 2005 年提出的一种 JavaScript 给服务器发送HTTP 请求的方式.

特点是--->>  可以不需要 刷新页面/页面跳转 就能进行数据传输

发送get请求

创建 test.html . 在 script标签中编写如下代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>test</title>
</head>
<body>
    <script>
        // 1. 创建 XMLHttpRequest 对象
        let httpRequest = new XMLHttpRequest();
 
        // 2. 默认异步处理响应. 需要挂在处理响应的回调函数
        httpRequest.onreadystatechange = function () {
            // readState 表示当前的状态.
            // 0: 请求未初始化
            // 1: 服务器连接已建立
            // 2: 请求已接收
            // 3: 请求处理中
            // 4: 请求已完成,且响应已就绪
            if (httpRequest.readyState == 4) {
 
                // status 属性获取 HTTP 响应状态码
                console.log(httpRequest.status);
 
               // responseText 属性获取 HTTP 响应 body
                console.log(httpRequest.responseText);
            }
        }
        httpRequest.open('GET','http://42.192.83.143:8080/AjaxMockServer/info');
        httpRequest.send;
    </script>
</body>
</html>

其中:

  • onreadystatechange : 存储函数, 每当readyState 属性改变的时候, 就会调用该函数
  • readyState : 存有XMLHttpRequest 的状态, 从0 ~4 变化
  • status : 200: OK, 404: 未找到资源.......

发送 POST 请求

对于 POST 请求, 需要设置 body 的内容

1. 先使用 setRequestHeader 设置 Content-Type

2. 再通过 send 的参数设置 body 内容

发送 application/x-www-form-urlencoded 数据 (数据格式同 form 的 post)

// 1. 创建 XMLHttpRequest 对象
let httpRequest = new XMLHttpRequest();
// 2. 默认异步处理响应. 需要挂在处理响应的回调函数.
httpRequest.onreadystatechange = function () {
// readState 表示当前的状态.
// 0: 请求未初始化
// 1: 服务器连接已建立
// 2: 请求已接收
// 3: 请求处理中
// 4: 请求已完成,且响应已就绪
if (httpRequest.readyState == 4) {
// status 属性获取 HTTP 响应状态码
console.log(httpRequest.status);
// responseText 属性获取 HTTP 响应 body
console.log(httpRequest.responseText);
}
}
// 3. 调用 open 方法设置要访问的 url
httpRequest.open('POST', 'http://42.192.83.143:8080/AjaxMockServer/info');
// 4. 调用 setRequestHeader 设置请求头
httpRequest.setRequestHeader('Content-Type', 'application/x-www-formurlencoded');
// 5. 调用 send 方法发送 http 请求
httpRequest.send('name=zhangsan&age=18');

发送 application/json 数据

// 4. 调用 setRequestHeader 设置请求头
httpRequest.setRequestHeader('Content-Type', 'application/json');
// 5. 调用 send 方法发送 http 请求
httpRequest.send(JSON.stringify({
name: 'zhangsan',
age: 18
}));
封装 ajax 方法

        原生的 XMLHTTPRequest 类使用并不方便. 我们可以在这个基础上进行简单封装

<!DOCTYPE html>
<html lang="en">
 
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>test</title>
</head>
 
<body>
    <script>
        // 参数 args 是一个 JS 对象, 里面包含了以下属性
        // method: 请求方法
        // url: 请求路径
        // body: 请求的正文数据
        // contentType: 请求正文的格式
        // callback: 处理响应的回调函数, 有两个参数, 响应正文和响应的状态码
        function ajax(args) {
            var xhr = new XMLHttpRequest();
            xhr.onreadystatechange = function () {
                // 0: 请求未初始化
                // 1: 服务器连接已建立
                // 2: 请求已接收
                // 3: 请求处理中
                // 4: 请求已完成,且响应已就绪
                if (xhr.readyState == 4) {
                    args.callback(xhr.responseText, xhr.status)
                }
            }
            xhr.open(args.method, args.url);
            if (args.contentType) {
                xhr.setRequestHeader('Content-type', args.contentType);
            }
            if (args.body) {
                xhr.send(args.body);
            } else {
                xhr.send();
            }
        }
        // 调用该函数
        ajax({
            method: 'get',
            url: '/info',
            callback: function (body, status) {
                console.log(status);
                console.log(body);
            }
        });
    </script>
</body>
 
</html>


 


目录
相关文章
|
1月前
|
缓存 安全 前端开发
探索HTTP协议:网络通信的基石
探索HTTP协议:网络通信的基石
|
1月前
|
缓存 自然语言处理 前端开发
第一章 引言-HTTP协议基础概念和前后端分离架构请求交互概述
第一章 引言-HTTP协议基础概念和前后端分离架构请求交互概述
|
9天前
|
开发框架 前端开发 应用服务中间件
基于RFC6265 (HTTP状态管理协议)实现简单的登录系统
基于RFC6265 (HTTP状态管理协议)实现简单的登录系统
11 0
|
11天前
|
安全 前端开发 中间件
中间件中HTTP/HTTPS 协议
【6月更文挑战第3天】
14 3
|
11天前
|
程序员 API 开发者
Socket与HTTP协议的实践
【6月更文挑战第4天】本文介绍了Python中的网络编程,包括Socket编程和基于HTTP协议的实践。Socket编程是网络通信的基础,Python的`socket`模块简化了其使用。文中展示了服务器和客户端的简单示例,以及如何通过多线程处理多个客户端连接。另外,文章讨论了HTTP协议,推荐了`requests`库,并给出了发送GET和POST请求的例子。最后,总结了Socket编程和HTTP协议在网络编程中的应用及其在Web开发和API交互中的重要性。
18 5
|
13天前
|
传感器 物联网
物联网协议概述:MQTT、CoAP 和 HTTP
【6月更文挑战第3天】探索物联网的三大协议——MQTT、CoAP 和 HTTP。MQTT 是高效的消息传递使者,适用于大规模、不稳定网络环境;CoAP 小巧灵活,适合资源有限的设备;HTTP 则是熟悉的网络通信老将。根据不同场景选择合适的协议,让物联网设备有效交流。示例代码展示它们的使用方式。
31 0
|
16天前
|
网络协议 开发者 UED
【计算巢】HTTP/2 与 HTTP/3:下一代 Web 协议的优势
【5月更文挑战第31天】HTTP/2 & HTTP/3,两大网络协议超级英雄,通过二进制分帧、多路复用提升效率,QUIC协议让HTTP/3实现更快连接与低延迟。代码示例展示HTTP/2高效请求,它们为用户带来更快加载速度,改善体验,尤其利于高延迟应用。对开发者意味着更高性能,为网站注入超级引擎。未来,它们将在更多领域发挥作用,点亮数字世界。
|
16天前
|
Oracle Java 关系型数据库
http 协议深入介绍(二)
http 协议深入介绍(二)
|
16天前
|
网络协议 前端开发 应用服务中间件
http 协议深入介绍(一)
http 协议深入介绍(一)
|
18天前
|
缓存 安全 网络协议
HTTP协议中Via的用法
【5月更文挑战第29天】Web请求通过代理服务器的情况,强调了随着代理的普及,追踪报文流以解决网络问题的重要性。