如何将数据从channel.dart传递到中间件句柄方法?

时间:2019-01-06 14:39:59

标签: dart aqueduct

我创建了一个中间件控制器,该控制器负责身份验证。控制器将链接在资源控制器的前面。我认为这是正确的方法?

在handle方法中,我正在执行数据库查询,该查询需要连接信息。但是,当我尝试通过构造函数传递数据时,它告诉我不允许使用setter。

将带有连接信息的Map从channel.dart传递到中间件控制器的最佳方法是什么(请参见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”。控制器不得包含setter和所有字段   必须标记为final,或者必须实现“可回收”。)

在我的案例中,AuthMiddleWare正在URL中解析一个令牌,并将检查该令牌在数据库中是否有效。如您所见,除了直接在AuthMiddleware isValid函数内添加dbConnectionDetails之外,我没有发现其他方法。但是,如果我可以将其从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 个答案:

答案 0 :(得分:1)

由CA编辑:解决方案(由Joe Conway提供):

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;
  }
}