如何在不发送请求的情况下拦截 Moya 请求并返回失败响应

Posted

技术标签:

【中文标题】如何在不发送请求的情况下拦截 Moya 请求并返回失败响应【英文标题】:How to intercept Moya request and return failure response without sending the request at all 【发布时间】:2019-10-22 11:13:09 【问题描述】:

我正在使用 Moya 库来处理网络层,并且我已经有一个自定义插件,可以将身份验证令牌添加到标头。

如果令牌尚不可用,我想做的是让这个插件取消请求并返回失败响应(或抛出错误)。

附:我扩展了协议TargetType 以添加额外的变量来指示目标是否需要身份验证,因此我需要访问这些数据以确定标头中是否需要身份验证令牌。

这是我的自定义插件的快照:

struct AuthTokenPlugin: PluginType 
    let tokenClosure:()->String?

    func prepare(_ request: URLRequest, target: TargetType) -> URLRequest 
        guard let target = target as? AuthorizebleTargetType, target.needsAuth else 
            return request
        

        guard let token = tokenClosure() else 
            // Here where a failure response will be triggered or an error should be thrown  
            return ......
        

        var request = request
        request.addValue( "Token " + token, forHTTPHeaderField:"Authorization")
        return request
    

P.S.2:抛出错误不是一个好的做法,而且这是不可能的,因为封闭函数“prepare(_:target:)”未声明为“抛出”。

【问题讨论】:

为什么抛出错误不是一个好习惯?您可能更喜欢返回Optional URLRequest 不是一个好习惯,因为它在逻辑上是响应的正常失败,而不是常规逻辑的异常(如 JSON 解析错误)。 Optional URLRequest 可能会解决这个问题,但它也是不可能的,因为它没有在 PluginType 协议中声明为可选 【参考方案1】:

我不认为我们可以使用protocol TargetType 来实现这样的逻辑,因为他的方法不返回 Bool 值并且没有抛出标记。

看看MoyaProvider init 参数。其中有一个requestClosure 参数。您可以复制粘贴并将此参数的默认实现替换为您自己的实现,这将检查Endpoint 的授权标头。

这个闭包的默认实现:

final class func defaultRequestMapping(for endpoint: Endpoint, closure: RequestResultClosure) 
        do 
            let urlRequest = try endpoint.urlRequest()
            closure(.success(urlRequest))
         catch MoyaError.requestMapping(let url) 
            closure(.failure(MoyaError.requestMapping(url)))
         catch MoyaError.parameterEncoding(let error) 
            closure(.failure(MoyaError.parameterEncoding(error)))
         catch 
            closure(.failure(MoyaError.underlying(error, nil)))
        
    

UPD 附上我的评论:

我建议检查Endpoint是否有带有“授权”键的标题,但它的值是空字符串,然后在requestClosure.failure的情况下调用closure参数

【讨论】:

感谢您的回复。但我的问题并不完整。据我了解,这个requestClosureEndpoint 对象而不是TargetType。但我需要TargetType 对象来确定标头中是否需要身份验证令牌。我用详细信息更新了我的问题。 您可以检查Endpont是否有带有“Authorization”键的标题,但它的值是空字符串,然后在requestClosure.failure的情况下调用closure参数 再次感谢。您能否编辑您的答案以包含此建议,以便其他人无需阅读 cmets 即可获得完整答案

以上是关于如何在不发送请求的情况下拦截 Moya 请求并返回失败响应的主要内容,如果未能解决你的问题,请参考以下文章

在 Moya 14 中记录响应和请求

iOS Swift moya框架发送数组作为请求参数(GET/POST)

如何在不丢失身份验证的情况下模拟Session.request?

如何在不使用 System.Net 类的情况下在 C# 中发送 HTTP 请求? [复制]

如何在不使用 HTML 表单的情况下以编程方式将 POST 请求发送到 JSF 页面?

Moya/Alamofire 请求变量问题