【问题标题】:How to get 401 error from servicestack swift client?如何从 servicestack swift 客户端获取 401 错误?
【发布时间】:2016-02-22 03:37:46
【问题描述】:

首先是我们的代码

let req = SignUp()
req.loginName = "abc@abc.com"
req.passWord = "xxx"

do{
    let resp = try client.put(req)   <---Where we had an error
} catch {
    //some error handling
    //.....
}

然后,当我们输入正确的信息时,一切都很好,但是当登录凭据错误时,我们原以为会收到带有正确错误消息的 401 错误,但我们没有。当我们追踪它试图找到它的起源时,我们已经将它追溯到 JsonServicClient.swift(从 Xcode 7.2 的 ServiceStack swift 插件生成),第 266 行。

public func send<T : JsonSerializable>(intoResponse:T, request:NSMutableURLRequest) throws -> T {
    var response:NSURLResponse? = nil

    var data = NSData()
    do {
        data = try NSURLConnection.sendSynchronousRequest(request, returningResponse: &response)

        var error:NSError? = NSError(domain: NSURLErrorDomain, code: NSURLErrorUnknown, userInfo: nil)
        if let dto = self.handleResponse(intoResponse, data: data, response: response!, error: &error) {
                                                                  //^^^error here, response is null/can't be null
            return dto
        }
        if let e = error {
            throw e
        }
        return T()
    } catch var ex as NSError? {
        if let e = self.handleResponse(intoResponse, data: data, response: response!, error: &ex) {
            return e
        }
        throw ex!
    }
}

那么问题来了,如何正确使用ServiceStack swift插件来得到401错误?当服务返回 400 时,一切正常。此问题仅在 servicestack 服务器 api 返回 401 时发生。按照设计,我们应该在用户身份验证失败时返回 401。

【问题讨论】:

  • 奇怪,标记行上的响应不应该是nil,但它应该在catch 块中失败。
  • @Sulthan 然而,这就是我们现在所见证的。我猜生成的 JsonServiceClient.swift 代码一定有问题。错误处理不起作用。
  • 错误处理程序中的代码显然是错误的。它还使用在 iOS 9 (sendSynchronousRequest) 上弃用的 API。生成的代码总是有点风险。
  • JsonServiceClient.swift 代码是从远程源拉进来的,不是生成的。仅生成客户端 DTO(由 ServiceStack 服务器生成并在本地提取)。 JsonServiceClient 的代码在 GH 上。 github.com/ServiceStack/ServiceStack.Swift/blob/master/dist/… 。与SignUp dto 关联的路由是否需要身份验证?你能显示相关的.NET服务代码吗?
  • @Layoric 对不起这个例子,注册真的不是一个好名字,想象我们正在处理登录,用户输入用户名和密码,应用程序将它用json发布到用servicestack编写的api。在 api 中,我们只是放置了一些标准验证,将密码与 db 中的哈希值进行比较等,当发生错误时,我们只是抛出一个错误。像这样: throw new AuthenticationException("password error something");

标签: swift servicestack


【解决方案1】:

这是 Swift 的 sendSynchronousRequest which sometimes returns a null response 中的一个错误,它导致无法确定服务器错误响应是什么。我已经为这个问题添加了一个修复in this commit,它现在将抛出一个未知错误而不是段错误,但由于 Swift 不返回 HTTP 响应,我们无法查询它以返回有关错误的更多信息,例如:

do {
    try client.post(request)
} catch let responseError as NSError {
    //Swift Bug: 401 returns an unitialized response so status is nil
    if let status:ResponseStatus = responseError.convertUserInfo() {
    }
}

要获取最新版本,您可以替换为最新的 JsonServiceClient.swift 或删除 JsonServiceClient.swift 并添加/删除将下载最新版本的新服务参考。

如果可以,您也可以改用不存在此问题的 Async API:

client.postAsync(request)
    .error { responseError in
        let status:ResponseStatus = responseError.convertUserInfo()!
        status.errorCode //= Unauthorized 
    }

【讨论】:

  • 那个catch 处理程序真的很奇怪,它也强制解开response,尽管大多数情况下response 会是nil。你确定这是正确的吗?
  • 如果 response = nil 是变化点,它永远不会达到强制展开。 catch 处理 Unknown 错误而不是 nil 并且它不会展开
  • 我不是在谈论更改,我的意思是原始的 catch 处理程序 catch var ex as NSError? { 在第一行展开 response!。这似乎不对。
  • 你试过了吗?它不是解开响应,而是处理抛出的 Unknown NSError 。听起来您对用于捕获 NSError 的 as 运算符感到困惑 - 这不是展开,而是捕获/处理可以转换为 NSError 的错误。
  • 谢谢两位。我们正在测试。这是结果。使用同步帖子时发生的错误消失了,但我们仍然无法收到 401 错误。当然这是一个 Swift 问题,因此仍在等待 Apple 处理它(我们是否通知了 Apple?)我们正在测试 postasync 以查看是否可以使用它。一个请求是我们是否可以被引导到一个页面,在那里我们可以找到这些方法的所有正确用法。像 postasync 一样,现在我们通过您的测试用例学习如何使用它...
猜你喜欢
  • 1970-01-01
  • 2018-08-06
  • 2018-09-23
  • 1970-01-01
  • 1970-01-01
  • 2019-12-11
  • 2019-09-29
  • 2017-09-13
  • 2016-03-15
相关资源
最近更新 更多