目录
[一、 HttpResponse.h](#一、 HttpResponse.h)
[1. 整体定位](#1. 整体定位)
[2. 核心结构](#2. 核心结构)
[1. 状态码 + 状态描述](#1. 状态码 + 状态描述)
[2. 响应头 headers_](#2. 响应头 headers_)
[3. 是否关闭连接 closeConnection_](#3. 是否关闭连接 closeConnection_)
[4. 响应体 body_](#4. 响应体 body_)
[3. 核心函数:appendToBuffer ()](#3. 核心函数:appendToBuffer ())
[4. 典型使用流程](#4. 典型使用流程)
[5. 和 HttpRequest 的关系](#5. 和 HttpRequest 的关系)
[二、 HttpResponse.cc](#二、 HttpResponse.cc)
[1. 核心功能一句话](#1. 核心功能一句话)
[2. 逐段拆解](#2. 逐段拆解)
[1. 拼接【状态行】](#1. 拼接【状态行】)
[2. 拼接【Connection + Content-Length】](#2. 拼接【Connection + Content-Length】)
[3. 拼接【所有响应头】](#3. 拼接【所有响应头】)
[4. 头部结束,加空行](#4. 头部结束,加空行)
[5. 最后加【响应体】](#5. 最后加【响应体】)
[3. 最终组装出来的 HTTP 报文长这样](#3. 最终组装出来的 HTTP 报文长这样)
[4. 这个类在 HTTP 服务中的位置](#4. 这个类在 HTTP 服务中的位置)
一、 HttpResponse.h
先贴出完整代码,再逐部分解释:
cpp
// Copyright 2010, Shuo Chen. 保留所有权利。
// http://code.google.com/p/muduo/
//
// 本源代码的使用受 BSD 许可证约束
// 可在 License 文件中找到许可证条款。
// 作者:陈硕 (chenshuo at chenshuo dot com)
//
// 这是一个公共头文件,仅允许包含其他公共头文件。
#ifndef MUDUO_NET_HTTP_HTTPRESPONSE_H
#define MUDUO_NET_HTTP_HTTPRESPONSE_H
#include "muduo/base/copyable.h"
#include "muduo/base/Types.h"
#include <map>
namespace muduo
{
namespace net
{
class Buffer;
///
/// HTTP 响应对象
/// 用于构造 HTTP 响应报文(状态行、响应头、响应体),并最终序列化到 Buffer 发送
///
class HttpResponse : public muduo::copyable
{
public:
/// HTTP 状态码枚举
enum HttpStatusCode
{
kUnknown, // 未知状态码
k200Ok = 200, // 成功
k301MovedPermanently = 301, // 永久重定向
k400BadRequest = 400, // 错误请求
k404NotFound = 404, // 资源未找到
};
/// 构造函数
/// @param close 是否在响应发送完毕后关闭连接(Connection: close)
explicit HttpResponse(bool close)
: statusCode_(kUnknown),
closeConnection_(close)
{
}
/// 设置 HTTP 状态码
void setStatusCode(HttpStatusCode code)
{ statusCode_ = code; }
/// 设置 HTTP 状态消息(如 "OK" / "Not Found")
void setStatusMessage(const string& message)
{ statusMessage_ = message; }
/// 设置是否关闭连接
void setCloseConnection(bool on)
{ closeConnection_ = on; }
/// 判断是否关闭连接
bool closeConnection() const
{ return closeConnection_; }
/// 设置响应体类型(Content-Type)
void setContentType(const string& contentType)
{ addHeader("Content-Type", contentType); }
/// 添加一个 HTTP 响应头
/// FIXME: 后续可用 StringPiece 替代 string 提升效率
void addHeader(const string& key, const string& value)
{ headers_[key] = value; }
/// 设置响应体内容
void setBody(const string& body)
{ body_ = body; }
/// 将完整的 HTTP 响应报文追加到输出缓冲区(用于发送)
void appendToBuffer(Buffer* output) const;
private:
std::map<string, string> headers_; // 响应头集合
HttpStatusCode statusCode_; // 状态码
string statusMessage_; // 状态消息
bool closeConnection_; // 是否关闭连接
string body_; // 响应体
};
} // namespace net
} // namespace muduo
#endif // MUDUO_NET_HTTP_HTTPRESPONSE_H
1. 整体定位
HttpResponse = 构造 HTTP 响应报文的工具
- 用户设置:状态码、响应头、响应体
- 它负责:拼接成标准 HTTP 响应格式
- 写入 Buffer → 发送给浏览器
2. 核心结构
cpp
class HttpResponse : public copyable
{
public:
// 状态码
enum HttpStatusCode {
kUnknown,
k200Ok = 200,
k301MovedPermanently = 301,
k400BadRequest = 400,
k404NotFound = 404
};
// 设置
void setStatusCode(HttpStatusCode code);
void setStatusMessage(const string& message);
void setCloseConnection(bool on);
void setContentType(const string& contentType);
void addHeader(const string& key, const string& value);
void setBody(const string& body);
// 序列化成Buffer(发送给客户端)
void appendToBuffer(Buffer* output) const;
private:
std::map<string, string> headers_;
HttpStatusCode statusCode_;
string statusMessage_;
bool closeConnection_;
string body_;
};
1. 状态码 + 状态描述
cpp
HttpStatusCode statusCode_;
string statusMessage_;
对应 HTTP 首行:
cpp
HTTP/1.1 200 OK
2. 响应头 headers_
cpp
map<string, string> headers_;
对应:
cpp
Content-Type: text/html
Connection: keep-alive
3. 是否关闭连接 closeConnection_
true:回复后立刻断开(Connection: close)false:长连接(Connection: Keep-Alive)
4. 响应体 body_
网页内容、JSON、HTML 等。
3. 核心函数:appendToBuffer ()
把 HttpResponse 序列化成真实 HTTP 响应报文,写入 Buffer 发送。
拼接格式:
cpp
HTTP/1.1 200 OK\r\n
Content-Type: text/html\r\n
Connection: Keep-Alive\r\n
\r\n
<html>...网页内容...</html>
这就是浏览器能识别的原始 HTTP 响应。
4. 典型使用流程
cpp
// 用户收到 HttpRequest 后,构造 HttpResponse
HttpResponse response(false); // 长连接
response.setStatusCode(HttpResponse::k200Ok);
response.setStatusMessage("OK");
response.setContentType("text/html");
response.setBody("<h1>Hello World</h1>");
// 序列化 → 发送
response.appendToBuffer(outputBuf);
conn->send(outputBuf);
5. 和 HttpRequest 的关系
cpp
浏览器发送 → HttpRequest(解析后)
用户处理 → 生成 HttpResponse
回复浏览器 ← HttpResponse(序列化后)
二、 HttpResponse.cc
先贴出完整代码,再逐部分解释:
cpp
// Copyright 2010, Shuo Chen. 保留所有权利。
// http://code.google.com/p/muduo/
//
// 本源代码的使用受 BSD 许可证约束
// 可在 License 文件中找到许可证条款。
// 作者:陈硕 (chenshuo at chenshuo dot com)
#include "muduo/net/http/HttpResponse.h"
#include "muduo/net/Buffer.h"
#include <stdio.h>
using namespace muduo;
using namespace muduo::net;
/// 将 HTTP 响应组装成标准协议格式,写入输出缓冲区
void HttpResponse::appendToBuffer(Buffer* output) const
{
char buf[32];
/// 1. 组装状态行:HTTP/1.1 200 OK\r\n
snprintf(buf, sizeof buf, "HTTP/1.1 %d ", statusCode_);
output->append(buf);
output->append(statusMessage_);
output->append("\r\n");
/// 2. 处理连接头与长度头
if (closeConnection_)
{
// 短连接:发送完直接关闭
output->append("Connection: close\r\n");
}
else
{
// 长连接:必须带上 Content-Length
snprintf(buf, sizeof buf, "Content-Length: %zd\r\n", body_.size());
output->append(buf);
output->append("Connection: Keep-Alive\r\n");
}
/// 3. 追加所有响应头
for (const auto& header : headers_)
{
output->append(header.first);
output->append(": ");
output->append(header.second);
output->append("\r\n");
}
/// 4. 空行分隔头部与body
output->append("\r\n");
/// 5. 追加响应体
output->append(body_);
}
1. 核心功能一句话
cpp
void HttpResponse::appendToBuffer(Buffer* output) const
把响应状态行 + 响应头 + 空行 + 响应体 → 拼接到 Buffer 里发给客户端。
2. 逐段拆解
1. 拼接【状态行】
cpp
snprintf(buf, sizeof buf, "HTTP/1.1 %d ", statusCode_);
output->append(buf);
output->append(statusMessage_);
output->append("\r\n");
生成:
cpp
HTTP/1.1 200 OK\r\n
- 固定使用 HTTP/1.1
statusCode_→ 200/404/301statusMessage_→ OK / Not Found
2. 拼接【Connection + Content-Length】
cpp
if (closeConnection_)
{
output->append("Connection: close\r\n");
}
else
{
snprintf(buf, sizeof buf, "Content-Length: %zd\r\n", body_.size());
output->append(buf);
output->append("Connection: Keep-Alive\r\n");
}
规则:
- 长连接(Keep-Alive)必须带 Content-Length浏览器才知道 body 何时结束
- 短连接(close)不需要 Content-Length断开连接即结束
3. 拼接【所有响应头】
cpp
for (const auto& header : headers_)
{
output->append(header.first);
output->append(": ");
output->append(header.second);
output->append("\r\n");
}
例如:
cpp
Content-Type: text/html\r\n
Server: muduo\r\n
4. 头部结束,加空行
cpp
output->append("\r\n");
HTTP 规定:头部与 body 之间必须空一行
5. 最后加【响应体】
cpp
output->append(body_);
如:<h1>Hello</h1> 或 {"key":"value"}
3. 最终组装出来的 HTTP 报文长这样
cpp
HTTP/1.1 200 OK\r\n
Content-Length: 5\r\n
Connection: Keep-Alive\r\n
Content-Type: text/html\r\n
\r\n
hello
4. 这个类在 HTTP 服务中的位置
cpp
HttpRequest :: 解析浏览器请求
↓
用户业务逻辑处理
↓
HttpResponse :: 构造响应
↓
appendToBuffer :: 序列化成原始HTTP报文
↓
TcpConnection::send 发送给浏览器