@@ -67,34 +67,10 @@ extension Converter {
6767 guard let parsedAcceptValue = OpenAPIMIMEType ( acceptValue) else {
6868 throw RuntimeError . invalidExpectedContentType ( acceptValue)
6969 }
70- switch ( parsedAcceptValue. kind, parsedSubstring. kind) {
71- case ( . any, _) :
72- // Accept: */* always matches
73- return
74- case ( . anySubtype( type: let acceptType) , let substring) :
75- switch substring {
76- case . any:
77- // */* as a concrete content type is NOT a match for an Accept header of foo/*
78- break
79- case . anySubtype( type: let substringType) :
80- // Only match if the types match.
81- if substringType. lowercased ( ) == acceptType. lowercased ( ) { return }
82- case . concrete( type: let substringType, _) :
83- if substringType. lowercased ( ) == acceptType. lowercased ( ) { return }
84- }
85- case ( . concrete( type: let acceptType, subtype: let acceptSubtype) , let substring) :
86- if case let . concrete( substringType, substringSubtype) = substring {
87- if acceptType. lowercased ( ) == substringType. lowercased ( )
88- && acceptSubtype. lowercased ( ) == substringSubtype. lowercased ( )
89- {
90- return
91- }
92- }
93- }
70+ if parsedSubstring. satisfies ( acceptValue: parsedAcceptValue) { return }
9471 }
9572 throw RuntimeError . unexpectedAcceptHeader ( acceptHeader)
9673 }
97-
9874 /// Retrieves and decodes a path parameter as a URI-encoded value of the specified type.
9975 ///
10076 /// - Parameters:
@@ -500,3 +476,27 @@ extension Converter {
500476 )
501477 }
502478}
479+
480+ fileprivate extension OpenAPIMIMEType {
481+ /// Checks if the type satisfies the provided Accept header value.
482+ /// - Parameter acceptValue: A parsed Accept header MIME type.
483+ /// - Returns: `true` if it satisfies the Accept header, `false` otherwise.
484+ func satisfies( acceptValue: OpenAPIMIMEType ) -> Bool {
485+ switch ( acceptValue. kind, self . kind) {
486+ case ( . concrete, . any) , ( . concrete, . anySubtype) , ( . anySubtype, . any) :
487+ // The response content-type must be at least as specific as the accept header.
488+ return false
489+ case ( . any, _) :
490+ // Accept: */* -- Any content-type satisfies the accept header.
491+ return true
492+ case ( . anySubtype( let acceptType) , . anySubtype( let substringType) ) ,
493+ ( . anySubtype( let acceptType) , . concrete( let substringType, _) ) :
494+ // Accept: type/* -- The content-type should match the partially-specified accept header.
495+ return acceptType. lowercased ( ) == substringType. lowercased ( )
496+ case ( . concrete( let acceptType, let acceptSubtype) , . concrete( let substringType, let substringSubtype) ) :
497+ // Accept: type/subtype -- The content-type should match the concrete type.
498+ return acceptType. lowercased ( ) == substringType. lowercased ( )
499+ && acceptSubtype. lowercased ( ) == substringSubtype. lowercased ( )
500+ }
501+ }
502+ }
0 commit comments