控制器

控制器在 Finch 中封装了请求处理逻辑。控制器是一个继承 Controller 的类,通过 rq 访问当前请求对象。

基本结构

import 'package:finch/finch_route.dart';

class HomeController extends Controller {
  Future<String> index() async {
    return rq.renderView(path: 'home/index');
  }
}

在路由中使用控制器:

final homeController = HomeController();

FinchRoute(
  key: 'root',
  path: '/',
  methods: Methods.ONLY_GET,
  index: homeController.index,
),

rq 对象

rq(request 的缩写)是每个控制器方法中可用的核心对象。它提供对请求数据、响应方法、会话、Cookie、语言等的访问。

响应方法

方法 描述
rq.renderView(path: '...') 渲染 Jinja 模板。路径相对于 widgetsPath
rq.renderData(data: {...}) 返回 JSON 响应
rq.renderError(status: 404) 发送 HTTP 错误响应
rq.renderString(text: '...') 返回纯文本或 HTML
rq.redirect(url: '...') 重定向到 URL
rq.renderNotFound() 返回 404

渲染模板

Future<String> index() async {
  return rq.renderView(
    path: 'home/index',        // 相对于 widgetsPath 的路径,无扩展名
    params: {
      'title': '首页',
      'user': currentUser,
    },
  );
}

返回 JSON

Future<String> apiUser() async {
  var id = rq.getParam('id');
  var user = await UserModel().find(id: id);
  return rq.renderData(data: user?.toJson() ?? {});
}

读取请求数据

// 查询/表单参数
var name = rq.get<String>('name', def: '');
var age  = rq.get<int>('age', def: 0);

// 路径参数 (/users/{id})
var id   = rq.getParam('id');

// 原始 JSON body
var body = await rq.getBodyAsJson();

// 上传的文件
var file = rq.getFile('avatar');

请求属性

rq.method           // 'GET', 'POST', …
rq.path             // '/users/42'
rq.ip               // 客户端 IP 地址
rq.headers          // Map<String, List<String>>
rq.isJson           // Content-Type 是否为 application/json
rq.currentLanguage  // 当前语言代码

向模板传递数据

除了 renderView 中的 params 之外,还可以在 FinchRoute 定义中为整个路由指定参数:

FinchRoute(
  key: 'root',
  path: '/',
  params: {'siteName': 'Finch 演示'},
  index: homeController.index,
),

路由级数据与 renderView 中的控制器级数据合并。

HTTP 错误

// 发送 403 Forbidden
return rq.renderError(status: 403, message: '禁止访问');

// 发送 500 Internal Server Error
return rq.renderError(status: 500);