使用cpp-httplib发布静态文件服务

1. 引言

静态文件(Static Files) 是指那些内容在服务器上预先写好、不会随请求动态改变的文件,例如:

  • HTML 页面(如 index.html)
  • CSS 样式表(如 style.css)
  • JavaScript 脚本(如 app.js)
  • 图片(如 logo.png, photo.jpg)
  • 字体、图标、PDF、音视频等

静态文件服务(Static File Serving) 是指 HTTP 服务器能够接收客户端(如浏览器)对某个路径的请求,并自动从本地文件系统中找到对应文件,将其内容返回给客户端。例如:

  • 用户访问 http://example.com/style.css
  • 服务器自动去磁盘找 ./www/style.css
  • 读取文件内容,设置正确的 Content-Type: text/css
  • 把文件原样返回给浏览器

这个过程无需写任何业务逻辑代码,由 HTTP 服务器框架自动完成。

一个通用的 HTTP 服务器框架通常会提供静态文件服务功能,因为:

  • 实现简单:读文件 + 设置 MIME 类型即可;
  • 用途广泛:极大简化小型项目部署;
  • 开发体验好:不用额外起 Nginx 就能跑完整 Web 应用;
  • 符合 HTTP 本质:HTTP 最初就是为传输静态文档设计的(超文本传输协议)。

2. 实例

使用 cpp-httplib 发布静态文件服务非常简单:

/* by 01130.hk - online tools website : 01130.hk/zh/regexdso.html */
#include <httplib.h>

#include <iostream>
#include <string>

using namespace std;

int main() {
  httplib::Server svr;

  svr.set_mount_point("/public", "D:/Work/HttpServer/public");

  std::cout << "Server listening on http://0.0.0.0:8080/public\n";
  svr.listen("0.0.0.0", 8080);

  return 0;
}

D:/Work/HttpServer/public 这个目录中笔者放置了一些文件:

那么可以在浏览器通过 URL 地址 http://127.0.0.1:8080/public/最小二乘问题详解1:线性最小二乘/meta.json 访问到具体的文件内容:

那么是不是所有的文件都支持访问并且加载显示呢?这取决于 HTTP 服务器(cpp-httplib)对文件扩展名与 MIME 类型的映射能力:

扩展名MIME 类型扩展名MIME 类型
csstext/cssmpgaaudio/mpeg
csvtext/csvwebaaudio/webm
txttext/plainwavaudio/wave
vtttext/vttotffont/otf
html, htmtext/htmlttffont/ttf
apngimage/apngwofffont/woff
avifimage/avifwoff2font/woff2
bmpimage/bmp7zapplication/x-7z-compressed
gifimage/gifatomapplication/atom+xml
pngimage/pngpdfapplication/pdf
svgimage/svg+xmlmjs, jstext/javascript
webpimage/webpjsonapplication/json
icoimage/x-iconrssapplication/rss+xml
tifimage/tifftarapplication/x-tar
tiffimage/tiffxhtml, xhtapplication/xhtml+xml
jpeg, jpgimage/jpegxsltapplication/xslt+xml
mp4video/mp4xmlapplication/xml
mpegvideo/mpeggzapplication/gzip
webmvideo/webmzipapplication/zip
mp3audio/mp3wasmapplication/wasm

3. 扩展

set_mount_point 是 cpp-httplib 用于发布静态文件服务的接口,将设置的目录挂载到 HTTP Get 请求。如果将代码写的更加本质一点,就是读取相应的数据,将数据填充到 Get 请求返回:

/* by 01130.hk - online tools website : 01130.hk/zh/regexdso.html */
#include <httplib.h>

#include <filesystem>  // C++17
#include <fstream>
#include <iostream>
#include <nlohmann/json.hpp>
#include <string>

using namespace std;
namespace fs = std::filesystem;

