HTTP报文详细解析

以下是对 HTTP GET 请求报文 的详细解析,结合示例报文逐部分说明其结构和含义:

一、HTTP GET 请求的整体结构

GET 请求是 HTTP 协议中用于「获取资源」的方法,其报文由以下三部分组成(没有请求体,区别于 POST 请求):

  1. 请求行(Request Line)
  2. 请求头(Request Headers)
  3. 空白行(Empty Line)

二、示例报文解析(以用户提供的为例)

GET /servlet05/getServlet?username=lucy&userpwd=1111 HTTP/1.1                           请求行
Host: localhost:8080                                                                    请求头
Connection: keep-alive
sec-ch-ua: "Google Chrome";v="95", "Chromium";v="95", ";Not A Brand";v="99"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Windows"
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.54 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Referer: http://localhost:8080/servlet05/index.html
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
                                                                                            空白行
                                                                                            请求体(GET请求无请求体)

三、各部分详细说明

1. 请求行(Request Line)

格式:方法 + 资源路径 + HTTP协议版本

  • GET:请求方法,表示「获取资源」。
  • /servlet05/getServlet?username=lucy&userpwd=1111
    • 前半部分 /servlet05/getServlet资源路径(URI),表示请求的目标资源。
    • 后半部分 ?username=lucy&userpwd=1111查询参数(Query Parameters),格式为 key=value&key=value,用于向服务器传递数据(如用户输入的用户名和密码)。
  • HTTP/1.1:使用的 HTTP 协议版本(常见版本:1.0、1.1、2.0)。

2. 请求头(Request Headers)

请求头包含客户端环境、请求细节等信息,格式为 字段名: 值,常见字段如下:

  • Host: localhost:8080
    • 表示请求的目标服务器地址和端口(localhost 是本地主机,8080 是 Tomcat 默认端口)。
  • Connection: keep-alive
    • 表示希望与服务器保持长连接(HTTP/1.1 默认为长连接),减少多次请求的开销。
  • sec-ch-ua: ...(浏览器指纹字段):
    • 用于传递浏览器信息(品牌、版本、操作系统等),示例中表明用户使用 Chrome 95 浏览器,操作系统为 Windows。
  • User-Agent: ...
    • 完整的客户端标识字符串,包含浏览器、操作系统、引擎等信息(服务器可据此判断客户端类型,如区分 PC 或移动端)。
  • Accept: ...
    • 客户端支持的响应内容类型(如 text/html 表示接受 HTML 页面,application/json 表示接受 JSON 数据),q=0.9 表示优先级(数值越高越优先)。
  • Referer: http://localhost:8080/servlet05/index.html
    • 表示当前请求是从哪个页面发起的(即「来源页面」),服务器可借此统计来源或防止跨站请求伪造(CSRF)。
  • Accept-Encoding: gzip, deflate, br
    • 客户端支持的响应压缩算法(如 gzip 压缩可减少传输数据量)。
  • Accept-Language: zh-CN,zh;q=0.9
    • 客户端偏好的语言(服务器可据此返回对应语言的内容,如中文页面)。

3. 空白行(Empty Line)

  • 位于请求头和请求体之间,用于分隔两部分(GET 请求无请求体,此处空白行后直接结束)。

4. 请求体(Request Body,GET 请求中不存在)

  • GET 请求没有请求体,数据通过 URL 中的查询参数传递。
  • POST 请求 才有请求体,用于传递大量数据(如表单提交的二进制文件、JSON 数据等)。

四、GET 请求的特点总结

  1. 无请求体:数据通过 URL 的查询参数传递,长度受浏览器限制(通常不超过 2048 字符)。
  2. 幂等性:多次相同的 GET 请求不会对服务器资源产生副作用(仅读取数据,不修改)。
  3. 可见性:查询参数直接显示在 URL 中,可能被浏览器缓存或记录在日志中,不适合传递敏感数据(如密码,示例中虽传递了 userpwd,但实际开发中应避免)。
  4. 用途:常用于获取资源(如查询数据、访问页面)。

五、服务器如何处理 GET 请求的参数

在 Java Servlet 中,通过 HttpServletRequest 对象获取 GET 请求参数:

String username = request.getParameter("username"); // 得到 "lucy"
String userpwd = request.getParameter("userpwd");   // 得到 "1111"

通过以上解析,可以清晰理解 HTTP GET 请求的报文结构及各部分的作用,这对调试 Web 应用、分析网络请求非常重要。

六、服务器如何处理 GET 请求的参数

当服务器接收到客户端的 HTTP GET 请求后,会根据请求内容进行处理,并返回一个 HTTP 响应报文。HTTP 响应报文由状态行、响应头、空白行和响应体四部分组成。下面是一个可能针对上述 GET 请求的响应报文示例,并对其进行详细解析。

示例响应报文

HTTP/1.1 200 OK                      状态行
Date: Tue, 08 Apr 2025 12:00:00 GMT  响应头
Server: Apache/2.4.41 (Ubuntu)
Content-Type: text/html; charset=UTF-8
Content-Length: 1234
Connection: keep-alive

