如何从servicestack swift客户端获取401错误?

时间:2016-02-22 03:37:47

标签: swift servicestack

首先是我们的代码

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。

1 个答案:

答案 0 :(得分:1)

这是Swift sendSynchronousRequest which sometimes returns a null response中的一个错误,因此无法确定服务器错误响应是什么。我已经为此问题in this commit添加了一个修复程序,它现在会抛出一个未知的错误而不是segfaulting但是由于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 
    }