Flutter插件relic的使用_Relic 是一个基于 Shelf 的 Web 服务器,
Flutter插件relic的使用_Relic 是一个基于 Shelf 的 Web 服务器,
Relic 是一个基于 Shelf 的 Web 服务器,支持中间件。它目前处于技术预览阶段,旨在收集反馈以便在发布稳定版本之前进行改进。请注意,API 仍有可能发生变化。最好的反馈方式是通过 GitHub 上的问题页面: https://github.com/serverpod/relic/issues
该包最初是为满足 Serverpod 的需求而创建的,我们希望拥有一个更现代且性能更高的 Web 服务器基础。Relic 基于 Shelf,但已进行了多项改进:
- 我们移除了所有的
<code>List<int></code>
,取而代之的是<code>Uint8List</code>
。 - 我们使所有内容类型安全(不再使用
dynamic
)。 - 编码类型已移至
<code>Request</code>/<code>Response</code>
的<code>Body</code>
中,以简化逻辑并提供单一的真相来源。 - 我们添加了对所有常用 HTTP 头的解析器和验证器。例如,时间由
<code>DateTime</code>
表示,cookies 有自己的类,并具有格式验证等。 - 扩展了测试覆盖率。
- 还有一些较小的修复。
尽管结构与 Shelf 非常相似,但这不再是向后兼容的。我们认为过渡会相当直接,并计划制定一份指南。
在发布稳定版本之前,我们还计划增加以下功能:
- 我们希望更紧密地将 HTTP 服务器集成到 Relic 中(即,从
<code>dart:io</code>
开始使用<code>HttpServer</code>
作为基础),这样一切都使用相同的类型。这还将提高性能,因为需要的转换更少。 - 路由可以通过使用 Radix 树来改进。目前只是遍历列表,如果你有很多路由,这可能会成为一个问题。
- 我们计划添加一个改进的测试框架。
- 性能测试和优化。
此外,我们还计划在 Serverpod 中包含 Relic,既用于支持我们的 RPC,也作为 Web 服务器的基础。这将为我们的 RPC 提供中间件支持。在 Web 服务器集成方面,我们支持 HTML 模板和路由。你还可以访问 Serverpod 生态系统的其他部分,包括序列化、缓存、发布订阅和数据库集成。
示例
查看 <code>example/example.dart</code>
文件。
import 'package:relic/relic.dart';
void main() async {
var handler =
const Pipeline().addMiddleware(logRequests()).addHandler(_echoRequest);
var server = await serve(
handler,
RelicAddress.fromHostname('localhost'),
8080,
);
// 启用内容压缩
server.autoCompress = true;
print('Serving at http://${server.address.host}:${server.port}');
}
Response _echoRequest(Request request) {
return Response.ok(
body: Body.fromString(
'Request for "${request.url}"',
),
);
}
处理程序和中间件
处理程序是任何处理 <code>Request</code>
并返回 <code>Response</code>
的函数。它可以自行处理请求——例如,静态文件服务器查找文件系统上的请求 URI;或者它可以做一些处理并将其转发给另一个处理程序——例如,记录器将请求和响应的信息打印到命令行。
后一种类型的处理程序称为“中间件”,因为它位于服务器堆栈的中间。中间件可以被视为一个函数,它接受一个处理程序并在另一个处理程序周围包装它以提供额外的功能。一个 Shelf 应用程序通常由许多层中间件组成,最中心有一个或多个处理程序;<code>Pipeline</code>
类使得构建这种应用程序变得容易。
某些中间件也可以接受多个处理程序,并为每个请求调用其中一个或多个。例如,路由中间件可能根据请求的 URI 或 HTTP 方法选择要调用的处理程序,而级联中间件可能按顺序调用每个处理程序,直到一个返回成功响应。
路由请求到处理程序之间的中间件应确保更新每个请求的 <code>handlerPath</code>
和 <code>url</code>
。这允许内部处理程序知道它们在应用中的位置,以便正确地进行自己的路由。这可以很容易地使用 <code>Request.copyWith()</code>
完成:
// 在一个假想的路由中间件中...
var component = request.url.pathSegments.first;
var handler = _handlers[component];
if (handler == null) return Response.notFound();
// 创建一个新的请求,就像这个请求一样,但使用 [component] 之后的任何 URL。
return handler(request.copyWith(path: component));
适配器
适配器是任何创建 <code>Request</code>
对象、传递给处理程序并处理结果 <code>Response</code>
的代码。大多数情况下,适配器会从前端 HTTP 服务器转发请求和响应;<code>serve</code>
就是这种适配器。适配器也可能使用 <code>window.location</code>
和 <code>window.history</code>
在浏览器内合成 HTTP 请求,或者可以直接将请求从 HTTP 客户端管道传输到 Shelf 处理程序。
API 要求
适配器必须处理来自处理程序的所有错误,包括处理程序返回 <code>null</code>
响应的情况。如果可能,它应该将每个错误打印到控制台,然后行为上好像处理程序返回了一个 500 响应。适配器可以包含 500 响应的正文数据,但这些数据不能包含发生错误的信息。这确保了意外错误不会默认在生产环境中暴露内部信息;如果用户想要返回详细的错误描述,他们应该显式地包括中间件来实现这一点。
适配器应确保处理程序抛出的异步错误不会导致应用程序崩溃,即使它们未被未来的链报告。具体来说,这些错误不应传递给根区域的错误处理器;然而,如果适配器在一个其他错误区域运行,它应该允许这些错误传递到该区域。可以使用以下函数捕获那些原本会被顶层处理的错误:
/// 运行 [callback] 并捕获任何原本会被顶层处理的错误。
///
/// 如果此函数在非根错误区域中调用,则只会运行 [callback] 并返回结果。否则,它将使用 [runZoned] 捕获任何错误并传递给 [onError]。
void catchTopLevelErrors(
void Function() callback,
void Function(Object error, StackTrace stackTrace) onError,
) {
if (Zone.current.inSameErrorZone(Zone.root)) {
return runZonedGuarded(callback, onError);
} else {
return callback();
}
}
更多关于Flutter插件relic的使用_Relic 是一个基于 Shelf 的 Web 服务器,的实战教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter插件relic的使用_Relic 是一个基于 Shelf 的 Web 服务器,的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
在Flutter开发中,当遇到一个新的或文档不充分的插件时,了解其功能和用法通常需要通过阅读插件的源代码、官方示例代码或者社区贡献的代码片段。由于relic
插件在官方Flutter插件库中并未定义,以下基于插件名称relic
进行推测,并给出一个可能的代码案例来展示如何集成和使用一个假设的Flutter插件。
请注意,以下代码仅作为示例,实际使用时需要根据relic
插件的实际API进行调整。
1. 添加依赖
首先,假设relic
插件已经发布在某个Flutter插件仓库中(如pub.dev或私有仓库),你需要在pubspec.yaml
文件中添加该依赖:
dependencies:
flutter:
sdk: flutter
relic: ^x.y.z # 替换为实际的版本号
然后运行flutter pub get
来安装依赖。
2. 导入插件
在你的Dart文件中导入relic
插件:
import 'package:relic/relic.dart';
3. 使用插件
由于relic
插件的具体功能未知,以下代码基于假设的功能进行编写。假设relic
插件提供了一个用于管理应用缓存的功能,以下是如何可能使用该插件的示例:
import 'package:flutter/material.dart';
import 'package:relic/relic.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Relic Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: RelicDemoScreen(),
);
}
}
class RelicDemoScreen extends StatefulWidget {
@override
_RelicDemoScreenState createState() => _RelicDemoScreenState();
}
class _RelicDemoScreenState extends State<RelicDemoScreen> {
String cacheStatus = 'Unknown';
@override
void initState() {
super.initState();
// 假设Relic有一个用于检查缓存状态的方法
_checkCacheStatus();
}
Future<void> _checkCacheStatus() async {
try {
// 假设Relic类有一个静态方法checkCacheStatus,返回一个Future<String>
String status = await Relic.checkCacheStatus();
setState(() {
cacheStatus = status;
});
} catch (e) {
print('Error checking cache status: $e');
setState(() {
cacheStatus = 'Error: ${e.toString()}';
});
}
}
Future<void> _clearCache() async {
try {
// 假设Relic类有一个静态方法clearCache,返回一个Future<void>
await Relic.clearCache();
setState(() {
cacheStatus = 'Cache cleared';
});
} catch (e) {
print('Error clearing cache: $e');
setState(() {
cacheStatus = 'Error: ${e.toString()}';
});
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Relic Demo'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text('Cache Status: $cacheStatus'),
SizedBox(height: 20),
ElevatedButton(
onPressed: _clearCache,
child: Text('Clear Cache'),
),
],
),
),
);
}
}
注意事项
- 实际API可能不同:上述代码基于假设的API编写,实际使用时需要根据
relic
插件的真实API进行调整。 - 错误处理:示例代码中包含了基本的错误处理,实际使用时可能需要更详细的错误处理逻辑。
- 文档和示例:如果
relic
插件有官方文档或示例代码,建议首先参考这些资源。
由于relic
插件的具体信息未知,以上内容仅作为如何集成和使用一个假设Flutter插件的示例。实际使用时,请根据插件的实际功能和API进行调整。