ErrorPage - 508364/NetLeaf GitHub Wiki
ErrorPage 模块是从 NetLeaf 主库分离出来的独立库,用于支持自定义错误页面模板,强制预留变量区域,并可与 Auto-route 模块联动显示路由建议。
版本: 与主库共用版本号
平台支持:
- ✅ Windows
- ✅ Linux
- ✅ macOS
- 其他模块不能使用此模块的功能
- 如果该模块未编译/未加载,错误页面功能将不可用,但不会影响主库运行
- 必须预留变量区域,否则模板无效
支持自定义HTML错误页面模板,提供灵活的错误页面定制能力。
自定义模板必须使用项目统一的变量格式 {{<var>变量名</var>}},包含以下变量:
| 变量 | 说明 | 是否必需 |
|---|---|---|
{{<var>ERROR_CODE</var>}} |
HTTP状态码(如404) | ✅ 必需 |
{{<var>ERROR_MESSAGE</var>}} |
状态码描述(如"Not Found") | ✅ 必需 |
{{<var>REQUESTED_PATH</var>}} |
请求的路径 | ✅ 必需 |
{{<var>SERVER_VERSION</var>}} |
服务器版本号 | ✅ 必需 |
{{<var>TIMESTAMP</var>}} |
错误发生时间戳 | ✅ 必需 |
{{<var>SUGGESTION</var>}} |
路由建议(可选) | 可选 |
注意: 此变量格式与项目中 nl_web_add_html_with_vars() 等函数使用的格式保持一致。
支持多种启用/禁用方式:
- 整数:
1(启用),0(禁用) - 字符串:
"true","false","on","off","yes","no"(大小写不敏感)
可以与 Auto-route 模块联动,在404错误页面中显示路由建议。
| 函数 | 说明 |
|---|---|
nl_errorpage_init() |
初始化模块 |
nl_errorpage_is_available() |
检查模块是否可用 |
nl_errorpage_version() |
获取模块版本 |
| 函数 | 说明 |
|---|---|
nl_errorpage_enable(int) |
启用/禁用模块(整数) |
nl_errorpage_enable_ex(const char*) |
启用/禁用模块(字符串) |
nl_errorpage_is_enabled() |
检查模块是否启用 |
| 函数 | 说明 |
|---|---|
nl_errorpage_load_template() |
从文件加载模板 |
nl_errorpage_set_template() |
设置模板内容 |
nl_errorpage_get_template() |
获取指定状态码的模板 |
nl_errorpage_validate_template() |
验证模板是否包含所有必需变量 |
| 函数 | 说明 |
|---|---|
nl_errorpage_render() |
使用自定义模板渲染错误页面 |
nl_errorpage_render_default() |
使用内置默认模板渲染 |
| 函数 | 说明 |
|---|---|
nl_errorpage_make_response() |
生成完整的HTTP错误响应 |
nl_errorpage_make_response_custom() |
使用自定义模板生成响应 |
nl_errorpage_quick_response() |
快速生成简单错误响应 |
nl_errorpage_404_with_suggestion() |
生成带路由建议的404响应 |
| 函数 | 说明 |
|---|---|
nl_errorpage_status_message() |
获取状态码对应的默认消息 |
nl_errorpage_is_cacheable() |
检查状态码是否可缓存 |
#include "netleaf_errorpage.h"
int main() {
// 初始化模块
nl_errorpage_init();
// 启用模块
nl_errorpage_enable_ex("true");
// 生成简单错误响应
char* response = nl_errorpage_quick_response(404, "Not Found", "/badpath");
// 使用完毕后释放内存
free(response);
return 0;
}#include "netleaf_errorpage.h"
int main() {
nl_errorpage_init();
nl_errorpage_enable_ex("true");
// 设置自定义模板(必须包含所有必需变量,使用统一格式 {{<var>VAR</var>}})
const char* template =
"<!DOCTYPE html>\n"
"<html><head><title>{{<var>ERROR_CODE</var>}} {{<var>ERROR_MESSAGE</var>}}</title></head>\n"
"<body>\n"
"<h1>{{<var>ERROR_CODE</var>}} - {{<var>ERROR_MESSAGE</var>}}</h1>\n"
"<p>您访问的路径: <code>{{<var>REQUESTED_PATH</var>}}</code> 不存在</p>\n"
"<p>{{<var>SUGGESTION</var>}}</p>\n"
"<footer>Server: {{<var>SERVER_VERSION</var>}} | Time: {{<var>TIMESTAMP</var>}}</footer>\n"
"</body></html>";
nl_errorpage_set_template(404, template);
// 生成错误响应
nl_errorpage_vars_t vars = {
.status_code = 404,
.error_message = "Not Found",
.requested_path = "/api/user",
.suggestion = "/api/users", // 来自Auto-route模块
.server_version = "NetLeaf v2.4.0"
};
char* response = nl_errorpage_make_response(404, &vars);
free(response);
return 0;
}#include "netleaf_errorpage.h"
#include "netleaf_autoroute.h"
void handle_404(const char* requested_path) {
// 获取路由建议(来自Auto-route模块)
char* suggestion = NULL;
if (nl_autoroute_is_available() && nl_autoroute_is_enabled()) {
nl_route_matcher_t* matcher = nl_autoroute_get_global_matcher();
suggestion = nl_route_matcher_find_similar(matcher, requested_path, 0.4);
}
// 生成带建议的404响应
char* response = nl_errorpage_404_with_suggestion(requested_path, suggestion);
// 发送响应...
free(suggestion);
free(response);
}<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{{<var>ERROR_CODE</var>}} {{<var>ERROR_MESSAGE</var>}}</title>
<style>
body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; margin: 0; padding: 40px; background: #f5f5f5; }
.error-container { max-width: 600px; margin: 0 auto; background: white; border-radius: 8px; padding: 40px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); }
h1 { color: #e74c3c; margin: 0 0 20px 0; font-size: 72px; }
h2 { color: #333; margin: 0 0 20px 0; font-size: 24px; }
p { color: #666; margin: 10px 0; }
.path { background: #f8f9fa; padding: 10px; border-radius: 4px; font-family: monospace; }
.suggestion { background: #e8f5e9; padding: 15px; border-radius: 4px; margin-top: 20px; }
.suggestion a { color: #2e7d32; font-weight: bold; }
.footer { margin-top: 30px; color: #999; font-size: 12px; }
</style>
</head>
<body>
<div class="error-container">
<h1>{{<var>ERROR_CODE</var>}}</h1>
<h2>{{<var>ERROR_MESSAGE</var>}}</h2>
<p>The requested path could not be found:</p>
<p class="path">{{<var>REQUESTED_PATH</var>}}</p>
{{<var>SUGGESTION</var>}}
<div class="footer">
Server: {{<var>SERVER_VERSION</var>}} | Time: {{<var>TIMESTAMP</var>}}
</div>
</div>
</body>
</html><!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{{<var>ERROR_CODE</var>}} {{<var>ERROR_MESSAGE</var>}}</title>
<style>
body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; margin: 0; padding: 40px; background: #f5f5f5; }
.error-container { max-width: 600px; margin: 0 auto; background: white; border-radius: 8px; padding: 40px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); }
h1 { color: #e74c3c; margin: 0 0 20px 0; font-size: 72px; }
h2 { color: #333; margin: 0 0 20px 0; font-size: 24px; }
p { color: #666; margin: 10px 0; }
.footer { margin-top: 30px; color: #999; font-size: 12px; }
</style>
</head>
<body>
<div class="error-container">
<h1>{{<var>ERROR_CODE</var>}}</h1>
<h2>{{<var>ERROR_MESSAGE</var>}}</h2>
<p>An internal server error occurred. Please try again later.</p>
<p>Path: <code>{{<var>REQUESTED_PATH</var>}}</code></p>
<div class="footer">
Server: {{<var>SERVER_VERSION</var>}} | Time: {{<var>TIMESTAMP</var>}}
</div>
</div>
</body>
</html>模块提供模板验证功能,确保自定义模板包含所有必需变量:
const char* template = "...";
if (nl_errorpage_validate_template(template)) {
printf("模板验证通过\n");
nl_errorpage_set_template(404, template);
} else {
printf("模板缺少必需变量\n");
}模块支持以下常见HTTP状态码的自定义模板:
| 状态码 | 说明 |
|---|---|
| 400 | Bad Request |
| 401 | Unauthorized |
| 403 | Forbidden |
| 404 | Not Found |
| 405 | Method Not Allowed |
| 408 | Request Timeout |
| 500 | Internal Server Error |
| 502 | Bad Gateway |
| 503 | Service Unavailable |
| 504 | Gateway Timeout |
BUILD_ERRORPAGE=ON # 默认启用- 模块独立性: ErrorPage模块是独立的,其他模块不能使用其功能
- 变量强制性: 自定义模板必须包含所有必需变量,否则验证失败
- 联动限制: 只能与Auto-route模块联动显示路由建议
- 错误处理: 如果模块未加载,错误页面功能不可用,但不会导致崩溃
- 内存管理: 生成的响应字符串需要调用者手动释放
用户请求不存在的路径
↓
服务器返回404
↓
Auto-route模块查找相似路由
↓
生成路由建议(如"/api/users")
↓
ErrorPage模块渲染错误页面
↓
在错误页面中显示"您可能在找: /api/users"