HTTP 基础
其实很多面试问 HTTP 的 3 次握手, 4 次挥手, 我觉得价值不大, 可以帮助你理解 HTTP 的原理, 死背硬记的对于你开发没有作用, 而是去理解它就行.
前端只关心 URL,headers 和 data, 接下来也围绕着它们展开.
了解 HTTP 请求可以看看:
1. 了解 URL
URL 比较简单, 就简单介绍一下, 将 URL 分为主要的 3 部分:
router, 路由. 路由地址可不能错, 这就跟收件地址一样, 填错收货的就不是既定的那个人了.
search, 查询字符串, 就是? 后面的字符串, 以键值对的形式通过 "&" 连接, 例如:"?key1=value1&key2=value2". 查询字符串就是发送到后台的数据, 跟普通的 post 请求相比, get 请求以明文的形式存储在访问历史, 浏览器和路由器都很容易查得到, 容易泄露, 所以不建议用 get 请求; 其次一般浏览器都有限制 URL 的长度, 所以不适合发送大数据量的数据.
hash, 哈希值或者称为锚, 是 #后面的字符串, 一般作为单页应用的路由地址, 或者文档的锚.
2. 前端常用的 headers
2.1.Content-Type(重要)
告诉客户端, 用什么形式前端的数据发送到后台: application/x-www-form-urlencoded,multipart/form-data,text/plain 等.
2.2 application/x-www-form-urlencoded
最常见的方式以键值对的字符串传输(类似 URL 的 search), 但不能传输文件, 几乎所有的 Ajax 框架都是默认以此种方式发送.
发送到后台的数据见下图:
2.3 multipart/form-data
这种方式会以键值对的形式通过分隔符链接, 以字符串给后台, 可以传输文件, 也可以传输普通数据.
常用场景:
- // 源生的 form 提交可设置 enctype="multipart/form-data", 一般表单中有文件会自动设为该值
- <form action="post" enctype="multipart/form-data"></form>
- // Ajax 请求, 通过 formdata 对象来达成此目的
- const formdata = new new FormData();
- formdata.append("key","value")
- $.Ajax({
- ...
- data: formdata,
- processData: false, // 取消对数据的预处理, 因为 formdata 不需要预处理
- headers: {
- "Content-Type": undefined // 客户端会自动给它设置正确的值, 不要设为 multipart/form-data, 这样设的后果会导致分隔符不正确
- },
- ...
- })
如果在抓包确认划线的一致的话就是正确发送过去了.
2.4text/plain
这个很少会用到了, 普通文本, 可以是任意数据, 除了文件.
2.5binary
二进制流, 仅限一个文件.
3 Data-Type
告诉后台你希望返回什么类型的数据, 如 xml,html,script,JSON,JSONP,text 等, 或者你跟后台约定的也可. 但是实际返回的并非跟预期一致, 还是由后台决定的.
4 自定义 header
如果跟后台有约定 header, 如 token 等, 也可传到后台.
headers["token"] = "MD5KEY";
CORS 跨域
跨域问题的根本问题就是同源策略, 旨在防止网站被攻击, 这里不做赘述.
CORS 是后台的工作, 但前端工程师还是要了解 CORS, 这样才有后台抬杠的资本. 以下是后台 response 配置 CORS 的 headers, 如果后台不懂, 请让他了解了解 CORS.
Access-Control-Allow-Origin
简单说, 允许跨域访问的 host, 必须设置, 否则不允许跨域.
- // 如需允许所有资源都可以访问您的资源, 您可以如此设置:
- Access-Control-Allow-Origin: *
- // 如需允许 https://developer.mozilla.org 访问您的资源, 您可以设置:
- Access-Control-Allow-Origin: https://developer.mozilla.org
- Access-Control-Allow-Credentials
如果想跨域传输 cookies, 需要 Access-Control-Allow-Credentials 与 XMLHttpRequest.withCredentials 或 Fetch API 中的 Request() 构造器中的 credentials 选项结合使用. Credentials 必须在前后端都被配置 (即 the Access-Control-Allow-Credentials header 和 XHR 或 Fetch request 中都要配置) 才能使带 credentials 的 CORS 请求成功.
Access-Control-Request-Method
允许跨域的请求的方法.
- Access-Control-Allow-Methods: POST, GET, OPTIONS
- Access-Control-Allow-Headers
response 的 header 中 Access-Control-Allow-Headers 用于 preflight request (即会在实际请求发送之前先发送一个 option 请求)中, 列出了将会在正式请求的 Access-Control-Expose-Headers 字段中出现的首部信息.
简单首部, 如 simple headers,Accept,Accept-Language,Content-Language,Content-Type (只限于解析后的值为 application/x-www-form-urlencoded,multipart/form-data 或 text/plain 三种 MIME 类型(不包括参数)), 它们始终是被支持的, 不需要在这个首部特意列出.
preflight request--options 请求
很多人在抓包时会很郁闷怎么会无端端多出了一个 OPTIONS 请求, 请不要奇怪, 这只是 CORS 策略的预检请求, 就像你要去跟别人借个东西, 要先问问对方肯不肯一样.
什么情况下会发送 OPTIONS 请求?
简单的说, 就是有自定义 headers,Content-Type 的值不属于下列之一: application/x-www-form-urlencoded,multipart/form-data,text/plain 的请求会触发 OPTIONS 请求. 如果产生 OPTIONS 请求, 需要后台去响应它, 允许它跨域.
https://www.jianshu.com/p/b55086cbd9af 可以参考篇文章.
抓包和问题分析
PS: 我主要使用 Chrome 的 DevTools 工具
确保发送的数据没问题
不要相信你的代码, 以抓包工具的为准!!!!! 要相信如果抓包的数据有问题, 那么就是你的代码有问题.
不要相信你的代码, 以抓包工具的为准!!!!! 要相信如果抓包的数据有问题, 那么就是你的代码有问题.
不要相信你的代码, 以抓包工具的为准!!!!! 要相信如果抓包的数据有问题, 那么就是你的代码有问题.
URL 确保跟后台约定的一致
headers 要尤其关注 Content-Type(请关注上文的 Content-Type),GET 请求没有 Content-Type.
请求的参数是否正确
后台返回什么了?
如果你确认你发送的数据没问题, 那么该看看后台响应了什么, 如果响应的数据有问题, 那么是后台的责任.
如果是跨域的要查看有没有响应 CORS 的请求头.
HTTP STATUS
来源: https://segmentfault.com/a/1190000018857480