文章目录
-
- [0. 引言](#0. 引言)
- [1. 完整实例代码](#1. 完整实例代码)
- [2. 关键实现](#2. 关键实现)
- [3. 运行与测试](#3. 运行与测试)
0. 引言
本文基于 cpp-httplib
和 nlohmann/json
实现简单的 HTTPS Server 实例代码,这两个库均是head-only的。
1. 完整实例代码
如下实例程序修改自example/server.cc
cpp
#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_SUPPORT
SSLServer svr(SERVER_CERT_FILE, SERVER_PRIVATE_KEY_FILE);
#else
Server svr;
#endif
if (!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 生成一个自签名证书:
bashopenssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -days 365 -nodes
文件说明
- `cert.pem`:服务器的自签名证书,包含公钥。
- `key.pem`:服务器的私钥,用于加密。
-
配置 SSL Server
httplib
提供了SSLServer
类,配置方法如下:cppSSLServer svr(SERVER_CERT_FILE, SERVER_PRIVATE_KEY_FILE);
SERVER_CERT_FILE
:证书文件路径。SERVER_PRIVATE_KEY_FILE
:私钥文件路径。
-
JSON 格式化响应
使用
nlohmann/json
将数据格式化为 JSON:cppres.set_content(headers_json.dump(4), "application/json");
headers_json.dump(4)
:将 JSON 对象格式化为字符串,缩进 4 空格。
-
日志记录
将每次请求和响应记录为 JSON 格式的日志:
cppsvr.set_logger([](const Request &req, const Response &res) { json log_data = log_json(req, res); printf("%s\n", log_data.dump(4).c_str()); });
-
错误处理
自定义错误响应:
cppsvr.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
:bashg++ server.cpp -o server -std=c++14 -lssl -lcrypto
-
运行服务
bash./server
-
测试 API
使用
curl
测试:bash$ 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
:忽略自签名证书的警告。
-
在浏览器上打开