{"action":"created","comment":{"url":"https://api.github.com/repos/Alamofire/Alamofire/pulls/comments/76535682","id":76535682,"diff_hunk":"@@ -24,428 +24,540 @@\n \n import Foundation\n \n-/// `AFError` is the error type returned by the Alamofire framework. It encompasses several\n+/// `AFError` is the error type returned by the Alamofire framework. It encompasses a few\n /// different types of errors, each with their own associated reasons.\n ///\n-/// - multipartEncodingFailed:          Returned by the multipart body data APIs. Contains a `MultipartEncodingFailureReason`.\n-/// - inputStreamReadFailed:            <#inputStreamReadFailed description#>\n-/// - outputStreamWriteFailed:          <#outputStreamWriteFailed description#>\n-/// - responseValidationFailed:         <#responseValidationFailed description#>\n-/// - responseSerializationFailed:      <#responseSerializationFailed description#>\n+/// `.multipartEncodingFailed` errors are returned when some step in the multipart encoding process fails.\n+///\n+/// `.responseValidationFailed` errors are returned when a `validate()` call fails.\n+///\n+/// `.responseSerializationFailed` errors are returned when a response serializer encounters an error in the serialization process.\n public enum AFError: Error {\n-    \n+\n     public enum MultipartEncodingFailureReason {\n-        case notAFile(at: URL)\n-        case failedToExtractFilename(for: URL)\n-        case fileNotReachable(at: URL)\n-        case isDirectory(at: URL)\n-        case failedToFetchAttributes(from: URL)\n-        case failedToCreateInputStream(from: URL)\n-    }\n-    \n-    /// `OutputStreamFailureReason` is the reason returned for an `AFError.multipartEncodingFailed` error.\n-    ///\n-    /// - writeFailed:          <#writeFailed description#>\n-    /// - failedToCreateStream: <#failedToCreateStream description#>\n-    /// - fileAlreadyExists:    <#fileAlreadyExists description#>\n-    /// - invalidFile:          <#invalidFile description#>\n-    public enum OutputStreamFailureReason {\n-        case writeFailed(to: OutputStream)\n-        case failedToCreateStream(at: URL)\n-        case fileAlreadyExists(at: URL)\n-        case invalidFile(at: URL)\n-    }\n-    \n-    public enum SerializationFailureReason {\n-        case inputDataNil\n-        case inputDataNilOrZeroLength\n-        case invalidStringEncoding(String.Encoding)\n+        case bodyPartURLInvalid(at: URL)\n+        case bodyPartFilenameInvalid(in: URL)\n+        case bodyPartFileNotReachable(at: URL)\n+        case bodyPartFileNotReachableWithError(url: URL, error: Error)\n+        case bodyPartFileIsDirectory(at: URL)\n+        case bodyPartFileSizeNotAvailable(at: URL)\n+        case bodyPartFileSizeQueryFailedWithError(url: URL, error: Error)\n+        case bodyPartInputStreamCreationFailed(for: URL)\n+\n+        case outputStreamCreationFailed(for: URL)\n+        case outputStreamFileAlreadyExists(at: URL)\n+        case outputStreamURLInvalid(url: URL)\n+        case outputStreamWriteFailed(error: Error)\n+\n+        case inputStreamReadFailed(error: Error)\n     }\n-    \n+\n     public enum ValidationFailureReason {\n-        case contentTypeMismatch(acceptable: [String], actual: String)\n-        case contentTypeMissingAndNotWildcard\n+        case missingContentType(acceptable: [String])\n+        case unacceptableContentType(acceptable: [String], response: String)\n         case unacceptableStatusCode(code: Int)\n     }\n-    \n+\n+    public enum SerializationFailureReason {\n+        case inputDataNil\n+        case inputDataNilOrZeroLength\n+        case stringSerializationFailed(encoding: String.Encoding)\n+        case jsonSerializationFailed(error: Error)\n+        case propertyListSerializationFailed(error: Error)\n+    }\n+\n     case multipartEncodingFailed(reason: MultipartEncodingFailureReason)\n-    case inputStreamReadFailed(inputStream: InputStream)\n-    case outputStreamWriteFailed(reason: OutputStreamFailureReason)\n     case responseValidationFailed(reason: ValidationFailureReason)\n     case responseSerializationFailed(reason: SerializationFailureReason)\n+\n }\n \n // MARK: Error Booleans\n \n public extension AFError {\n-    \n-    // MARK: Multipart Encoding\n-    \n-    /// Returns whether or not the AFError is a multipart encoding error. When this property is true,\n-    /// the `url` property will contain the associated `URL`.\n-    var isMultipartEncodingError: Bool {\n+\n+    /// Returns whether the AFError is a multipart encoding error.\n+    /// When true, the `url` and `underlyingError` properties will contain the associated values.\n+    public var isMultipartEncodingError: Bool {\n         if case .multipartEncodingFailed = self { return true }\n         return false\n     }\n-    \n-    var isMultipartNotAFileError: Bool {\n-        guard case let .multipartEncodingFailed(reason) = self else { return false }\n-        return reason.isNotAFile\n-    }\n-    \n-    var isMultipartFailedToExtractFilenameError: Bool {\n-        guard case let .multipartEncodingFailed(reason) = self else { return false }\n-        return reason.isFailedToExtractFilename\n-    }\n-    \n-    var isMultipartFileNotReachableError: Bool {\n-        guard case let .multipartEncodingFailed(reason) = self else { return false }\n-        return reason.isFileNotReachable\n-    }\n-    \n-    var isMultipartIsADirectoryError: Bool {\n-        guard case let .multipartEncodingFailed(reason) = self else { return false }\n-        return reason.isADirectory\n-    }\n-    \n-    var isMultipartFailedToFetchAttributesError: Bool {\n-        guard case let .multipartEncodingFailed(reason) = self else { return false }\n-        return reason.isFailedToFetchAttributes\n-    }\n-    \n-    var isMultipartFailedToCreateInputStreamError: Bool {\n-        guard case let .multipartEncodingFailed(reason) = self else { return false }\n-        return reason.isFailedToCreateInputStream\n-    }\n-    \n-    // MARK: InputStream\n-    \n-    /// Returns whether or not the `AFError` is a `.inputStreamReadFailed` error. When this property is true the `inputStream` property will contain the associated `InputStream`.\n-    var isInputStreamReadError: Bool {\n-        if case .inputStreamReadFailed = self { return true }\n+\n+    /// Returns whether the `AFError` is a response validation error.\n+    /// When true, the `acceptableContentTypes`, `responseContentType`, and `responseCode` properties will contain the associated values.\n+    public var isResponseValidationError: Bool {\n+        if case .responseValidationFailed = self { return true }\n         return false\n     }\n-    \n-    // MARK: OutputStream\n-    \n-    var isOutputStreamWriteError: Bool {\n-        if case .outputStreamWriteFailed = self { return true }\n+\n+    /// Returns whether the `AFError` is a response serialization error.\n+    /// When true, the `failedStringEncoding` and `underlyingError` properties will contain the associated values.\n+    public var isResponseSerializationError: Bool {\n+        if case .responseSerializationFailed = self { return true }\n         return false\n     }\n-    \n-    var isOutputStreamWriteFailedError: Bool {\n-        guard case let .outputStreamWriteFailed(reason) = self else { return false }\n-        return reason.isWriteFailed\n+\n+}\n+\n+extension AFError {\n+\n+    var isBodyPartURLInvalid: Bool {\n+        if case let .multipartEncodingFailed(reason) = self, reason.isBodyPartURLInvalid { return true }\n+        return false\n     }\n-    \n-    var isOutputStreamFailedToCreateStream: Bool {\n-        guard case let .outputStreamWriteFailed(reason) = self else { return false }\n-        return reason.isFailedToCreateStream\n+\n+    var isBodyPartFilenameInvalid: Bool {\n+        if case let .multipartEncodingFailed(reason) = self, reason.isBodyPartFilenameInvalid { return true }\n+        return false\n+    }\n+\n+    var isBodyPartFileNotReachable: Bool {\n+        if case let .multipartEncodingFailed(reason) = self, reason.isBodyPartFileNotReachable { return true }\n+        return false\n+    }\n+\n+    var isBodyPartFileNotReachableWithError: Bool {\n+        if case let .multipartEncodingFailed(reason) = self, reason.isBodyPartFileNotReachableWithError { return true }\n+        return false\n+    }\n+\n+    var isBodyPartFileIsDirectory: Bool {\n+        if case let .multipartEncodingFailed(reason) = self, reason.isBodyPartFileIsDirectory { return true }\n+        return false\n+    }\n+\n+    var isBodyPartFileSizeNotAvailable: Bool {\n+        if case let .multipartEncodingFailed(reason) = self, reason.isBodyPartFileSizeNotAvailable { return true }\n+        return false\n     }\n-    \n+\n+    var isBodyPartFileSizeQueryFailedWithError: Bool {\n+        if case let .multipartEncodingFailed(reason) = self, reason.isBodyPartFileSizeQueryFailedWithError { return true }\n+        return false\n+    }\n+\n+    var isBodyPartInputStreamCreationFailed: Bool {\n+        if case let .multipartEncodingFailed(reason) = self, reason.isBodyPartInputStreamCreationFailed { return true }\n+        return false\n+    }\n+\n+    var isOutputStreamCreationFailed: Bool {\n+        if case let .multipartEncodingFailed(reason) = self, reason.isOutputStreamCreationFailed { return true }\n+        return false\n+    }\n+\n     var isOutputStreamFileAlreadyExists: Bool {\n-        guard case let .outputStreamWriteFailed(reason) = self else { return false }\n-        return reason.isFileAlreadyExists\n-    }\n-    \n-    var isOutputStreamInvalidFile: Bool {\n-        guard case let .outputStreamWriteFailed(reason) = self else { return false }\n-        return reason.isInvalidFile\n-    }\n-    \n-    // MARK: Response Validation\n-    \n-    var isResponseValidationError: Bool {\n-        if case .responseValidationFailed = self { return true }\n+        if case let .multipartEncodingFailed(reason) = self, reason.isOutputStreamFileAlreadyExists { return true }\n+        return false\n+    }\n+\n+    var isOutputStreamURLInvalid: Bool {\n+        if case let .multipartEncodingFailed(reason) = self, reason.isOutputStreamURLInvalid { return true }\n         return false\n     }\n-    \n-    var isResponseValidationContentTypeMismatchError: Bool {\n-        guard case let .responseValidationFailed(reason) = self else { return false }\n-        return reason.isContentTypeMismatch\n+\n+    var isOutputStreamWriteFailed: Bool {\n+        if case let .multipartEncodingFailed(reason) = self, reason.isOutputStreamWriteFailed { return true }\n+        return false\n     }\n-    \n-    var isResponseValidationContentTypeMissingAndNotWildCardError: Bool {\n-        guard case let .responseValidationFailed(reason) = self else { return false }\n-        return reason.isContentTypeMissingAndNotWildcard\n+\n+    var isInputStreamReadFailed: Bool {\n+        if case let .multipartEncodingFailed(reason) = self, reason.isInputStreamReadFailed { return true }\n+        return false\n     }\n-    \n-    var isResponseValidationUnacceptableStatusCodeError: Bool {\n-        guard case let .responseValidationFailed(reason) = self else { return false }\n-        return reason.isUnacceptableStatusCode\n+\n+    // SerializationFailureReason\n+\n+    var isInputDataNil: Bool {\n+        if case let .responseSerializationFailed(reason) = self, reason.isInputDataNil { return true }\n+        return false\n     }\n-    \n-    // MARK: Response Serialization\n-    \n-    var isResponseSerializationError: Bool {\n-        if case .responseSerializationFailed = self { return true }\n+\n+    var isInputDataNilOrZeroLength: Bool {\n+        if case let .responseSerializationFailed(reason) = self, reason.isInputDataNilOrZeroLength { return true }\n         return false\n     }\n-    \n-    var isResponseSerializationInputDataNilError: Bool {\n-        guard case let .responseSerializationFailed(reason) = self else { return false }\n-        return reason.isInputDataNil\n+\n+    var isStringSerializationFailed: Bool {\n+        if case let .responseSerializationFailed(reason) = self, reason.isStringSerializationFailed { return true }\n+        return false\n     }\n-    \n-    var isResponseSerializationInputDataNilOrZeroLengthError: Bool {\n-        guard case let .responseSerializationFailed(reason) = self else { return false }\n-        return reason.isInputDataNilOrZeroLength\n+\n+    var isJSONSerializationFailed: Bool {\n+        if case let .responseSerializationFailed(reason) = self, reason.isJSONSerializationFailed { return true }\n+        return false\n     }\n-    \n-    var isResponseSerializationInvalidStringEncodingError: Bool {\n-        guard case let .responseSerializationFailed(reason) = self else { return false }\n-        return reason.isInvalidStringEncoding\n+\n+    var isPropertyListSerializationFailed: Bool {\n+        if case let .responseSerializationFailed(reason) = self, reason.isPropertyListSerializationFailed { return true }\n+        return false\n+    }\n+\n+    // ValidationFailureReason\n+\n+    var isMissingContentType: Bool {\n+        if case let .responseValidationFailed(reason) = self, reason.isMissingContentType { return true }\n+        return false\n+    }\n+\n+    var isUnacceptableContentType: Bool {\n+        if case let .responseValidationFailed(reason) = self, reason.isUnacceptableContentType { return true }\n+        return false\n+    }\n+\n+    var isUnacceptableStatusCode: Bool {\n+        if case let .responseValidationFailed(reason) = self, reason.isUnacceptableStatusCode { return true }\n+        return false\n     }\n \n }\n \n extension AFError.MultipartEncodingFailureReason {\n-    \n-    var isNotAFile: Bool {\n-        if case .notAFile = self { return true }\n+\n+    var isBodyPartURLInvalid: Bool {\n+        if case .bodyPartURLInvalid = self { return true }\n         return false\n     }\n-    \n-    var isFailedToExtractFilename: Bool {\n-        if case .failedToExtractFilename = self { return true }\n+\n+    var isBodyPartFilenameInvalid: Bool {\n+        if case .bodyPartFilenameInvalid = self { return true }\n         return false\n     }\n-    \n-    var isFileNotReachable: Bool {\n-        if case .fileNotReachable = self { return true }\n+\n+    var isBodyPartFileNotReachable: Bool {\n+        if case .bodyPartFileNotReachable = self { return true }\n         return false\n     }\n-    \n-    var isADirectory: Bool {\n-        if case .isDirectory = self { return true }\n+\n+    var isBodyPartFileNotReachableWithError: Bool {\n+        if case .bodyPartFileNotReachableWithError = self { return true }\n         return false\n     }\n-    \n-    var isFailedToFetchAttributes: Bool {\n-        if case .failedToFetchAttributes = self { return true }\n+\n+    var isBodyPartFileIsDirectory: Bool {\n+        if case .bodyPartFileIsDirectory = self { return true }\n         return false\n     }\n-    \n-    var isFailedToCreateInputStream: Bool {\n-        if case .failedToCreateInputStream = self { return true }\n+\n+    var isBodyPartFileSizeNotAvailable: Bool {\n+        if case .bodyPartFileSizeNotAvailable = self { return true }\n         return false\n     }\n-    \n-}\n \n-extension AFError.OutputStreamFailureReason {\n-    \n-    var isWriteFailed: Bool {\n-        if case .writeFailed = self { return true }\n+    var isBodyPartFileSizeQueryFailedWithError: Bool {\n+        if case .bodyPartFileSizeQueryFailedWithError = self { return true }\n         return false\n     }\n-    \n-    var isFailedToCreateStream: Bool {\n-        if case .failedToCreateStream = self { return true }\n+\n+    var isBodyPartInputStreamCreationFailed: Bool {\n+        if case .bodyPartInputStreamCreationFailed = self { return true }\n         return false\n     }\n-    \n-    var isFileAlreadyExists: Bool {\n-        if case .fileAlreadyExists = self { return true }\n+\n+    var isOutputStreamCreationFailed: Bool {\n+        if case .outputStreamCreationFailed = self { return true }\n         return false\n     }\n-    \n-    var isInvalidFile: Bool {\n-        if case .invalidFile = self { return true }\n+\n+    var isOutputStreamFileAlreadyExists: Bool {\n+        if case .outputStreamFileAlreadyExists = self { return true }\n         return false\n     }\n-    \n-}\n \n-extension AFError.ValidationFailureReason {\n-    \n-    var isContentTypeMismatch: Bool {\n-        if case .contentTypeMismatch = self { return true }\n+    var isOutputStreamURLInvalid: Bool {\n+        if case .outputStreamURLInvalid = self { return true }\n         return false\n     }\n-    \n-    var isContentTypeMissingAndNotWildcard: Bool {\n-        if case .contentTypeMismatch = self { return true }\n+\n+    var isOutputStreamWriteFailed: Bool {\n+        if case .outputStreamWriteFailed = self { return true }\n         return false\n     }\n-    \n-    var isUnacceptableStatusCode: Bool {\n-        if case .contentTypeMismatch = self { return true }\n+\n+    var isInputStreamReadFailed: Bool {\n+        if case .inputStreamReadFailed = self { return true }\n         return false\n     }\n-    \n+\n }\n \n extension AFError.SerializationFailureReason {\n-    \n+\n     var isInputDataNil: Bool {\n         if case .inputDataNil = self { return true }\n         return false\n     }\n-    \n+\n     var isInputDataNilOrZeroLength: Bool {\n         if case .inputDataNilOrZeroLength = self { return true }\n         return false\n     }\n-    \n-    var isInvalidStringEncoding: Bool {\n-        if case .invalidStringEncoding = self { return true }\n+\n+    var isStringSerializationFailed: Bool {\n+        if case .stringSerializationFailed = self { return true }\n+        return false\n+    }\n+\n+    var isJSONSerializationFailed: Bool {\n+        if case .jsonSerializationFailed = self { return true }\n+        return false\n+    }\n+\n+    var isPropertyListSerializationFailed: Bool {\n+        if case .propertyListSerializationFailed = self { return true }\n+        return false\n+    }\n+\n+}\n+\n+extension AFError.ValidationFailureReason {\n+\n+    var isMissingContentType: Bool {\n+        if case .missingContentType = self { return true }\n         return false\n     }\n-    \n+\n+    var isUnacceptableContentType: Bool {\n+        if case .unacceptableContentType = self { return true }\n+        return false\n+    }\n+\n+    var isUnacceptableStatusCode: Bool {\n+        if case .unacceptableStatusCode = self { return true }\n+        return false\n+    }\n+\n }\n \n+// MARK: Convenience Properties\n \n-// MARK: Associated Value Properties\n+public extension AFError {\n \n-extension AFError {\n-    \n-    /// The `URL` associated with all `.multipartEncodingFailed` reasons and some `.outputStreamWriteFailed` reasons. `nil` otherwise.\n-    var url: URL? {\n+    /// The `URL` associated with the error.\n+    public var url: URL? {\n         switch self {\n-        case let .multipartEncodingFailed(reason):\n-            return reason.url\n-        case let .outputStreamWriteFailed(reason):\n+        case .multipartEncodingFailed(let reason):\n             return reason.url\n         default:\n             return nil\n         }\n     }\n-    \n-    /// The `InputStream` associated with the `.inputStreamReadFailed` error. `nil` otherwise.\n-    var inputStream: InputStream? {\n-        guard case let .inputStreamReadFailed(inputStream) = self else { return nil }\n-        \n-        return inputStream\n-    }\n-    \n-    /// The `OutputStream` associated with the `.outputStreamWriteFailed` error. `nil` otherwise.\n-    var outputStream: OutputStream? {\n-        guard case let .outputStreamWriteFailed(reason) = self else { return nil }\n-        \n-        return reason.outputStream\n-    }\n-    \n-    /// The acceptable content types associated with a `.responseValidationFailed` error, if it was a `Content-Type` validation that failed. `nil` otherwise.\n-    var acceptableContentTypes: [String]? {\n-        guard case let .responseValidationFailed(reason) = self else { return nil }\n-        \n-        return reason.acceptableContentTypes\n-    }\n-    \n-    /// The actual content type recieved from the request associated with a `.responseValidationFailed` error, if it was a `Content-Type` validation that failed. `nil` otherwise.\n-    var actualContentType: String? {\n-        guard case let .responseValidationFailed(reason) = self else { return nil }\n-        \n-        return reason.actualContentType\n-    }\n-    \n-    /// The status code associated with a `.responseValidationFailed` error when it was a response code validation that failed. `nil` otherwise.\n-    var statusCode: Int? {\n-        guard case let .responseValidationFailed(reason) = self else { return nil }\n-        \n-        return reason.statusCode\n-    }\n-    \n-    /// The `String.Encoding` associated with the `.invalidStringEncoding` reason of the `.responseValidationFailed` error. `nil` otherwise.\n-    var stringEncoding: String.Encoding? {\n-        guard case let .responseSerializationFailed(reason) = self else { return nil }\n-        \n-        return reason.stringEncoding\n-    }\n-    \n-}\n \n-extension AFError.MultipartEncodingFailureReason {\n-    \n-    var url: URL {\n+    /// The `Error` returned by a system framework associated with a `.multipartEncodingFailed` or `.responseSerializationFailed` error.\n+    public var underlyingError: Error? {\n         switch self {\n-        case .notAFile(let url), .failedToExtractFilename(let url), .fileNotReachable(let url),\n-             .isDirectory(let url), .failedToFetchAttributes(let url), .failedToCreateInputStream(let url):\n-            return url\n+        case .multipartEncodingFailed(let reason):\n+            return reason.underlyingError\n+        case .responseSerializationFailed(let reason):\n+            return reason.underlyingError\n+        default:\n+            return nil\n         }\n     }\n-    \n+\n+    /// The acceptable `Content-Type`s of a `.responseValidationFailed` error.\n+    public var acceptableContentTypes: [String]? {\n+        switch self {\n+        case .responseValidationFailed(let reason):\n+            return reason.acceptableContentTypes\n+        default:\n+            return nil\n+        }\n+    }\n+\n+    /// The response `Content-Type` of a `.responseValidationFailed` error.\n+    public var responseContentType: String? {\n+        switch self {\n+        case .responseValidationFailed(let reason):\n+            return reason.responseContentType\n+        default:\n+            return nil\n+        }\n+    }\n+\n+    /// The response code of a `.responseValidationFailed` error.\n+    public var responseCode: Int? {\n+        switch self {\n+        case .responseValidationFailed(let reason):\n+            return reason.responseCode\n+        default:\n+            return nil\n+        }\n+    }\n+\n+    /// The `String.Encoding` associated with a failed `.stringResponse()` call.\n+    public var failedStringEncoding: String.Encoding? {\n+        switch self {\n+        case .responseSerializationFailed(let reason):\n+            return reason.failedStringEncoding\n+        default:\n+            return nil\n+        }\n+    }\n+\n }\n \n-extension AFError.OutputStreamFailureReason {\n-    \n+extension AFError.MultipartEncodingFailureReason {\n+\n     var url: URL? {\n         switch self {\n-        case .failedToCreateStream(let url), .fileAlreadyExists(let url), .invalidFile(let url):\n+        case .bodyPartURLInvalid(let url), .bodyPartFilenameInvalid(let url), .bodyPartFileNotReachable(let url),\n+             .bodyPartFileIsDirectory(let url), .bodyPartFileSizeNotAvailable(let url), .bodyPartInputStreamCreationFailed(let url),\n+             .outputStreamCreationFailed(let url), .outputStreamFileAlreadyExists(let url), .outputStreamURLInvalid(let url),\n+             .bodyPartFileNotReachableWithError(let url, _), .bodyPartFileSizeQueryFailedWithError(let url, _):\n             return url\n         default:\n             return nil\n         }\n     }\n-    \n-    var outputStream: OutputStream? {\n-        guard case let .writeFailed(outputStream) = self else { return nil }\n-        \n-        return outputStream\n+\n+    var underlyingError: Error? {\n+        switch self{\n+        case .bodyPartFileNotReachableWithError(_, let error), .bodyPartFileSizeQueryFailedWithError(_, let error),\n+             .outputStreamWriteFailed(let error), .inputStreamReadFailed(let error):\n+            return error\n+        default:\n+            return nil\n+        }\n     }\n-    \n+\n }\n \n extension AFError.ValidationFailureReason {\n-    \n+","path":"Source/Error.swift","position":null,"original_position":661,"commit_id":"60dc4ec0525ebe034787ada405bdfe3e6d644507","original_commit_id":"60dc4ec0525ebe034787ada405bdfe3e6d644507","user":{"login":"cnoon","id":169110,"avatar_url":"https://avatars.githubusercontent.com/u/169110?v=3","gravatar_id":"","url":"https://api.github.com/users/cnoon","html_url":"https://github.com/cnoon","followers_url":"https://api.github.com/users/cnoon/followers","following_url":"https://api.github.com/users/cnoon/following{/other_user}","gists_url":"https://api.github.com/users/cnoon/gists{/gist_id}","starred_url":"https://api.github.com/users/cnoon/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/cnoon/subscriptions","organizations_url":"https://api.github.com/users/cnoon/orgs","repos_url":"https://api.github.com/users/cnoon/repos","events_url":"https://api.github.com/users/cnoon/events{/privacy}","received_events_url":"https://api.github.com/users/cnoon/received_events","type":"User","site_admin":false},"body":"Extra newline.","created_at":"2016-08-28T17:09:14Z","updated_at":"2016-08-28T17:09:14Z","html_url":"https://github.com/Alamofire/Alamofire/pull/1419#discussion_r76535682","pull_request_url":"https://api.github.com/repos/Alamofire/Alamofire/pulls/1419","_links":{"self":{"href":"https://api.github.com/repos/Alamofire/Alamofire/pulls/comments/76535682"},"html":{"href":"https://github.com/Alamofire/Alamofire/pull/1419#discussion_r76535682"},"pull_request":{"href":"https://api.github.com/repos/Alamofire/Alamofire/pulls/1419"}}},"pull_request":{"url":"https://api.github.com/repos/Alamofire/Alamofire/pulls/1419","id":82142656,"html_url":"https://github.com/Alamofire/Alamofire/pull/1419","diff_url":"https://github.com/Alamofire/Alamofire/pull/1419.diff","patch_url":"https://github.com/Alamofire/Alamofire/pull/1419.patch","issue_url":"https://api.github.com/repos/Alamofire/Alamofire/issues/1419","number":1419,"state":"open","locked":false,"title":"WIP: New Error Handling","user":{"login":"jshier","id":51020,"avatar_url":"https://avatars.githubusercontent.com/u/51020?v=3","gravatar_id":"","url":"https://api.github.com/users/jshier","html_url":"https://github.com/jshier","followers_url":"https://api.github.com/users/jshier/followers","following_url":"https://api.github.com/users/jshier/following{/other_user}","gists_url":"https://api.github.com/users/jshier/gists{/gist_id}","starred_url":"https://api.github.com/users/jshier/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jshier/subscriptions","organizations_url":"https://api.github.com/users/jshier/orgs","repos_url":"https://api.github.com/users/jshier/repos","events_url":"https://api.github.com/users/jshier/events{/privacy}","received_events_url":"https://api.github.com/users/jshier/received_events","type":"User","site_admin":false},"body":"This PR refactors Alamofire's error handling to be based around a new `AFError` type rather than `NSError`, as Swift 3 has pushed the system frameworks and consumers toward using `Error` for everything. \r\n\r\n`AFError` consists of a few base cases with reason types for each. Convenience booleans and other properties have been added to make interacting with type easier in end use scenarios.\r\n\r\nThis PR is a works in progress as the inline and separate documentation still needs to be completed and the tests need to be updated for the new error type.","created_at":"2016-08-22T07:03:16Z","updated_at":"2016-08-28T17:09:14Z","closed_at":null,"merged_at":null,"merge_commit_sha":"c2b535ff66f25801ef371c0ab81612d124c46eea","assignee":null,"assignees":[],"milestone":null,"commits_url":"https://api.github.com/repos/Alamofire/Alamofire/pulls/1419/commits","review_comments_url":"https://api.github.com/repos/Alamofire/Alamofire/pulls/1419/comments","review_comment_url":"https://api.github.com/repos/Alamofire/Alamofire/pulls/comments{/number}","comments_url":"https://api.github.com/repos/Alamofire/Alamofire/issues/1419/comments","statuses_url":"https://api.github.com/repos/Alamofire/Alamofire/statuses/60dc4ec0525ebe034787ada405bdfe3e6d644507","head":{"label":"Alamofire:new-error-handling","ref":"new-error-handling","sha":"60dc4ec0525ebe034787ada405bdfe3e6d644507","user":{"login":"Alamofire","id":7774181,"avatar_url":"https://avatars.githubusercontent.com/u/7774181?v=3","gravatar_id":"","url":"https://api.github.com/users/Alamofire","html_url":"https://github.com/Alamofire","followers_url":"https://api.github.com/users/Alamofire/followers","following_url":"https://api.github.com/users/Alamofire/following{/other_user}","gists_url":"https://api.github.com/users/Alamofire/gists{/gist_id}","starred_url":"https://api.github.com/users/Alamofire/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Alamofire/subscriptions","organizations_url":"https://api.github.com/users/Alamofire/orgs","repos_url":"https://api.github.com/users/Alamofire/repos","events_url":"https://api.github.com/users/Alamofire/events{/privacy}","received_events_url":"https://api.github.com/users/Alamofire/received_events","type":"Organization","site_admin":false},"repo":{"id":22458259,"name":"Alamofire","full_name":"Alamofire/Alamofire","owner":{"login":"Alamofire","id":7774181,"avatar_url":"https://avatars.githubusercontent.com/u/7774181?v=3","gravatar_id":"","url":"https://api.github.com/users/Alamofire","html_url":"https://github.com/Alamofire","followers_url":"https://api.github.com/users/Alamofire/followers","following_url":"https://api.github.com/users/Alamofire/following{/other_user}","gists_url":"https://api.github.com/users/Alamofire/gists{/gist_id}","starred_url":"https://api.github.com/users/Alamofire/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Alamofire/subscriptions","organizations_url":"https://api.github.com/users/Alamofire/orgs","repos_url":"https://api.github.com/users/Alamofire/repos","events_url":"https://api.github.com/users/Alamofire/events{/privacy}","received_events_url":"https://api.github.com/users/Alamofire/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/Alamofire/Alamofire","description":"Elegant HTTP Networking in Swift","fork":false,"url":"https://api.github.com/repos/Alamofire/Alamofire","forks_url":"https://api.github.com/repos/Alamofire/Alamofire/forks","keys_url":"https://api.github.com/repos/Alamofire/Alamofire/keys{/key_id}","collaborators_url":"https://api.github.com/repos/Alamofire/Alamofire/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/Alamofire/Alamofire/teams","hooks_url":"https://api.github.com/repos/Alamofire/Alamofire/hooks","issue_events_url":"https://api.github.com/repos/Alamofire/Alamofire/issues/events{/number}","events_url":"https://api.github.com/repos/Alamofire/Alamofire/events","assignees_url":"https://api.github.com/repos/Alamofire/Alamofire/assignees{/user}","branches_url":"https://api.github.com/repos/Alamofire/Alamofire/branches{/branch}","tags_url":"https://api.github.com/repos/Alamofire/Alamofire/tags","blobs_url":"https://api.github.com/repos/Alamofire/Alamofire/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/Alamofire/Alamofire/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/Alamofire/Alamofire/git/refs{/sha}","trees_url":"https://api.github.com/repos/Alamofire/Alamofire/git/trees{/sha}","statuses_url":"https://api.github.com/repos/Alamofire/Alamofire/statuses/{sha}","languages_url":"https://api.github.com/repos/Alamofire/Alamofire/languages","stargazers_url":"https://api.github.com/repos/Alamofire/Alamofire/stargazers","contributors_url":"https://api.github.com/repos/Alamofire/Alamofire/contributors","subscribers_url":"https://api.github.com/repos/Alamofire/Alamofire/subscribers","subscription_url":"https://api.github.com/repos/Alamofire/Alamofire/subscription","commits_url":"https://api.github.com/repos/Alamofire/Alamofire/commits{/sha}","git_commits_url":"https://api.github.com/repos/Alamofire/Alamofire/git/commits{/sha}","comments_url":"https://api.github.com/repos/Alamofire/Alamofire/comments{/number}","issue_comment_url":"https://api.github.com/repos/Alamofire/Alamofire/issues/comments{/number}","contents_url":"https://api.github.com/repos/Alamofire/Alamofire/contents/{+path}","compare_url":"https://api.github.com/repos/Alamofire/Alamofire/compare/{base}...{head}","merges_url":"https://api.github.com/repos/Alamofire/Alamofire/merges","archive_url":"https://api.github.com/repos/Alamofire/Alamofire/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/Alamofire/Alamofire/downloads","issues_url":"https://api.github.com/repos/Alamofire/Alamofire/issues{/number}","pulls_url":"https://api.github.com/repos/Alamofire/Alamofire/pulls{/number}","milestones_url":"https://api.github.com/repos/Alamofire/Alamofire/milestones{/number}","notifications_url":"https://api.github.com/repos/Alamofire/Alamofire/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/Alamofire/Alamofire/labels{/name}","releases_url":"https://api.github.com/repos/Alamofire/Alamofire/releases{/id}","deployments_url":"https://api.github.com/repos/Alamofire/Alamofire/deployments","created_at":"2014-07-31T05:56:19Z","updated_at":"2016-08-28T16:15:35Z","pushed_at":"2016-08-26T05:24:32Z","git_url":"git://github.com/Alamofire/Alamofire.git","ssh_url":"git@github.com:Alamofire/Alamofire.git","clone_url":"https://github.com/Alamofire/Alamofire.git","svn_url":"https://github.com/Alamofire/Alamofire","homepage":"","size":3710,"stargazers_count":18799,"watchers_count":18799,"language":"Swift","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":2986,"mirror_url":null,"open_issues_count":30,"forks":2986,"open_issues":30,"watchers":18799,"default_branch":"master"}},"base":{"label":"Alamofire:swift3","ref":"swift3","sha":"3cc5b4e8453bec9fd6b973d60e6b0605a38e4cf4","user":{"login":"Alamofire","id":7774181,"avatar_url":"https://avatars.githubusercontent.com/u/7774181?v=3","gravatar_id":"","url":"https://api.github.com/users/Alamofire","html_url":"https://github.com/Alamofire","followers_url":"https://api.github.com/users/Alamofire/followers","following_url":"https://api.github.com/users/Alamofire/following{/other_user}","gists_url":"https://api.github.com/users/Alamofire/gists{/gist_id}","starred_url":"https://api.github.com/users/Alamofire/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Alamofire/subscriptions","organizations_url":"https://api.github.com/users/Alamofire/orgs","repos_url":"https://api.github.com/users/Alamofire/repos","events_url":"https://api.github.com/users/Alamofire/events{/privacy}","received_events_url":"https://api.github.com/users/Alamofire/received_events","type":"Organization","site_admin":false},"repo":{"id":22458259,"name":"Alamofire","full_name":"Alamofire/Alamofire","owner":{"login":"Alamofire","id":7774181,"avatar_url":"https://avatars.githubusercontent.com/u/7774181?v=3","gravatar_id":"","url":"https://api.github.com/users/Alamofire","html_url":"https://github.com/Alamofire","followers_url":"https://api.github.com/users/Alamofire/followers","following_url":"https://api.github.com/users/Alamofire/following{/other_user}","gists_url":"https://api.github.com/users/Alamofire/gists{/gist_id}","starred_url":"https://api.github.com/users/Alamofire/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Alamofire/subscriptions","organizations_url":"https://api.github.com/users/Alamofire/orgs","repos_url":"https://api.github.com/users/Alamofire/repos","events_url":"https://api.github.com/users/Alamofire/events{/privacy}","received_events_url":"https://api.github.com/users/Alamofire/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/Alamofire/Alamofire","description":"Elegant HTTP Networking in Swift","fork":false,"url":"https://api.github.com/repos/Alamofire/Alamofire","forks_url":"https://api.github.com/repos/Alamofire/Alamofire/forks","keys_url":"https://api.github.com/repos/Alamofire/Alamofire/keys{/key_id}","collaborators_url":"https://api.github.com/repos/Alamofire/Alamofire/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/Alamofire/Alamofire/teams","hooks_url":"https://api.github.com/repos/Alamofire/Alamofire/hooks","issue_events_url":"https://api.github.com/repos/Alamofire/Alamofire/issues/events{/number}","events_url":"https://api.github.com/repos/Alamofire/Alamofire/events","assignees_url":"https://api.github.com/repos/Alamofire/Alamofire/assignees{/user}","branches_url":"https://api.github.com/repos/Alamofire/Alamofire/branches{/branch}","tags_url":"https://api.github.com/repos/Alamofire/Alamofire/tags","blobs_url":"https://api.github.com/repos/Alamofire/Alamofire/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/Alamofire/Alamofire/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/Alamofire/Alamofire/git/refs{/sha}","trees_url":"https://api.github.com/repos/Alamofire/Alamofire/git/trees{/sha}","statuses_url":"https://api.github.com/repos/Alamofire/Alamofire/statuses/{sha}","languages_url":"https://api.github.com/repos/Alamofire/Alamofire/languages","stargazers_url":"https://api.github.com/repos/Alamofire/Alamofire/stargazers","contributors_url":"https://api.github.com/repos/Alamofire/Alamofire/contributors","subscribers_url":"https://api.github.com/repos/Alamofire/Alamofire/subscribers","subscription_url":"https://api.github.com/repos/Alamofire/Alamofire/subscription","commits_url":"https://api.github.com/repos/Alamofire/Alamofire/commits{/sha}","git_commits_url":"https://api.github.com/repos/Alamofire/Alamofire/git/commits{/sha}","comments_url":"https://api.github.com/repos/Alamofire/Alamofire/comments{/number}","issue_comment_url":"https://api.github.com/repos/Alamofire/Alamofire/issues/comments{/number}","contents_url":"https://api.github.com/repos/Alamofire/Alamofire/contents/{+path}","compare_url":"https://api.github.com/repos/Alamofire/Alamofire/compare/{base}...{head}","merges_url":"https://api.github.com/repos/Alamofire/Alamofire/merges","archive_url":"https://api.github.com/repos/Alamofire/Alamofire/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/Alamofire/Alamofire/downloads","issues_url":"https://api.github.com/repos/Alamofire/Alamofire/issues{/number}","pulls_url":"https://api.github.com/repos/Alamofire/Alamofire/pulls{/number}","milestones_url":"https://api.github.com/repos/Alamofire/Alamofire/milestones{/number}","notifications_url":"https://api.github.com/repos/Alamofire/Alamofire/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/Alamofire/Alamofire/labels{/name}","releases_url":"https://api.github.com/repos/Alamofire/Alamofire/releases{/id}","deployments_url":"https://api.github.com/repos/Alamofire/Alamofire/deployments","created_at":"2014-07-31T05:56:19Z","updated_at":"2016-08-28T16:15:35Z","pushed_at":"2016-08-26T05:24:32Z","git_url":"git://github.com/Alamofire/Alamofire.git","ssh_url":"git@github.com:Alamofire/Alamofire.git","clone_url":"https://github.com/Alamofire/Alamofire.git","svn_url":"https://github.com/Alamofire/Alamofire","homepage":"","size":3710,"stargazers_count":18799,"watchers_count":18799,"language":"Swift","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":2986,"mirror_url":null,"open_issues_count":30,"forks":2986,"open_issues":30,"watchers":18799,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/Alamofire/Alamofire/pulls/1419"},"html":{"href":"https://github.com/Alamofire/Alamofire/pull/1419"},"issue":{"href":"https://api.github.com/repos/Alamofire/Alamofire/issues/1419"},"comments":{"href":"https://api.github.com/repos/Alamofire/Alamofire/issues/1419/comments"},"review_comments":{"href":"https://api.github.com/repos/Alamofire/Alamofire/pulls/1419/comments"},"review_comment":{"href":"https://api.github.com/repos/Alamofire/Alamofire/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/Alamofire/Alamofire/pulls/1419/commits"},"statuses":{"href":"https://api.github.com/repos/Alamofire/Alamofire/statuses/60dc4ec0525ebe034787ada405bdfe3e6d644507"}}}}
{"actor":{"display_login":"cnoon"}}