文章目录
- 0. 引言
- 1. 完整实例代码
- 2. 关键实现
- 3. 运行与测试
0. 引言
本文基于 cpp-httplib
和 nlohmann/json
实现简单的 HTTPS Server 实例代码,这两个库均是head-only的。
1. 完整实例代码
如下实例程序修改自example/server.cc
#include <httplib.h>#include <chrono>
#include <cstdio>
#include <nlohmann/json.hpp>using namespace httplib;
using json = nlohmann::json;#define SERVER_CERT_FILE "./cert.pem"
#define SERVER_PRIVATE_KEY_FILE "./key.pem"json dump_headers_json(const Headers &headers) {json j;for (const auto &x : headers) {j[x.first] = x.second;}return j;
}json log_json(const Request &req, const Response &res) {json j;j["request"]["method"] = req.method;j["request"]["version"] = req.version;j["request"]["path"] = req.path;json query_params = json::object();for (const auto &x : req.params) {query_params[x.first] = x.second;}j["request"]["query_params"] = query_params;j["request"]["headers"] = dump_headers_json(req.headers);j["response"]["status"] = res.status;j["response"]["version"] = res.version;j["response"]["headers"] = dump_headers_json(res.headers);j["response"]["body"] = res.body;return j;
}int main(void) {
#ifdef CPPHTTPLIB_OPENSSL_SUPPORTSSLServer svr(SERVER_CERT_FILE, SERVER_PRIVATE_KEY_FILE);
#elseServer svr;
#endifif (!svr.is_valid()) {printf("server has an error...\n");return -1;}svr.Get("/", [=](const Request & /*req*/, Response &res) { res.set_redirect("/hi"); });svr.Get("/hi", [](const Request & /*req*/, Response &res) { res.set_content("Hello World!\n", "text/plain"); });svr.Get("/slow", [](const Request & /*req*/, Response &res) {std::this_thread::sleep_for(std::chrono::seconds(2));res.set_content("Slow...\n", "text/plain");});svr.Get("/dump", [](const Request &req, Response &res) {json headers_json = dump_headers_json(req.headers);res.set_content(headers_json.dump(4), "application/json");});svr.Get("/stop", [&](const Request & /*req*/, Response & /*res*/) { svr.stop(); });svr.set_error_handler([](const Request & /*req*/, Response &res) {json j;j["error"]["status"] = res.status;j["error"]["message"] = "An error occurred.";res.set_content(j.dump(4), "application/json");});svr.set_logger([](const Request &req, const Response &res) {json log_data = log_json(req, res);printf("%s\n", log_data.dump(4).c_str());});svr.listen("localhost", 8080);return 0;
}
2. 关键实现
-
自签名证书(开发/测试用途)
SSL 服务器需要证书和私钥文件。使用 OpenSSL 生成一个自签名证书:
openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -days 365 -nodes
文件说明
- `cert.pem`:服务器的自签名证书,包含公钥。
- `key.pem`:服务器的私钥,用于加密。
-
配置 SSL Server
httplib
提供了SSLServer
类,配置方法如下:SSLServer svr(SERVER_CERT_FILE, SERVER_PRIVATE_KEY_FILE);
SERVER_CERT_FILE
:证书文件路径。SERVER_PRIVATE_KEY_FILE
:私钥文件路径。
-
JSON 格式化响应
使用nlohmann/json
将数据格式化为 JSON:res.set_content(headers_json.dump(4), "application/json");
headers_json.dump(4)
:将 JSON 对象格式化为字符串,缩进 4 空格。
-
日志记录
将每次请求和响应记录为 JSON 格式的日志:svr.set_logger([](const Request &req, const Response &res) {json log_data = log_json(req, res);printf("%s\n", log_data.dump(4).c_str()); });
-
错误处理
自定义错误响应:svr.set_error_handler([](const Request & /*req*/, Response &res) {json j;j["error"]["status"] = res.status;j["error"]["message"] = "An error occurred.";res.set_content(j.dump(4), "application/json"); });
3. 运行与测试
-
编译代码
确保链接nlohmann/json
和httplib
:g++ server.cpp -o server -std=c++14 -lssl -lcrypto
-
运行服务
./server
-
测试 API
使用curl
测试:$ curl -k https://localhost:8080/dump {"Accept": "*/*","Host": "localhost:8080","LOCAL_ADDR": "127.0.0.1","LOCAL_PORT": "8080","REMOTE_ADDR": "127.0.0.1","REMOTE_PORT": "41542","User-Agent": "curl/7.68.0" }%
参数说明:
-k
:忽略自签名证书的警告。
-
在浏览器上打开