章节目录

读懂 RinBlog:从函数到架构

本章目标

这一章把前面的知识放回当前项目。你会从请求流、数据模型、存储、HTML 渲染、文档站模块几个角度读懂 RinBlog,并理解它如何从教学项目演进成更清晰的工程。

它是什么

RinBlog 是一个极简 Rust Web 服务。它包含两条主线:

  • 博客线:发布文章、保存到文件、查看文章。
  • 教材线:读取 docs/ Markdown、渲染 HTML、在线浏览。

这两条线共用 HTTP 服务器和响应结构,但业务数据来源不同。

为什么需要

学语法和读真实项目之间有落差。这个项目刻意小,让你能从入口读到每个函数;又足够完整,让你看到路由、解析、存储、渲染、安全边界。

工程架构的关键不是一开始就上复杂框架,而是能回答:

  • 请求从哪里进来。
  • 数据在哪里变形。
  • 错误在哪里处理。
  • 哪些模块知道哪些细节。
  • 哪些输入必须被校验。

怎么使用

建议按这条路线读源码:

  1. main:启动监听和创建文章目录。
  2. handle_connection:连接级处理。
  3. read_http_request:字节到请求结构体。
  4. route_inner:路径到功能。
  5. render_index_responserender_post_response:博客 HTML。
  6. docs::render_docs_response:教材 HTML。
  7. save_postload_post:文件存储。
  8. escape_html:输出安全。

逐行解释

_ if request.method == "GET" && docs::is_docs_path(path) => docs::render_docs_response(path),
  • _ 表示前面的精确模式没有匹配时,进入这个带条件的分支判断。
  • request.method == "GET" 限定只有 GET 请求可以读文档。
  • docs::is_docs_path(path) 把文档路径判断交给 docs 模块。
  • docs::render_docs_response(path) 生成完整文档响应。
  • 这一行体现了模块边界:路由层只知道“交给 docs”,不知道 Markdown 如何读取和渲染。

常见坑

  • 小项目也要有安全边界。post_path 校验数字 id,docs 模块使用章节白名单。
  • HTML 输出用户内容必须转义。文章标题和正文都不能直接拼进 HTML。
  • 教材 Markdown 是仓库可信内容,因此可以渲染为 HTML;用户提交的 Markdown 则需要更严格策略。
  • 路由顺序会影响匹配结果,越具体的分支通常越靠前。

练习

  1. 画出一次 /docs 请求经过的函数链。
  2. 画出一次 /posts POST 请求经过的函数链。
  3. 找出哪些函数返回 io::Result,说明它们为什么可能失败。
  4. 找出所有把字符串拼成 HTML 的地方,确认是否需要转义。

造轮子任务

把路由解析单独抽象成 enum Route,再让 route_inner 先调用 parse_route(path)。这会让路由层从“字符串匹配”进化到“类型匹配”,也更适合后续扩展。

小结

RinBlog 的价值在于透明。它不完美,也不追求生产级能力,但它展示了一个 Web 服务的骨架。读懂它之后,再看 Axum、Actix Web、Rocket,你会更清楚框架在替你处理哪些层。