如何添加属性记录?

How to add properties to record?

我要

  1. 从 http 请求中提取 jwt
  2. 从 jwt 获取声明
  3. 向命令模型添加声明

喜欢下面

let middleware<'a> handler next (ctx: HttpContext) =
    task {
        let token = ctx.Request.Headers.["Authorization"].ToString()
        match token with
        | Bearer token ->
            let claims = getClaims token
            let! command = ctx.BindJsonAsync<'a>()
            // how to add claims to command?
            return! handler command next ctx

        | _ ->
            return! RequestErrors.unauthorized "Bearer" "Commerce" authenticationError next ctx
    }

如何进行第 3 步?

这里有 4 个选项。

  1. 您可以将 JWT 授权属性添加到您的命令模型中,并避免在调用 BindJsonAsync 时绑定它们然后填充它。这是我最不喜欢的方法,因为您最终得到的属性可以由发送模型的人设置。

  2. 您可以使用匿名记录向您的记录类型添加额外的属性。这种方法你需要知道可能会导致问题的命令类型,因为看起来你正在使用通用模型绑定。这也使得跨二进制边界传递类型变得更加困难。

type CommandHandler = { Command : string; Entity : int }
let command = { Command = "Update"; Entity = 1 }
let authorisedCommand = {| command with AuthToken = "ey ===" |}
  1. 您可以创建一个新类型,它是您用于模型绑定的类型的副本,除了附加属性之外,但这再次意味着您需要知道您正在复制的固定类型,并且您还需要复制所有的属性。
type CommandHandlerModel = { Command : string; Id : int }
type AuthorisedCommandHandlerModel = { Command : string; Id : int }
let commandHandler = { CommandHandlerModel.Command = "Update"; Id = 1 }
let authedCommandHandler = { AuthporosedCommandHandlerModel.Command = "Update"; Id = 1 }
  1. 不过,我可能会采用的方法是将您的命令包装成这样的新类型:
type CommandHandlerModel = { Command : string; Id : int }
type AuthorisedCommandHandlerModel<'a> = { CommandModel : 'a; AuthToken : string }
let! command = ctx.BindJsonAsync<'a>()
let authedCommand = { CommandModel = command; AuthToken = claims }

我觉得这种组合方法是解决问题的更惯用的方法,也是我过去使用过的方法