@@ -101,45 +101,32 @@ public let FunctionsErrorDetailsKey: String = "details"
101101 case unauthenticated = 16
102102}
103103
104- /**
105- * Takes an HTTP status code and returns the corresponding `FIRFunctionsErrorCode` error code.
106- * This is the standard HTTP status code -> error mapping defined in:
107- * https://github.com/googleapis/googleapis/blob/master/google/rpc/code.proto
108- * - Parameter status An HTTP status code.
109- * - Returns: The corresponding error code, or `FIRFunctionsErrorCodeUnknown` if none.
110- */
111- func FunctionsCodeForHTTPStatus( _ status: NSInteger ) -> FunctionsErrorCode {
112- switch status {
113- case 200 :
114- return . OK
115- case 400 :
116- return . invalidArgument
117- case 401 :
118- return . unauthenticated
119- case 403 :
120- return . permissionDenied
121- case 404 :
122- return . notFound
123- case 409 :
124- return . alreadyExists
125- case 429 :
126- return . resourceExhausted
127- case 499 :
128- return . cancelled
129- case 500 :
130- return . internal
131- case 501 :
132- return . unimplemented
133- case 503 :
134- return . unavailable
135- case 504 :
136- return . deadlineExceeded
137- default :
138- return . internal
104+ extension FunctionsErrorCode {
105+ /// Takes an HTTP status code and returns the corresponding `FIRFunctionsErrorCode` error code.
106+ ///
107+ /// + This is the standard HTTP status code -> error mapping defined in:
108+ /// https://github.com/googleapis/googleapis/blob/master/google/rpc/code.proto
109+ ///
110+ /// - Parameter status: An HTTP status code.
111+ /// - Returns: A `FunctionsErrorCode`. Falls back to `internal` for unknown status codes.
112+ static func errorCode( forHTTPStatus status: Int ) -> Self {
113+ switch status {
114+ case 200 : . OK
115+ case 400 : . invalidArgument
116+ case 401 : . unauthenticated
117+ case 403 : . permissionDenied
118+ case 404 : . notFound
119+ case 409 : . alreadyExists
120+ case 429 : . resourceExhausted
121+ case 499 : . cancelled
122+ case 500 : . internal
123+ case 501 : . unimplemented
124+ case 503 : . unavailable
125+ case 504 : . deadlineExceeded
126+ default : . internal
127+ }
139128 }
140- }
141129
142- extension FunctionsErrorCode {
143130 static func errorCode( forName name: String ) -> FunctionsErrorCode {
144131 switch name {
145132 case " OK " : return . OK
@@ -207,53 +194,55 @@ extension FunctionsErrorCode {
207194 code: rawValue,
208195 userInfo: userInfo ?? [ NSLocalizedDescriptionKey: descriptionForErrorCode] )
209196 }
210- }
211197
212- func FunctionsErrorForResponse ( status: NSInteger ,
198+ static func errorForResponse ( status: Int ,
213199 body: Data ? ,
214200 serializer: FunctionsSerializer ) -> NSError ? {
215- // Start with reasonable defaults from the status code.
216- var code = FunctionsCodeForHTTPStatus ( status)
217- var description = code. descriptionForErrorCode
218-
219- var details : AnyObject ?
201+ // Start with reasonable defaults from the status code.
202+ var code = FunctionsErrorCode . errorCode ( forHTTPStatus: status)
203+ var description = code. descriptionForErrorCode
204+ var details : AnyObject ?
205+
206+ // Then look through the body for explicit details.
207+ if let body,
208+ let json = try ? JSONSerialization . jsonObject ( with: body) as? NSDictionary ,
209+ let errorDetails = json [ " error " ] as? NSDictionary {
210+ if let status = errorDetails [ " status " ] as? String {
211+ code = . errorCode( forName: status)
212+
213+ // If the code in the body is invalid, treat the whole response as malformed.
214+ guard code != . internal else {
215+ return code. generatedError ( userInfo: nil )
216+ }
217+ }
220218
221- // Then look through the body for explicit details.
222- if let body,
223- let json = try ? JSONSerialization . jsonObject ( with: body) as? NSDictionary ,
224- let errorDetails = json [ " error " ] as? NSDictionary {
225- if let status = errorDetails [ " status " ] as? String {
226- code = FunctionsErrorCode . errorCode ( forName: status)
219+ if let message = errorDetails [ " message " ] as? String {
220+ description = message
221+ } else {
222+ description = code. descriptionForErrorCode
223+ }
227224
228- // If the code in the body is invalid, treat the whole response as malformed.
229- guard code != . internal else {
230- return code. generatedError ( userInfo: nil )
225+ details = errorDetails [ " details " ] as AnyObject ?
226+ // Update `details` only if decoding succeeds;
227+ // otherwise, keep the original object.
228+ if let innerDetails = details,
229+ let decodedDetails = try ? serializer. decode ( innerDetails) {
230+ details = decodedDetails
231231 }
232232 }
233233
234- if let message = errorDetails [ " message " ] as? String {
235- description = message
236- } else {
237- description = code. descriptionForErrorCode
234+ if code == . OK {
235+ // Technically, there's an edge case where a developer could explicitly return an error code
236+ // of
237+ // OK, and we will treat it as success, but that seems reasonable.
238+ return nil
238239 }
239240
240- details = errorDetails [ " details " ] as AnyObject ?
241- if let innerDetails = details {
242- // Just ignore the details if there an error decoding them.
243- details = try ? serializer . decode ( innerDetails )
241+ var userInfo = [ String : Any ] ( )
242+ userInfo [ NSLocalizedDescriptionKey ] = description
243+ if let details {
244+ userInfo [ FunctionsErrorDetailsKey ] = details
244245 }
246+ return code. generatedError ( userInfo: userInfo)
245247 }
246-
247- if code == . OK {
248- // Technically, there's an edge case where a developer could explicitly return an error code of
249- // OK, and we will treat it as success, but that seems reasonable.
250- return nil
251- }
252-
253- var userInfo = [ String: Any] ( )
254- userInfo [ NSLocalizedDescriptionKey] = description
255- if let details {
256- userInfo [ FunctionsErrorDetailsKey] = details
257- }
258- return code. generatedError ( userInfo: userInfo)
259248}
0 commit comments