Skip to content

Commit 9d4a2ff

Browse files
Improve error message when encountering unexpected content-type headers (#104)
### Motivation When the server response has a content-type header that does not conform to the OpenAPI document, we currently throw an error. However, this error presents itself in a very confusing manner: it prints `Unexpected Content-Type header: application/json`, where `application/json is the _expected_ content-type. At best, this is ambiguous and potentially misleading. ### Modifications - Extend `case RuntimeError.unexpectedContentTypeHeader` with _both_ the expected and received content-type associated values. - Update the printed description to include both the expected and received content-type header values. ### Result When an unexpected content-type is received, the error message is clearer. ### Test Plan Updated the existing test that expects an error to check the error and that the error values are provided in the correct order.
1 parent 6e2f9b9 commit 9d4a2ff

File tree

3 files changed

+20
-5
lines changed

3 files changed

+20
-5
lines changed

Sources/OpenAPIRuntime/Conversion/Converter+Common.swift

+6-1
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,12 @@ extension Converter {
6161
// The force unwrap is safe, we only get here if the array is not empty.
6262
let bestOption = evaluatedOptions.max { a, b in a.match.score < b.match.score }!
6363
let bestContentType = bestOption.contentType
64-
if case .incompatible = bestOption.match { throw RuntimeError.unexpectedContentTypeHeader(bestContentType) }
64+
if case .incompatible = bestOption.match {
65+
throw RuntimeError.unexpectedContentTypeHeader(
66+
expected: bestContentType,
67+
received: String(describing: received)
68+
)
69+
}
6570
return bestContentType
6671
}
6772

Sources/OpenAPIRuntime/Errors/RuntimeError.swift

+3-2
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ internal enum RuntimeError: Error, CustomStringConvertible, LocalizedError, Pret
3737

3838
// Headers
3939
case missingRequiredHeaderField(String)
40-
case unexpectedContentTypeHeader(String)
40+
case unexpectedContentTypeHeader(expected: String, received: String)
4141
case unexpectedAcceptHeader(String)
4242
case malformedAcceptHeader(String)
4343
case missingOrMalformedContentDispositionName
@@ -95,7 +95,8 @@ internal enum RuntimeError: Error, CustomStringConvertible, LocalizedError, Pret
9595
return
9696
"Unsupported parameter style, parameter name: '\(name)', kind: \(location), style: \(style), explode: \(explode)"
9797
case .missingRequiredHeaderField(let name): return "The required header field named '\(name)' is missing."
98-
case .unexpectedContentTypeHeader(let contentType): return "Unexpected Content-Type header: \(contentType)"
98+
case .unexpectedContentTypeHeader(expected: let expected, received: let received):
99+
return "Unexpected content type, expected: \(expected), received: \(received)"
99100
case .unexpectedAcceptHeader(let accept): return "Unexpected Accept header: \(accept)"
100101
case .malformedAcceptHeader(let accept): return "Malformed Accept header: \(accept)"
101102
case .missingOrMalformedContentDispositionName:

Tests/OpenAPIRuntimeTests/Conversion/Test_Converter+Common.swift

+11-2
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
//
1313
//===----------------------------------------------------------------------===//
1414
import XCTest
15-
@_spi(Generated) import OpenAPIRuntime
15+
@testable @_spi(Generated) import OpenAPIRuntime
1616
import HTTPTypes
1717

1818
extension HTTPField.Name { static var foo: Self { Self("foo")! } }
@@ -84,7 +84,16 @@ final class Test_CommonConverterExtensions: Test_Runtime {
8484
try testCase(received: "image/png", options: ["image/*", "*/*"], expected: "image/*")
8585
XCTAssertThrowsError(
8686
try testCase(received: "text/csv", options: ["text/html", "application/json"], expected: "-")
87-
)
87+
) { error in
88+
XCTAssert(error is RuntimeError)
89+
guard let error = error as? RuntimeError,
90+
case .unexpectedContentTypeHeader(expected: let expected, received: let received) = error,
91+
expected == "text/html", received == "text/csv"
92+
else {
93+
XCTFail("Unexpected error: \(error)")
94+
return
95+
}
96+
}
8897
}
8998

9099
func testVerifyContentTypeIfPresent() throws {

0 commit comments

Comments
 (0)