美文网首页
网络协议(十四)-应用层(HTTP)

网络协议(十四)-应用层(HTTP)

作者: 小冰山口 | 来源:发表于2021-01-08 18:00 被阅读0次
    HTTP
    • HTTP(Hyper Text Transfer Protocol), 译为超文本传输协议
      -- 是互联网中应用最广泛的应用层协议之一
      -- 设计HTTP最初的目的是: 提供一种发布和接收HTML页面的方法, 由URI来标识具体的资源
      -- 后面用HTTP来传递的数据格式不仅仅是HTML, 应用非常广泛

    • HTML(Hyper Text Markup Language): 超文本标记语言
      -- 用以编写网页

    版本
    • 1991年, HTTP/0.9
      -- 只支持GET请求方法获取文本数据(比如HTML文档), 且不支持请求头, 响应头等, 无法向服务器传递太多信息

    • 1996年, HTTP/1.0
      -- 支持POST, HEAD等请求方法, 支持请求头, 响应头等, 支持更多种数据类型 (不再局限于文本数据)
      -- 浏览器的每次请求都需要与服务器建立一个TCP连接, 请求处理完成后立即断开TCP连接

    • 1997年, HTTP/1.1(最经典, 使用最广泛的版本)
      -- 支持PUT, DELETE等请求办法
      -- 采用持久连接(Connection: keep-alive), 多个请求可以共用一个TCP连接

    • 2015年, HTTP/2.0

    • 2018年, HTTP/3.0

    报文格式
    image.png image.png
    • ABNF (Augmented BNF)
      -- 是BNF (Backus-Naur Form, 译为: 巴科斯-瑙尔范式)的修改, 增强版
      -- 在RFC 52234中表明: ABNF用作internet中通信协议的定义语言
      -- ABNF是最严谨的HTTP报文格式描述形式, 脱离ABNF谈论HTTP报文格式, 往往都是片面, 不严谨的

    • 关于HTTP报文格式的定义
      -- RFC 2616 4.HTTP Message(旧)
      -- RFC 7230 3.Message Format(新)

    image.png
    ABNF-核心规则
    image.png
    报文格式-request-line, status-line

    request-line = method SP request-target SP HTTP-version CRLF
    HTTP-version = HTTP-name "/" DIGIT"."DIGIT"
    HTTP-name = %48.54.54.50;HTTP

    GET /hello/ HTTP/1.1

    status-line = HTTP-version SP status-code SP reason-phrase CRLF
    status-code = 3DIGIT
    reason-phrase = *(HTAB / SP / VCHAR / obs-text)

    HTTP/1.1 200
    HTTP/1.1 200 OK

    报文格式 - header-filed, message-body

    header-filed = filed-name ":" OWS field-value OWS
    field-name = token
    field-value = *(field-content / obs-fold)
    OWS = *(SP / HTAB)

    message-body = *OCTET

    URL的编码
    • URL中一旦出现了一些特殊字符(比如中文, 空格), 需要进行编码
      -- 在浏览器地址栏输入URL时, 是采用UTF-8进行编码

    • 比如
      -- 编码前: https://www.baidu.com/s?wd=百度
      -- 编码前: https://www.baidu.com/s?wd=%E5%8D%8E%E4%B8%BA

    请求方法
    • GET 常用于读取的操作, 请求参数直接拼接在URL的后面(浏览器对URL是有长度限制的)

    • POST 常用于添加, 修改, 删除的操作, 请求参数可以放到请求体中(没有大小限制)**(URL也可以拼接参数, 请求体里也拼接参数)**

    • HEAD 请求得到的与GET请求相同的响应, 但没有响应体
      -- 使用场景举例: 在下载一个大文件前, 先获取其大小, 再决定是否要下载. 以此可以节约带宽资源

    • OPTIONS 用于获取目的资源所支持的通信选项, 比如服务器支持的请求方法
      -- OPTIONS * HTTP/1.1

    • PUT 用于对已存在的资源进行整体覆盖

    • PATCH 用于对资源进行部分修改(资源不存在, 会创建新的资源)

    • DELETE 用于删除指定的资源

    • TRACE 请求服务器回显其收到的请求信息, 主要用于HTTP请求的测试和诊断

    • CONNECT 可以开启一个客户端与所请求资源之间的双向沟通的通道, 它可以用来创建隧道(tunnel)
      -- 可以用来访问采用了SSL(HTTPS)协议的站点

    头部字段(Header Field)
    • 头部字段可以分为4种类型
      -- 请求头字段(Request Header Fields)
      ✅有关要获取的资源或客户端本身信息的消息头

    -- 响应头字段(ResponseHeader Fields)
    ✅有关响应的补充信息, 比如服务器本身(名称和版本等)的消息头

    -- 实体头字段(Entity Header Fields)
    ✅有关实体主体的更多信息, 比如主体长度(Content-Length)MIME类型

    -- 请求头字段(General Header Fields)
    ✅同时适用于请求和响应消息, 但与消息主体无关的消息头

    请求头字段
    image.png image.png image.png
    响应头字段
    image.png image.png image.png
    状态码(Status Code)
    • RFC 2616 10.Status Code Definitions规范中定义
      -- 状态码指示HTTP请求是否已成功完成

    • 状态码可以分为5
      -- 信息响应: 100~199
      -- 成功响应: 200~299
      -- 重定向: 300~399
      -- 客户端错误: 400~499
      -- 服务器错误: 500~599

    • 100 Continue
      -- 请求的初始部分已经被服务器收到, 并且并没有被服务器拒绝. 客户端应该继续发送剩余的请求, 如果请求已经完成, 就忽略这个响应
      -- 允许客户端发送带请求体的请求前, 判断服务器是否愿意接手请求(服务器通过请求头判断)
      -- 在某些情况下, 如果服务器在不看请求体就拒绝请求时, 客户端就发送请求体是不恰当或者低效的

    • 200 OK 请求成功

    • 302 Found 请求的资源被暂时移动到了由Location头部指定的URL

    • 304 Not Modified 说明无需再次传输请求内容, 也就是说可以使用缓存内容

    • 400 Bad Request 由于语法无效, 服务器无法理解该需求

    • 401 Unauthorized 由于缺乏目标资源要求的身份验证凭证

    • 403 Forbidden 服务器端有能力处理该请求, 但是拒绝授权访问

    • 404 Not Found 服务器端无法找到所请求的资源

    • 405 Method Not Allowed 服务器禁止了使用当前HTTP方法的请求

    • 406 Not Acceptable 服务器端无法提供与Accept-Charset以及Accept-Language指定的值相匹配的响应

    • 408 Request Timeout 服务器想要将没有在使用的连接关闭
      -- 一些服务器会在空闲连接上发送此信息, 即便是在客户端没有发送任何请求的情况下

    • 500 Internal Server Error 所请求的服务器遇到意外的情况并阻止其执行请求

    • 501 Not Implemented 请求的方法不被服务器支持, 因此无法被处理(注意和405的区别)
      -- 服务器必须支持的方法(即不会返回这个状态码的方法)只有GETHEAD

    • 502 Bad Gateway 作为网关或代理角色的服务器, 从上游服务器(如tomcat)中接收到的响应是无效的

    • 503 Service Unavailable 服务器尚未处于可以接受请求的状态
      -- 通常造成这种情况的原因是由于服务器停机维护或者已超载

    form提交-常用属性
    • action 请求的URI
    • method 请求方法(GET, POST)
    • enctype POST请求时, 请求体的编码方式
      -- application/x-www-form-urlencoded(默认值)
      ✅用&分隔参数, 用=分隔键和值, 字符用URL编码方式进行编码

    -- multipart/form-data
    ✅文件上传时必须使用这种编码方式

    form提交-multipart/form-data
    • 参考RFC 1521
    • 请求头
      -- Content-Type: multipart/form-data; boundary=xxx
      image.png
    同源策略
    • 浏览器有个同源策略(Same-Origin Policy)
      -- 它规定了: 默认情况下, AJAX请求只能发送给同源的URL
      -- 同源是指3个相同: 协议, 域名(IP), 端口

      image.png
    • img, script, link, iframe, video, audio等标签不受同源策略的约束

    跨域资源共享
    • 解决AJAX跨域请求的常用方法
      -- CORS(Cross-Origin Resource Sharing) 跨域资源共享

    • CORS的实现需要客户端和服务器同时支持
      -- 客户端
      ✅所有的浏览器都支持(IE至少是IE10 版本)

    -- 服务器
    ✅需要返回相应的响应头(比如Access-Control-Allow-Origin)
    ✅告知浏览器这是一个允许跨域访问的请求

    后端在返回数据前就应该先判断origin和允许访问的是否一致, 否则就算浏览器报错跨域问题, 前端一样可以拿到数据, 后端的数据就存在不安全性

    会话跟踪
    • HTTP是一种"无状态"(stateless)的协议
      -- 每次客户端访问网页时, 客户端都会打开与Web服务器的单独连接
      -- 并且服务器不会自动保留之前客户端请求的任何记录
      -- 所以服务器无法识别多个请求是否来自同一个客户端(比如浏览器)

    • 在很多应用场景中, 都有以下需求
      -- 服务器能够识别出多个请求是够来自同一个客户端
      -- 在来自同一个客户端的多个请求之间共享数据

    • 以上需求可以使用会话跟踪技术来完成. 在Java中, 实现会话跟踪的常用方法是
      -- Cookie
      -- Session

    Cookie & Session
    • Cookie是直接存储在浏览器本地的一小串数据
      -- 使用document.cookie访问Cookie
      -- 在修改Cookie时, 只会修改其中提到的Cookie
      -- name=value必须被编码(encodeURIComponent)
      -- 一个Cookie最大为4kb, 每个网站最多有20+个左右的Cookie(具体取决于浏览器)

    • WindowsChrome浏览器的Cookie存放位置
      -- C:\Users\用户名\AppData\Local\Google\Chrome\User Data\Default\Cookies
      -- 使用SQLite数据库进行存储

    Cookie的有效期
    • 如果没有设置Cookie的过期时间, 则当浏览器关闭时, Cookie就失效了

    • expries
      -- 必须完全采用GMT时区的格式, 可以受用date.toUTCString来获取
      -- 例如: expires=Tue, 19 Jan 2038 03:14:07 GMT

    • max-age
      -- 过期时间距离当前时间的秒数
      -- 例如: max-age=60

    • Cookie(只归一个浏览器管)
      -- 在客户端(浏览器)存储一些数据, 存储到本地磁盘(硬盘)
      -- 服务器可以返回Cookie交给客户端去存储

    • Session(针对用户浏览器的, 会话跟踪)
      -- 在服务器存储一些数据, 存储到内存中

    Cookie的作用域
    • domainpath标识定义了Cookie的作用域, 即Cookie应该发送给哪些URL

    • domain
      -- 标识指定了哪些主机可以接受Cookie
      -- 如果不指定, 默认为当前文档的主机(不包含子域名); 如果指定了domain, 则一般包含子域名
      -- 例如: 如果设置domain=520it.com, 则Cookie也包含在子域名中(如bbs.520it.com)

    • path
      -- 标识指定了主机下的哪些路径可以接受Cookie, 子路径也会被匹配
      -- 例如:设置path=/docs, 则以下地址都会匹配
      ✔️/docs
      ✔️/docs/one/
      ✔️/docs/one/img

    服务器设置Cookie
    • Cookie通常是由Web服务器使用响应头Set-Cookie设置的

    • 关于max-age

    • -在JavaScript中, 如果设置为0或者负数, 会立即删除Cookie
      -- 在Java中: 如果设置为0, 是立即删除Cookie; 如果设置为负数, 按默认情况处理

    getSession内部的原理
    • 检查客户端是否有发送一个叫做JSESSIONIDCookie
      -- 如果没有
      ✔️创建一个新的Session对象, 并且这个Session对象会有一个id
      ✔️这个Session对象会保留在服务器的内存中
      ✔️在响应的时候, 会添加一个Cookie(JSESSIONID=Session对象的id)给客户端

    -- 如果有
    ✔️返回idJSESSIONIDSession对象

    JSESSIONID
    • 默认情况下, 当用户关闭浏览器时, Cookie中存储的JSESSIONID就会被销毁

    • 可以通过以下代码延长JSESSIONID在客户端的寿命

    Cookie cookie = new Cookie("JSESSIONID", request.getSession().getId());
    cookie.setMaxAge(3600);
    response.addCookie(cookie);
    
    Session的有效期
    • Session的有效期默认是30分钟
    • 可以在web.xml中配置失效时间(单位是分钟)
    <session-config>
        <session-timeout>30</session-timeout>
     </session-config>
    
    总结
    • Cookie
      -- 数据存储在浏览器客户端
      -- 数据有大小和数量的限制
      -- 适合存储一些小型, 不敏感的数据
      -- 默认情况下, 关闭浏览器后就会销毁

    • Session
      -- 数据存储在服务器端
      -- 数据没有大小和数量的限制
      -- 可以存储大型, 敏感的数据(比如用户信息)
      -- 默认情况下, 未使用30分钟后就会销毁

    相关文章

      网友评论

          本文标题:网络协议(十四)-应用层(HTTP)

          本文链接:https://www.haomeiwen.com/subject/pxbmoktx.html