第三十六章 前端路由与控制器

篇别:第八篇 前端开发

本章学习目标

  • 编写 type='http'type='jsonrpc'Web Controller,理解 authcsrfwebsite 的含义。
  • 掌握 Odoo 19 中 jsonjsonrpc 路由类型变更的 迁移步骤与回归点
  • 理解 WebClientURL(含 hash)与当前 action / 菜单同步关系,能安全 分享深链
  • 能为 自定义 JSON API 编写 HttpCase基本安全清单(鉴权、限流、输入校验)。

导读:控制器是「HTTP 边界」

Controller 是 Odoo 与 浏览器、移动端 App、Webhook 源站 之间的 HTTP 边界。这里最容易出现 CSRF 疏漏、鉴权过宽、JSON 解析错误未捕获 等问题。本章与 第三十章(安全)第三十七章~三十八章(API) 强相关:同样一条 URL,可能是 网站页JSON-RPC自定义 REST路由签名不同则 行为完全不同


36.1 Web Controller

36.1.1 知识要点

  • http.Controller:类属性 @http.route 定义 路径、类型、认证、站点
  • type='http':返回 Response / QWeb / JSONmake_json_response);适用于 页面、文件下载、简单 JSON
  • authpublic(可匿名)、user(须登录后台用户)、none(极少用)等;网站路由website=True
  • csrf:表单与部分 HTTP POST 默认校验csrf=False 仅在有 替代防护 时使用(签名、API Key、内网)。
  • request.env:与 ORM 一致;request.jsonrequest(若存在)仅 jsonrpc 路径典型可用——以版本为准。
  • 错误:捕获业务异常 UserError 映射为 合适 HTTP 状态 向客户端泄露 Python 栈(生产)。

36.1.2 案例

from odoo import http
from odoo.http import request

class LibraryController(http.Controller):
    @http.route("/library/ping", type="http", auth="public", website=True, csrf=False)
    def ping(self):
        return request.make_json_response({"ok": True})

    @http.route("/library/me", type="http", auth="user", methods=["GET"], website=True)
    def me(self):
        return request.make_json_response({"login": request.env.user.login})

36.1.3 截图占位

图 36-1 Postman 或 curl 调用 /library/ping

36.1.4 本节练习

  1. 实操:为 /library/me 增加 auth='user'未登录 访问测试(302 / 401 / 403 之一,以部署为准)。
  2. 简答website=Truewebsite=FalseQWeb 布局与会话 的典型影响?
  3. 判断auth='public' 表示 不经过 Odoo 会话。( )

参考答案提示:3. 错;仍可有 匿名会话,取决于 网站中间件


36.2 控制器类型变更(补充)

36.2.1 知识要点

  • Odoo 19 起,旧式 type='json' 路由应迁移为 type='jsonrpc'(名称以 官方迁移说明 为准)。
  • 语义JSON-RPC 2.0 封装 jsonrpcmethodparamsid;与 裸 REST JSON 不同。
  • 客户端:前端 rpc / orm service 依赖 正确路由类型;混用会导致 415 / 404 / 解析失败
  • 迁移:全仓库 grep "type='json'"逐条替换跑 smoke + 自定义集成测试

36.2.2 案例

class LibraryApi(http.Controller):
    @http.route("/library/jsonrpc/ping", type="jsonrpc", auth="user")
    def jsonrpc_ping(self):
        return {"pong": True}

36.2.3 截图占位

图 36-2 官方文档中 route type 说明

36.2.4 本节练习

  1. 实操:全局搜索 type='json',替换为 jsonrpc 后跑 登录与一条业务 RPC 烟测。
  2. 简答jsonrpc 路由的 返回值http + make_json_response错误格式 上可能有何不同?

参考答案提示:2. JSON-RPC 封装错误对象;裸 JSON 常 自定义 status + body


36.3 前端路由机制(新增)

36.3.1 知识要点

  • WebClient 通过 action service、菜单、hash(或 history API,以版本为准)维持 「当前动作 ↔ URL」 同步。
  • 分享链接:带 actionidmodel 等参数的 URL 可 直达某条记录接收方须权限同一 dbdbfilter 环境尤需注意)。
  • 多标签:不同标签 会话相同 时,互相覆盖 hash 可能造成 「以为丢了页面」——属 正常浏览器行为
  • 扩展:自定义 client action 若需 可分享状态,应将 关键参数 写入 action context / hash(设计时与 产品经理 对齐)。

36.3.2 案例

口述步骤:打开 销售订单列表 → 点开 某单表单 → 复制 地址栏 URL隐身窗口 登录同用户粘贴 → 核对 是否同一记录

36.3.3 截图占位

图 36-3 地址栏 hash 与当前 action / 记录

36.3.4 本节练习

  1. 简答:分享带 id= 的 URL 给同事需注意什么?(至少 权限、数据库、环境 三点中写两点。)
  2. 判断:前端路由 完全由 Nginx rewrite 决定,与 Odoo WebClient 无关。( )

参考答案提示:2. 错。


本章综合练习

  1. 实现JSON API(http + JSON) 返回 图书列表,支持 limit、简单 domain 查询参数,并写 HttpCase200 + JSON 结构)。
  2. 安全auth='public' 接口的 rate limit 思路(Nginx、WAF、应用内计数 任选两层说明)。
  3. 综合:对比 第三十八章 REST本章 jsonrpc:各写 一条 适用集成场景
  4. 实操:为 jsonrpc 接口增加 UserError,观察 前端 notificationHTTP 状态(记录现象即可)。

本章对应白皮书目录:第三十六章 前端路由与控制器。 @http.route 装饰器参数、路径转换器与 http / jsonrpc 细节第五十章《HTTP 控制器与 @http.route