2

我的 iOS 应用程序中有以下 Swift 代码:

session?.dataTaskWithRequest(urlRequest, completionHandler: { (data, response, error) -> Void in
    if let httpResponse = response as? NSHTTPURLResponse {
        var dataString:String?
        if data != nil {
            // Print the response as a string
            dataString = String(data: data!, encoding: NSUTF8StringEncoding)!
            if RequestManager.verbose { print("Response data: \(dataString)") }
        } else {
            if RequestManager.verbose { print("Response data: \(response?.description)") }
        }
        //[...]

当对 Web 服务 API 的调用成功时,这一切正常:response!.statusCode设置正确并且data传递到完成处理程序中的内容可以从 JSON 解析为有用的对象。

但是,当服务器响应是错误时,例如 500,则data为零字节,我只能看到标头信息,而不是响应的正文。

这是一个示例响应,使用代理应用程序Charles从模拟器中收集:

HTTP/1.1 500 内部服务器错误
传输编码:分块
服务器:Microsoft-IIS/8.0
X-Powered-By:ASP.NET
Set-Cookie:ARRAffinity=000000000000000000008888888888888888888888888aaaaaaaaaaaaaaaa;Path=/;Domain=blah-testing.azurewebsites.net
日期: 2016 年 7 月 21 日星期四 05:57:44 GMT

{"ExceptionType":"Exception","Message":"Not on your Nelly","StackTrace":" at Blah.Controllers.CustomersController.Get() in D:\Users\timregan\Source\Repos\ServerSideCode\Blah \ApiControllers\CustomersController.cs:第 37 行\r\n 在 lambda_method(Closure , Object , Object[] )\r\n 在 Microsoft.AspNetCore.Mvc.Internal.ObjectMethodExecutor.Execute(Object target, Object[] 参数)\ r\n 在 Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.d__28.MoveNext()\r\n--- 从先前引发异常的位置结束堆栈跟踪 ---\r\n 在 System.Runtime.ExceptionServices .ExceptionDispatchInfo.Throw()\r\n 在 Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.d__18.MoveNext()\r\n--- 堆栈跟踪从上一个引发异常的位置结束 ---\r\ n 在系统。Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务任务)\r\n 在 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务任务)\r\n 在 System.Runtime.CompilerServices.TaskAwaiter.GetResult()\r\n 在Microsoft.AspNetCore.Builder.RouterMiddleware.d__4.MoveNext()\r\n--- 从先前引发异常的位置结束堆栈跟踪 ---\r\n 在 System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task任务)\r\n 在 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务任务)\r\n 在 System.Runtime.CompilerServices.TaskAwaiter.GetResult()\r\n 在 Microsoft.AspNetCore.Authentication.AuthenticationMiddlewareHandleNonSuccessAndDebuggerNotification(Task task)\r\n 在 System.Runtime.CompilerServices.TaskAwaiter.GetResult()\r\n 在 Microsoft.AspNetCore.Builder.RouterMiddleware.d__4.MoveNext()\r\n--- 堆栈跟踪结束从先前引发异常的位置 ---\r\n 在 System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务任务)\r\n 在 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务任务)\r\n在 System.Runtime.CompilerServices.TaskAwaiter.GetResult()\r\n 在 Microsoft.AspNetCore.Authentication.AuthenticationMiddlewareHandleNonSuccessAndDebuggerNotification(Task task)\r\n 在 System.Runtime.CompilerServices.TaskAwaiter.GetResult()\r\n 在 Microsoft.AspNetCore.Builder.RouterMiddleware.d__4.MoveNext()\r\n--- 堆栈跟踪结束从先前引发异常的位置 ---\r\n 在 System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务任务)\r\n 在 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务任务)\r\n在 System.Runtime.CompilerServices.TaskAwaiter.GetResult()\r\n 在 Microsoft.AspNetCore.Authentication.AuthenticationMiddlewareTaskAwaiter.ThrowForNonSuccess(任务任务)\r\n 在 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务任务)\r\n 在 System.Runtime.CompilerServices.TaskAwaiter.GetResult()\r\n 在 Microsoft.AspNetCore。 Authentication.AuthenticationMiddlewareTaskAwaiter.ThrowForNonSuccess(任务任务)\r\n 在 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务任务)\r\n 在 System.Runtime.CompilerServices.TaskAwaiter.GetResult()\r\n 在 Microsoft.AspNetCore。 Authentication.AuthenticationMiddleware1.<Invoke>d__18.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware1.d__18.MoveNext()\r\n--- 从先前引发异常的位置结束堆栈跟踪 ---\r\n 在 System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务任务)\r\n在 System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务任务)\r\n 在 Blah.Startup.<>c.<b__6_0>d.MoveNext() 在 D:\Users\timregan\Source\Repos\ServerSideCode\Blah \Startup.cs:第 59 行","状态代码":500}

但在 Xcode 中,相同的响应却少得多。标头元素都在NSHTTPURLResponse对象中,但完成处理程序的其他参数dataTaskWithRequest什么都没有:data零字节和erroris nil。带有服务器错误堆栈跟踪的响应正文到哪里去了?如何在 Swift 中访问它?

4

1 回答 1

1

IIRC,默认情况下, NSURLSession 在获得非 200 标头后停止请求数据,因此它不会浪费时间下载您可能不需要的正文数据。

如果您想每次都实际检索正文数据:

  • 实现URLSession:dataTask:didReceiveResponse:completionHandler:委托方法并使其始终返回NSURLSessionResponseAllow
  • 实现该URLSession:task:willPerformHTTPRedirection:newRequest:completionHandler:方法并使其完成处理程序始终NULL作为新请求传递,以便不会遵循重定向。

认为这应该足够了,除非我在某处忘记了另一个委托方法。

于 2016-07-25T04:08:01.520 回答