使用 RIO

如何解决使用 RIO

我正在尝试将 Servant 身份验证(servant-auth-server 包)与 RIO 结合作为我的处理程序 monad,以避免出现 ExceptT 反模式。但是,我无法正确排列类型以处理被拒绝的身份验证。

我的(简化的)API 端点是

type UserEndpoint = "user" :> (
              Get '[JSON] User                                       
        :<|>  ReqBody '[JSON] UpdatedUser :> Put '[JSON] User        
    )

和对应的服务器

protectedServer
  :: HasLogFunc m
  => AuthResult AuthUserId
  -> ServerT UserEndpoint (RIO m)
protectedServer (Authenticated authUser) =
  getUser authUser :<|> updateUser authUser
-- Otherwise,we return a 401.
protectedServer _ = throwIO err401

在拒绝身份验证的分支中出现类型错误

    Could not deduce (Monadio ((:<|>) (RIO m User)))
      arising from a use of ‘throwIO’
    [..]

我不理解这种类型的错误。根据我的理解(并给出 protectedServer 的签名),返回类型应该是 ServerT UserEndpoint (RIO m),它应该有一个 Monadio 的实例,以便根据 {{3} } 应该使用 throwIO 而不是 throwAll 中的 Servant.Auth.Server。看来我还没有完全理解Servant的类型机制,我的错误在哪里?

两个处理函数定义为

updateUser :: HasLogFunc m => AuthUserId -> UpdatedUser -> RIO m User
updateUser authUser updateUser = ...

getUser :: HasLogFunc m => AuthUserId -> RIO m User
getUser authUser = ...

解决方法

问题在于 throwIO err401 是一个单个 RIO 操作。但是当一个servant服务器有多个端点时,每个不同的处理程序都必须由:<|>组合子组成。

如果您的 API 有许多端点,那么为每个端点编写 401 返回处理程序很快就会变得烦人。幸运的是,servant-auth-server 似乎提供了一个 throwAll 辅助函数,可以为整个 API 自动构建错误返回处理程序。

编辑:正如 Ulrich 所指出的,throwAll 的问题在于它只适用于 MonadError 单子,而 RIO 不是 { {1}}。但是应该可以修改类型类以使其支持 MonadError

首先,一些导入和辅助数据类型:

RIO

这是主要的 {-# LANGUAGE UndecidableInstances,TypeOperators,FlexibleInstances,TypeFamilies,DataKinds,ImportQualifiedPost #-} module Main where import RIO (RIO) -- rio import RIO qualified import Data.Tagged (Tagged (..)) -- package tagged import Servant ((:<|>) (..),ServerError(..)) import Network.HTTP.Types -- package http-types import Network.Wai -- package wai import Data.ByteString.Char8 qualified as BS 类型类:

RIOThrowAll

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?