<!DOCTYPE html>
<html>
<head>
    <title>Response Page</title>
</head>
<body>
    <h1>Hello, Lucy!</h1>
    <p>Your request has been processed successfully.</p>
</body>
</html>
                          空白行
                          响应体

各部分详细解析

1. 状态行(Status Line)

格式为:HTTP 协议版本 + 状态码 + 状态消息

  • HTTP/1.1:表示使用的 HTTP 协议版本,与请求报文保持一致,这里使用的是 HTTP 1.1 版本。
  • 200:状态码,是一个三位数字,用于表示请求的结果。200 表示请求成功,服务器已经成功处理了客户端的请求。常见的状态码还有 404(未找到资源)、500(服务器内部错误)等。
  • OK:状态消息,是对状态码的文本描述,方便开发者和用户理解状态码的含义。

2. 响应头(Response Headers)

响应头包含了服务器的相关信息、响应内容的元数据等,格式为 字段名: 值

  • Date: Tue, 08 Apr 2025 12:00:00 GMT:表示响应生成的日期和时间,采用格林威治标准时间(GMT)格式。
  • Server: Apache/2.4.41 (Ubuntu):表明服务器的类型和版本,这里使用的是 Apache 服务器,版本为 2.4.41,运行在 Ubuntu 操作系统上。
  • Content-Type: text/html; charset=UTF-8:指定响应内容的类型和字符编码。text/html 表示响应内容是 HTML 格式,charset=UTF-8 表示使用 UTF - 8 字符编码,确保文本能正确显示各种语言字符。
  • Content-Length: 1234:表示响应体的长度,单位是字节。客户端可以根据这个长度来确定接收数据的结束位置。
  • Connection: keep-alive:与请求头中的 Connection 字段对应,表示服务器希望与客户端保持长连接,以便后续的请求可以复用该连接。

3. 空白行(Empty Line)

用于分隔响应头和响应体,表明响应头部分结束,接下来是响应体的内容。

4. 响应体(Response Body)

响应体包含了服务器返回给客户端的实际数据,根据 Content-Type 字段的不同,响应体可以是 HTML 页面、JSON 数据、图片等。在这个示例中,响应体是一个 HTML 页面,包含一个标题和一段文本信息。

服务器生成响应的示例代码(Java Servlet)

import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

@WebServlet("/servlet05/getServlet")
public class MyGetResponseServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // 设置响应的状态码
        response.setStatus(HttpServletResponse.SC_OK);

        // 设置响应头
        response.setContentType("text/html; charset=UTF-8");

        // 获取响应输出流
        PrintWriter out = response.getWriter();

        // 生成响应体
        out.println("<!DOCTYPE html>");
        out.println("<html>");
        out.println("<head>");
        out.println("<title>Response Page</title>");
        out.println("</head>");
        out.println("<body>");
        String username = request.getParameter("username");
        out.println("<h1>Hello, " + username + "!</h1>");
        out.println("<p>Your request has been processed successfully.</p>");
        out.println("</body>");
        out.println("</html>");
    }
}    

代码解释

  • response.setStatus(HttpServletResponse.SC_OK):设置响应的状态码为 200,表示请求成功。
  • response.setContentType("text/html; charset=UTF-8"):设置响应内容的类型为 HTML 格式,并使用 UTF - 8 字符编码。
  • PrintWriter out = response.getWriter():获取响应输出流,用于向客户端发送响应体内容。
  • 通过 out.println() 方法生成 HTML 格式的响应体内容,并根据请求参数中的 username 动态显示欢迎信息。

通过以上内容,你可以了解 HTTP 响应报文的结构和各部分的作用,以及如何在 Java Servlet 中生成响应。

Javaweb 文章被收录于专栏

JavaWeb 是指使用 Java 技术来开发基于 Web 的应用程序,它结合了 Java 语言的强大功能和 Web 技术的灵活性,广泛应用于各种企业级 Web 应用开发中。

全部评论

相关推荐

