HTTP Requests
Request 对象(rq)在每一个 Controller 方法以及每一个 app.get/post 回调中都可以使用。它提供了对完整 HTTP 请求以及所有响应辅助方法的访问。
Accessing the Request
在 Controller 子类内部:
class MyController extends Controller {
Future<String> index() async {
// rq 可以直接作为 getter 使用
var name = rq.get<String>('name', def: 'World');
return rq.renderString(text: 'Hello $name');
}
}
在内联的 app.get() / app.post() 回调中,rq 是该函数的参数:
app.get(
path: '/hello',
index: (rq) async {
var name = rq.get<String>('name', def: 'World');
return rq.renderString(text: 'Hello $name');
},
);
在匿名的 FinchRoute index 闭包中,使用 Context.rq:
FinchRoute(
key: 'hello',
path: 'hello',
index: () async {
var name = Context.rq.get<String>('name', def: 'World');
return Context.rq.renderString(text: 'Hello $name');
},
),
Reading Input Data
GET and POST fields
rq.get<T>(key, {T? def, trim = true}) 用于从 GET 查询参数或 POST 请求体字段中读取数据:
var name = rq.get<String>('name', def: 'anonymous');
var age = rq.get<int>('age', def: 0);
var active = rq.get<bool>('active', def: false);
检查某个字段是否存在:
if (rq.hasData('name')) { ... }
URL path parameters
对于像 users/{id} 这样的路径,使用 rq.getParam() 读取:
var id = rq.getParam('id');
// 如果该参数不存在,则返回 null
Adding parameters manually
addParam / addParams 会将数据注入请求上下文,使其在模板中可用:
rq.addParam('user', user.toJson());
rq.addParams({
'title': 'Dashboard',
'year': DateTime.now().year,
});
在 Jinja 模板中:{{ user.name }}、{{ title }}
Request Properties
| 属性 / 方法 | 类型 | 描述 |
|---|---|---|
rq.method |
String |
HTTP 方法(GET、POST、……) |
rq.isPost |
bool |
方法为 POST 时为 true |
rq.uri |
Uri |
完整的请求 URI |
rq.headers |
HttpHeaders |
HTTP 请求头 |
rq.authorization |
Authorization |
已解析的 Authorization 请求头 |
rq.cookies |
List<Cookie> |
请求中的 cookie |
rq.session |
HttpSession |
服务端 session |
rq.isApiEndpoint |
bool |
当路径以 /api/ 开头时为 true |
rq.clientIP |
String |
客户端 IP 地址 |
rq.route |
FinchRoute? |
匹配到的路由(拥有 permissions、key 等属性) |
rq.getLanguage() |
String |
当前语言代码(en、fa、……) |
Cookies
getCookie/addCookie 默认会对值进行加密和解密(两者的 safe 参数都默认为 true)——如需明文、可直接阅读的 cookie 值,需要显式传入 safe: false:
// 加密(默认)——该值在浏览器中不可读、也无法被篡改
var token = rq.getCookie('auth_token', def: '');
rq.addCookie('auth_token', 'abc123');
// 明文——该值原样存储,在浏览器的开发者工具中可见
var theme = rq.getCookie('theme', def: 'light', safe: false);
rq.addCookie('theme', 'dark', safe: false);
// 删除一个 cookie
rq.removeCookie('theme');
加密密钥是 FinchConfigs.cookiePassword。addCookie 还接受 duration、expires、path、domain、secure、httpOnly 和 sameSite 参数,用于完整控制 Set-Cookie 响应头。完整参考请参阅 Cookies and Sessions。
Sessions
// 读取
var userEmail = rq.getSession('user', def: '');
// 写入
rq.addSession('user', '[email protected]');
// 删除
rq.session.remove('user');
Redirects
// 重定向到相对路径
return rq.redirect('/login');
// 重定向到完整 URL
return rq.redirect('https://example.com');
// 使用指定的状态码
return rq.redirect('/dashboard', status: 301);
Response Methods Summary
| 方法 | Content-Type | 描述 |
|---|---|---|
renderView(path: '...') |
text/html |
渲染 Jinja 模板文件 |
renderData(data: {...}) |
application/json |
JSON 响应 |
renderString(text: '...') |
text/plain |
纯文本 |
renderHtml(html: '...') |
text/html |
HTML 字符串 |
renderTag(tag: Tag) |
text/html |
渲染 Htmler Tag |
renderError(404) |
视情况而定 | 标准错误页面或 JSON |
renderSSE(stream) |
text/event-stream |
Server-Sent Events |
renderSocket() |
— | WebSocket 握手占位符 |
renderView
rq.addParams({'title': 'Home', 'items': items});
return rq.renderView(path: 'pages/home');
// 加载路径:widgetsPath + '/pages/home.' + widgetsType
renderData (JSON)
return rq.renderData(data: {'success': true, 'count': 10});
renderError
// HTML 错误页面
return rq.renderError(404);
// JSON 错误(用于 API 路由)
return rq.renderError(403, toData: true, params: {'message': 'Forbidden'});
renderSSE (Server-Sent Events)
Future<String> sseExample() async {
Stream<String> streamer = Stream.periodic(
Duration(seconds: 1),
(count) => 'Message $count\n',
).take(10);
return rq.renderSSEString(streamer);
}