Как передать данные из channel.dart в метод дескриптора промежуточного программного обеспечения?
Я создал контроллер промежуточного программного обеспечения, который отвечает за аутентификацию. Контроллер будет связан перед контроллерами ресурсов. Я полагаю, это правильный способ сделать это?
В методе handle я выполняю запрос к базе данных, который требует информацию о соединении. Однако когда я пытаюсь передать данные через конструктор, он говорит мне, что сеттеры не допускаются.
Как лучше всего передать карту с информацией о соединении из channel.dart в контроллер Middleware (см. DbConnectionDetails)?
channel.dart
@override
Future prepare() async {
logger.onRecord.listen((rec) => print("$rec ${rec.error ?? ""} ${rec.stackTrace ?? ""}"));
dbConnectionDetails = ConnectionSettings (
user: "mydbuser",
password: "mydbpass",
host: "localhost",
port: 3306
);
}
@override
Controller get entryPoint {
final router = Router();
router
.route("/api/user/query/complex")
.link(() => AuthMiddleware())
.link(() => UserComplexQueryController(dbConnectionDetails));
}
В приведенном выше примере я могу передать dbConnectionDetails в конструктор UserComplexQueryController, чтобы я мог использовать его для подключения к базе данных.
Однако если я передам dbConnectionDetails в конструктор AuthMiddleWare, то получу следующую ошибку:
ArgumentError (Неверный аргумент (ы): недопустимый контроллер 'AuthMiddleware'. У контроллеров не должно быть сеттеров, и все поля должны быть помечены как окончательные, или он должен реализовывать 'Recyclable'.)
AuthMiddleWare в моем случае получает токен, проанализированный в URL, и проверит, является ли токен действительным в базе данных. Как вы можете видеть, я не нашел другого способа, кроме как добавить dbConnectionDetails непосредственно в функцию isValid AuthMiddleware. Но я бы предпочел, если бы я мог передать его из channel.dart.
class AuthMiddleware extends Controller {
// This does not work, as setters not allowed
//AuthMiddleware(this.dbConnectionDetails);
//
//ConnectionSettings dbConnectionDetails
@override
Future<RequestOrResponse> handle(Request request) async {
if (await isValid(request)) {
return request;
}
return Response.unauthorized();
}
Future<bool> isValid(Request request) async {
final String token = request.raw.requestedUri.queryParameters["token"];
final int timestamp = (DateTime.now().toUtc().millisecondsSinceEpoch / 1000).round();
ConnectionSettings dbConnectionDetails = ConnectionSettings (
user: "myuser",
password: "mypass",
host: "localhost",
port: 3306
);
AuthTokenDao authTokenDao = new AuthTokenDao(dbConnectionDetails);
if(await authTokenDao.validateToken(token, timestamp)) {
return true;
}
return false;
}
}
И да, вы видели правильно. Я подключаюсь к базе данных MySQL:)
1 ответ
Редактировать CA: Решение (предоставлено Джо Конвей):
class AuthMiddleware extends Controller {
// Works by adding "final"
final ConnectionSettings dbConnectionDetails;
// Now dbConnectionDetails can be passed within the constructor.
AuthMiddleware(this.dbConnectionDetails);
@override
Future<RequestOrResponse> handle(Request request) async {
if (await isValid(request)) {
return request;
}
return Response.unauthorized();
}
Future<bool> isValid(Request request) async {
final String token = request.raw.requestedUri.queryParameters["token"];
final int timestamp = (DateTime.now().toUtc().millisecondsSinceEpoch / 1000).round();
/* Removed this
ConnectionSettings dbConnectionDetails = ConnectionSettings (
user: "myuser",
password: "mypass",
host: "localhost",
port: 3306
);
*/
AuthTokenDao authTokenDao = new AuthTokenDao(dbConnectionDetails);
if(await authTokenDao.validateToken(token, timestamp)) {
return true;
}
return false;
}
}