分享暑期实习面经,包括非常规八股以及手撕腾讯(已offer)3.27&nbsp;腾讯云一面&nbsp;第二天挂&nbsp;无手撕1.ET,LT使用场景2.natstat3.select适用于长连接还是短连接4.从零开始学go,你打算如何学4.9&nbsp;微信支付一面&nbsp;1.半小时手撕两道,带优先级的括号匹配,双端反转链表2.string在堆上还是栈上3.static初始化时机4.memset给一个对象赋值0会发生什么5.new的对象可以free吗6.fork一个多线程的进程后的线程个数7.共享内存为什么快8.1~n号线程,以及一个长度为n的数组,每个线程只对其对应索引上的值+1,有没有线程安全问题9.timewait状态10.RPC调用如何优化4.11&nbsp;微信支付二面1.半小时手撕三道,最长递增子序列的起始坐标,LRU,不用加法运算符实现加法2.手撕象棋实现,包括业务实现,网络架构实现3.手撕定时器4.负载均衡都有什么方法5.如何实现一个高性能日志系统4.17&nbsp;面委会1.半小时手撕三道,二分查找变体,LRU,树的层序遍历2.项目的缓冲区如何优化3.十亿个文件去重4.21&nbsp;HR面,&nbsp;4.23&nbsp;oc+offer京东,移动端开发给捞上来了,招聘流程极其混乱4.11&nbsp;移动端一面1.http如何请求文件大小2.实现一个顺序容器,同时满足常数复杂度的查找3.线程池实现,如何体现任务优先级4.DNS如何请求不同IP(没搞懂问题在问啥)5.git用法6.手撕一个sort函数,要根据数据的不同类型给出最合适的算法4.15&nbsp;移动端二面,居然是HR面4.17&nbsp;三面&nbsp;我改了下时间,然后直接给我挂了。。后端一面秒约,但是还是客户端的在面,不知道什么意思4.21&nbsp;不知道哪个部门几面,像是hr面,问了具体意向,工作地点,规划等,说后面会加微信,直接主管面到今天也没消息阿里云4.11&nbsp;CDN部门一面,面完秒挂,迟到+唠家常+不开摄像头+回答无反馈,基本KPI1.模板讨论2.模板和多态实现的区别3.main函数运行之前会发生什么4.电源启动加载操作系统的过程5.对称加密和非对称加密算法实现6.多个证书如何选取正确的7.你写过的项目中都能在哪里体现出cpp的什么特性8.设计CDN要注意什么9.wifi切4g会发生什么10.手撕实现一个高性能服务器4.23&nbsp;maxcompute一面,二面拒了1.可重定向文件2.ELF文件3.进程执行程序的过程4.SIMD5.一个系统都会遇到什么瓶颈,如何确定,如何解决6.一堆我没听过的英文名。。7.gdb如何调试coredump8.glibc9.手撕三道,第一道给两个类和一个main函数,指出他的错误以及不规范的写法,并改正。第二道写一个多线程模型,A生产者,B消费者,B要把数据分成5份并行处理再组装。第三道字符串解码快手4.18一面主要是在讨论项目,面试体验最好的一次,面试官反馈很多,面完秒过1.cpp为什么要有新特性2.quic连接迁移3.接雨水并优化4.23二面&nbsp;一直在问高考哪的,高考成绩,还有学硕专硕,感觉希望不大1.介绍实习和项目2.40个人,3个选项,每个人只能选一个,问有多少个结果。面试前刚收到腾讯offer,写的时候都不想写了,想迭代处理。然后面试官说如果是m人n选项怎么求。最后在提示下解决。美团4.14一面挂&nbsp;面试官第一句话说你知道业务部门都是用java吗。。1.cas饥饿问题2.buffer吞吐量3.任务队列溢出如何处理,如何提前感知?4.定时器如何实现5.手撕一道树的dfs遍历,美团的手撕和leetcode一摸一样,要考虑特殊情况海康4.17&nbsp;一面&nbsp;全程介绍实习,项目。面试官无反馈,最后手撕实现一个类简历挂/泡池子:腾讯音乐,oppo,小米
点赞 评论 收藏
分享
05-12 22:45
已编辑
2222 安卓
55min问了40多个问题,底裤都被扒完了...问题:1,为什么使用flutter2,flutter的优点是什么3,mvvm架构的特点4,flutter和原生混合开发时,页面路由如何管理5,hashmap数据结构如何实现6,红黑树特点,插入和查找的时间复杂度7,hashmap为什么在链表长度为8时转化为红黑树8,内存泄漏的根本原因是什么?9,内存泄漏检测工具的原理了解吗?内存泄漏是如何被检测出来的?10,引用类型有哪些?11,Java中加锁有几种方式?12,审查代码时,如何发现潜在的死锁问题?13,死锁如何产生14,如何避免死锁15,tcp,udp是哪一层的协议,他们的区别是什么?16,tcp如何保证可靠性17,请求头中有哪些信息18,cookie的概念19,序列化和反序列化20,json和protobuf的区别21,数据加密有了解过吗?22,https相比较与http增加了哪些内容?23,https中的证书的概念24,效率比较高的排序算法,哪种算法时间最稳定?25,在实际项目中更轻倾向于自己实现排序算法,还是使用系统提供的方法26,java或c++中排序算法的源码有了解过吗,动态调节排序算法的策略?27,字符串查找算法,kmp时间复杂度,kmp思想是什么?28,计算机两数相乘溢出,如何解决?29,两个链表相交,如何求焦点30,安卓跨进程通信31,传统的操作系统,除了共享内存外,还有哪些跨进程通信的方法,使用场景相比于共享内存有哪些不同?32,view的绘制流程33,安卓绘制中的硬件加速的概念34,flutter是如何实现跨平台的35,flutter如何进行渲染,落实到平台上36,安卓消息机制37,flutter跟原生之间的消息通信38,服务器主动推送消息到客户端有了解吗?39,安卓本地存储,sqlite和sp的特点40,sp可以跨进程吗?如何操作?41,sp存储信息的两种方式,有什么区别?42,高德sdk,手机在室内时无法做卫星定位,如何发挥作用,误差是多少?43,网络请求框架现在普遍使用的是什么?dio是一种什么样的网络请求框架?
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务