// 辅助函数:根据文件扩展名返回 MIME 类型
std::string get_mime_type(const std::string& filename) {
  if (filename.ends_with(".md")) {
    return "text/markdown; charset=utf-8";
  } else if (filename.ends_with(".json")) {
    return "application/json; charset=utf-8";
  } else if (filename.ends_with(".txt")) {
    return "text/plain; charset=utf-8";
  }
  // 默认 fallback
  return "application/octet-stream";
}

int main() {
  httplib::Server svr;

  std::u8string docRoot =
      u8"D:/Work/HttpServer/public/最小二乘问题详解1:线性最小二乘";

  // 路由:GET /files/<filename>
  svr.Get(R"(/files/([^/]+))", [&](const httplib::Request& req,
                                   httplib::Response& res) {
    // 提取文件名(来自正则捕获组)
    std::string filename = req.matches[1];
    std::u8string u8Filename(filename.begin(), filename.end());

    // 安全检查:防止路径穿越(如 ../../etc/passwd)
    if (filename.find("..") != std::string::npos || filename.empty()) {
      res.status = 400;
      res.set_content(R"({"error": "Invalid filename"})", "application/json");
      return;
    }

    // 构建完整路径
    fs::path filepath = fs::path(docRoot) / u8Filename;

    // 检查文件是否存在且是普通文件
    if (!fs::exists(filepath) || !fs::is_regular_file(filepath)) {
      res.status = 404;
      res.set_content(R"({"error": "File not found"})", "application/json");
      return;
    }

    // 读取文件内容
    std::ifstream file(filepath, std::ios::binary);
    if (!file) {
      res.status = 500;
      res.set_content(R"({"error": "Failed to read file"})",
                      "application/json");
      return;
    }

    std::string content((std::istreambuf_iterator<char>(file)),
                        std::istreambuf_iterator<char>());

    // 设置 Content-Type
    std::string mime = get_mime_type(filename);
    res.set_content(content, mime);
  });

  std::cout << "Server listening on http://0.0.0.0:8080/files/<filename>\n";
  svr.listen("0.0.0.0", 8080);

  return 0;
}

如果我们在浏览器地址访问http://127.0.0.1:8080/files/最小二乘问题详解1:线性最小二乘.md,就可以看到最小二乘问题详解1:线性最小二乘.md这个文件的内容:

这是因为这里将 .md 文件的 MIME 设置成了 text/markdown,浏览器会按照文本格式显示 .md 文件的内容。而在 set_mount_point 接口中,由于不识别 .md 格式类型,MIME 类型会回退回 application/octet-stream ,也就是二进制文件/未知类型,浏览器会强制下载。

