拦截401以获取Elm中的任何响应
我正在Elm中构建一个应用程序,其中大多数API调用都受到保护;i、 e.用户需要登录API调用才能工作。如果用户未登录,他们将收到拦截401以获取Elm中的任何响应,elm,Elm,我正在Elm中构建一个应用程序,其中大多数API调用都受到保护;i、 e.用户需要登录API调用才能工作。如果用户未登录,他们将收到401未经授权的响应。如果任何响应是401,我希望应用程序重定向到登录页面 目前,我只为单个API调用设置了此重定向。下面是代码的精简版本,让您了解如何进行设置: -- Util/Api.elm type alias Data data = { data : data } -- Resources/Expense.elm getExpenses :
401未经授权的响应。如果任何响应是401,我希望应用程序重定向到登录页面
目前,我只为单个API调用设置了此重定向。下面是代码的精简版本,让您了解如何进行设置:
-- Util/Api.elm
type alias Data data =
{ data : data
}
-- Resources/Expense.elm
getExpenses : (Progress (Api.Data (List Expense)) -> msg) -> Sub msg
getExpenses msg =
(dataDecoder expenseListDecoder)
|> Http.get expensesEndpoint
|> Progress.track expensesEndpoint msg
-- Main/Msg.elm
type Msg
= ExpenseListMsg ExpenseListMsg
| RedirectToLogin
-- Main/Update.elm
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
case msg of
ExpenseListMsg msg ->
ExpenseList.Update.update msg model
GoTo path ->
model ! [ Navigation.newUrl path ]
RedirectToLogin ->
model ! [ Navigation.load "path/to/login" ]
-- ExpenseList/Msg.elm
type ExpenseListMsg
= GetExpensesProgress (Progress (Api.Data (List Expense)))
| SetLoading
-- ExpenseList/Update.elm
update : ExpenseListMsg -> Model -> ( Model, Cmd Msg )
update msg model =
case msg of
SetLoading ->
{ model | expenses = setExpensesLoading model.expenses } ! []
GetExpensesProgress (Done { data }) ->
{ model | expenses = addExpenses model.expenses data } ! []
GetExpensesProgress (Fail (BadStatus { status })) ->
case status.code of
401 ->
model ! [ msgToCmd RedirectToLogin ]
_ ->
model ! []
GetExpensesProgress (Fail error) ->
model ! []
GetExpensesProgress progress ->
{ model | expenses = setExpensesLoading model.expenses } ! []
基本上,我想将逻辑从ExpenseList/Update.elm
移动到Main/Update.elm
的401
响应,这样我就可以将它用于我想要的任何请求
我尝试了很多方法,但是对于Elm的类型系统,没有一种方法是有效的。例如,我想做的一件事是尝试做一个嵌套模式匹配,在中间缺少特异性,例如:
-- Main/Update.elm
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
case msg of
ApiCall (messageType (msg (Fail (BadStatus { status })))) ->
case status of ->
. . .
. . .
我希望这样的东西能起作用,并且能匹配这样的消息:ApiCall(ExpenseListMsg(GetExpensesProgress(Fail(BadStatus)))
。不幸的是,它不是正确的Elm语法,所以我的代码没有编译
我如何编写一些东西来将API调用标记为受保护,并在Main.Update.Update
中捕获顶层的401
错误?当前,API调用由ExpenseList/Update
模块封装。这种封装使得Main
模块无法使用API调用结果。交互工作原理如下:Main->FeatureModule->API
由于API提供了确定应用程序是否应重定向到登录页面所需的信息,并且您希望Main
模块执行重定向,因此Main
模块需要访问API
。因此,需要进行封装。相反,您可以:
- 有一个API模块,它通过生成
任务
s来提供低级API功能。与生成Cmd
s不同,这允许调用方(如Main
模块)决定如何处理任务的结果,这可以通过将任务
转换为Cmd
并将其交给Elm运行时执行来获得
- 让
ExpenseList.Update
模块使用API模块创建任务
李>
在这种安排下:
Main
模块向功能模块发送高级命令,功能模块随后使用API模块生成低级指令,然后将这些指令提供给Main
模块李>
Main
模块不需要关心那些低级指令是什么,它只是将任务
转换为Cmd
并等待结果
- 当结果返回时,它是一种低级格式(例如成功/失败)。此时,
Main
模块可以跳入并处理401错误时的重定向。否则,它可以将结果传递给功能模块,以便处理结果
试试看