内容概要:本文系统介绍了标准化和软件知识产权的基础知识,涵盖标准化的基本概念、分类、标准代号、国际标准的采用原则及程度,重点讲解了信息技术标准化、ISO与IEC等国际标准化组织以及ISO9000和ISO/IEC15504等重要标准体系;在知识产权部分,详细阐述了知识产权的定义、分类及特点,重点分析了计算机软件著作权的主体、客体、权利内容、行使方式、保护期限及侵权认定,同时涉及商业秘密的构成与侵权形式、专利权的类型与申请条件,以及企业如何综合运用著作权、专利、商标和商业秘密等方式保护软件知识产权。; 适合人群:从事软件开发、项目管理、IT标准化或知识产权相关工作的技术人员与管理人员,以及备考相关资格考试的学习者;具备一定信息技术背景,希望系统掌握标准化与软件知识产权基础知识的专业人员。; 使用场景及目标:①帮助理解各类标准的分类体系及国际标准采用方式,提升标准化实践能力;②指导企业在软件研发过程中有效保护知识产权,规避法律风险;③为软件著作权登记、专利申请、技术保密等提供理论依据和操作指引。; 阅读建议:建议结合国家相关政策法规和实际案例进行深入学习,重点关注软件著作权与专利权的适用边界、标准制定流程及企业知识产权管理策略,强化理论与实践的结合。
<think> 我们被要求提供关于cpp-httplib库的使用指南、功能介绍和示例代码。根据引用内容,我们可以总结如下: 1. 引用[1]和[2]指出cpp-httplib是一个轻量级、易用的C++ HTTP库,只需一个头文件即可使用,适合快速开发和原型验证。 2. 引用[3]提到了该库支持HTTP持久连接(Keep-Alive),通过复用TCP连接减少开销。 3. 引用[4]给出了使用该库实现HTTPS服务的示例,需要定义宏并链接OpenSSL。 4. 引用[5]则提到了在旧版GCC中可能遇到的编译问题及解决方案。 因此,我们将围绕这些方面展开回答。 ### cpp-httplib使用指南 #### 1. **安装与配置** cpp-httplib 是一个单头文件库,只需下载 `httplib.h` 并包含到项目中即可使用[^2]: ```cpp #include <httplib.h> ``` **环境要求**: - C++11 或更高版本 - 若需 HTTPS 支持,需链接 OpenSSL 库(并在包含头文件前定义宏 `CPPHTTPLIB_OPENSSL_SUPPORT`) **编译选项**(针对旧版 GCC): 若使用 GCC 11 或更低版本,可能需要添加编译选项 `-std=c++11` 或解决兼容性问题(参考引用[5])。 #### 2. **核心功能** ##### 客户端功能 - 支持 HTTP/HTTPS 请求(GET、POST、PUT、DELETE 等) - 自动处理连接复用(Keep-Alive) - 支持超时设置、重定向、代理等 ##### 服务端功能 - 创建 HTTP/HTTPS 服务- 路由注册(如 `Get`、`Post`) - 中间件支持(如权限验证) - 文件上传与下载 #### 3. **基础示例** ##### 示例 1:发送 GET 请求 ```cpp #include <httplib.h> #include <iostream> int main() { httplib::Client cli("http://example.com"); // 创建客户端 auto res = cli.Get("/api/data"); // 发送GET请求 if (res && res->status == 200) { std::cout << res->body << std::endl; // 输出响应内容 } else { std::cerr << "Request failed!" << std::endl; } } ``` ##### 示例 2:创建 HTTP 服务器 ```cpp #include <httplib.h> int main() { httplib::Server svr; // 注册GET请求处理 svr.Get("/hello", [](const httplib::Request& req, httplib::Response& res) { res.set_content("Hello World!", "text/plain"); }); svr.listen("0.0.0.0", 8080); // 监听所有地址的8080端口 } ``` #### 4. **HTTPS 支持** 需提前准备证书(`cert.pem`)和私钥(`key.pem`)[^4]: ```cpp #define CPPHTTPLIB_OPENSSL_SUPPORT // 启用OpenSSL支持 #include <httplib.h> int main() { // 创建HTTPS服务器(需提供证书和私钥路径) httplib::SSLServer svr("./cert.pem", "./key.pem"); svr.Get("/", [](const auto& req, auto& res) { res.set_content("HTTPS Response", "text/plain"); }); svr.listen("0.0.0.0", 443); } ``` #### 5. **连接复用优化** 通过以下宏可调整 Keep-Alive 参数[^3]: ```cpp #define CPPHTTPLIB_KEEPALIVE_TIMEOUT_SECOND 10 // 空闲连接超时(秒) #define CPPHTTPLIB_KEEPALIVE_MAX_COUNT 200 // 最大连接数 #include <httplib.h> ``` #### 6. **文件上传与下载** ##### 服务端接收文件: ```cpp svr.Post("/upload", [](const auto& req, auto& res) { auto file = req.get_file_value("file"); // 获取上传文件 std::ofstream ofs(file.filename, std::ios::binary); ofs.write(file.content.data(), file.content.size()); res.set_content("Upload OK", "text/plain"); }); ``` ##### 客户端下载文件: ```cpp auto res = cli.Get("/largefile"); if (res && res->status == 200) { std::ofstream ofs("downloaded_file", std::ios::binary); ofs << res->body; } ``` ### 注意事项 1. **性能**:单线程服务器仅适合低并发场景,高并发需自行封装线程池。 2. **编译问题**:若遇 `std::variant` 错误(GCC<7),需升级编译器或使用 `-std=c++17`。 3. **HTTPS 证书**:生产环境务必使用正规 CA 签发的证书。 > 完整文档参考:[官方 GitHub 仓库](https://github.com/yhirose/cpp-httplib)[^2] --- ### §§相关问题§§ 1. 如何用 cpp-httplib 实现文件上传的进度监控? 2. cpp-httplib 如何处理多线程并发请求? 3. 如何在 cpp-httplib 中实现 OAuth2 认证? 4. 使用 cpp-httplib 时如何记录访问日志? 5. cpp-httplib 与 WebSocket 的兼容性如何? </think> ### cpp-httplib使用指南与功能详解 cpp-httplib 是一个轻量级、易用的 C++ HTTP 库,支持 HTTP 客户端和服务端功能。以下是核心功能和使用方法: --- #### **核心优势** 1. **单文件设计**:仅需包含 `httplib.h` 头文件即可使用 2. **零依赖**:不依赖外部库(HTTPS 需 OpenSSL) 3. **跨平台**:支持 Windows/Linux/macOS 4. **高性能**:支持 HTTP 持久连接(Keep-Alive)[^3] --- #### **基础使用** ##### 1. HTTP 客户端示例 ```cpp #include <httplib.h> int main() { // 创建客户端 httplib::Client cli("http://example.com"); // 发送 GET 请求 auto res = cli.Get("/api/data"); if (res && res->status == 200) { std::cout << "响应内容: " << res->body; } } ``` ##### 2. HTTP 服务器示例 ```cpp #include <httplib.h> int main() { httplib::Server svr; // 注册 GET 路由 svr.Get("/hello", [](const auto& req, auto& res) { res.set_content("Hello World", "text/plain"); }); // 启动服务器 (监听 8080 端口) svr.listen("0.0.0.0", 8080); } ``` --- #### **高级功能** ##### 1. HTTPS 支持[^4] ```cpp #define CPPHTTPLIB_OPENSSL_SUPPORT // 启用 SSL #include <httplib.h> int main() { // HTTPS 客户端 httplib::Client cli("https://example.com"); // HTTPS 服务器 (需证书) httplib::SSLServer svr("./cert.pem", "./key.pem"); svr.Get("/secure", [](auto&, auto& res) { res.set_content("安全连接", "text/plain"); }); svr.listen("0.0.0.0", 443); } ``` ##### 2. 连接复用配置[^3] ```cpp // 配置 Keep-Alive #define CPPHTTPLIB_KEEPALIVE_TIMEOUT_SECOND 10 // 超时时间 #define CPPHTTPLIB_KEEPALIVE_MAX_COUNT 50 // 最大连接数 #include <httplib.h> ``` ##### 3. 文件服务 ```cpp svr.set_base_dir("./static"); // 设置静态文件目录 svr.Get("/download", [](auto& req, auto& res) { res.set_file("large_file.zip"); // 发送文件 }); ``` ##### 4. 请求/响应处理 ```cpp // 带参数的 POST 请求 httplib::Params params{{"key1", "value1"}, {"key2", "value2"}}; auto res = cli.Post("/submit", params); // JSON 响应 svr.Get("/json", [](auto&, auto& res) { res.set_content(R"({"status": "ok"})", "application/json"); }); ``` --- #### **性能优化** 1. **连接池**:自动复用 TCP 连接减少握手开销 2. **零拷贝**:文件传输避免内存拷贝 3. **异步接口**:支持回调异步处理 ```cpp cli.Get("/async", [](auto res) { if (res->status == 200) { // 异步处理 } }); ``` --- #### **编译注意事项[^5]** ```bash # GCC 旧版本需指定 C++11 标准 g++ -std=c++11 -lssl -lcrypto main.cpp -o server ``` > **提示**:完整文档参考[官方 GitHub](https://github.com/yhirose/cpp-httplib)[^2] --- ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值