Skip to content

Commit

Permalink
Merge pull request #379 from mattpolzin/bugfix/378/content-types
Browse files Browse the repository at this point in the history
Add support for multiple content types on one content encoding object
  • Loading branch information
mattpolzin authored Jul 19, 2024
2 parents ea46a4c + ce799a3 commit 4991b7e
Show file tree
Hide file tree
Showing 5 changed files with 73 additions and 35 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/codecov.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ jobs:
image: swift:5.8
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- run: swift test --enable-test-discovery --enable-code-coverage
- id: analysis
uses: mattpolzin/[email protected]
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/documentation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ jobs:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
# TODO: replace the documentation generator with something that is still maintained.

# - name: Generate Documentation
Expand Down
32 changes: 4 additions & 28 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,23 +13,15 @@ jobs:
fail-fast: false
matrix:
image:
- swift:5.1-xenial
- swift:5.1-bionic
- swift:5.2-xenial
- swift:5.2-bionic
- swift:5.2-focal
- swift:5.2-centos8
- swift:5.2-amazonlinux2
- swift:5.3-xenial
- swift:5.3-bionic
- swift:5.3-focal
- swift:5.3-centos8
- swift:5.3-amazonlinux2
# see below for 5.4, 5.5, etc.
container: ${{ matrix.image }}
steps:
- name: Checkout code
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Run tests
run: swift test --enable-test-discovery
# 5.4 is separate because there was a bug in the compiler that caused
Expand All @@ -40,15 +32,12 @@ jobs:
fail-fast: false
matrix:
image:
- swift:5.4-xenial
- swift:5.4-bionic
- swift:5.4-focal
- swift:5.4-centos8
- swift:5.4-amazonlinux2
container: ${{ matrix.image }}
steps:
- name: Checkout code
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Run tests (without test discovery flag)
run: swift test -Xswiftc -Xfrontend -Xswiftc -sil-verify-none
linux-5_5-plus:
Expand All @@ -57,36 +46,23 @@ jobs:
fail-fast: false
matrix:
image:
- swift:5.5-xenial
- swift:5.5-bionic
- swift:5.5-focal
- swift:5.5-centos8
- swift:5.5-amazonlinux2
- swift:5.6-bionic
- swift:5.6-focal
- swift:5.6-amazonlinux2
- swift:5.7-bionic
- swift:5.7-focal
- swift:5.7-jammy
- swift:5.7-amazonlinux2
- swift:5.8-bionic
- swift:5.8-focal
- swift:5.8-jammy
- swift:5.8-amazonlinux2
- swift:5.9-focal
- swift:5.9-jammy
- swift:5.9-amazonlinux2
- swift:5.10-focal
- swift:5.10-jammy
- swift:5.10-amazonlinux2
- swiftlang/swift:nightly-bionic
- swiftlang/swift:nightly-focal
- swiftlang/swift:nightly-jammy
- swiftlang/swift:nightly-amazonlinux2
container: ${{ matrix.image }}
steps:
- name: Checkout code
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Run tests
run: swift test
osx:
Expand All @@ -97,6 +73,6 @@ jobs:
with:
xcode-version: latest
- name: Checkout code
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Run tests
run: swift test --enable-test-discovery
45 changes: 40 additions & 5 deletions Sources/OpenAPIKit/Content/ContentEncoding.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,33 +14,54 @@ extension OpenAPI.Content {
public struct Encoding: Equatable {
public typealias Style = OpenAPI.Parameter.SchemaContext.Style

public let contentType: OpenAPI.ContentType?
/// If an encoding object only contains 1 content type, it will be populated here.
/// Two or more content types will result in a null value here but the `contentTypes`
/// (plural) property will contain all content types specified.
///
/// The singular `contentType` property is only provided for backwards compatibility and
/// using the plural `contentTypes` property should be preferred.
@available(*, deprecated, message: "use contentTypes instead")
public var contentType: OpenAPI.ContentType? {
guard let contentType = contentTypes.first,
contentTypes.count == 1 else {
return nil
}
return contentType
}

public let contentTypes: [OpenAPI.ContentType]
public let headers: OpenAPI.Header.Map?
public let style: Style
public let explode: Bool
public let allowReserved: Bool

/// The singular `contentType` argument is only provided for backwards compatibility and
/// using the plural `contentTypes` argument should be preferred.
public init(
contentType: OpenAPI.ContentType? = nil,
contentTypes: [OpenAPI.ContentType] = [],
headers: OpenAPI.Header.Map? = nil,
style: Style = Self.defaultStyle,
allowReserved: Bool = false
) {
self.contentType = contentType
self.contentTypes = contentTypes + [contentType].compactMap { $0 }
self.headers = headers
self.style = style
self.explode = style.defaultExplode
self.allowReserved = allowReserved
}

/// The singular `contentType` argument is only provided for backwards compatibility and
/// using the plural `contentTypes` argument should be preferred.
public init(
contentType: OpenAPI.ContentType? = nil,
contentTypes: [OpenAPI.ContentType] = [],
headers: OpenAPI.Header.Map? = nil,
style: Style = Self.defaultStyle,
explode: Bool,
allowReserved: Bool = false
) {
self.contentType = contentType
self.contentTypes = contentTypes + [contentType].compactMap { $0 }
self.headers = headers
self.style = style
self.explode = explode
Expand All @@ -56,7 +77,12 @@ extension OpenAPI.Content.Encoding: Encodable {
public func encode(to encoder: Encoder) throws {
var container = encoder.container(keyedBy: CodingKeys.self)

try container.encodeIfPresent(contentType, forKey: .contentType)
if contentTypes.count > 0 {
let contentTypesString = contentTypes
.map(\.rawValue)
.joined(separator: ", ")
try container.encode(contentTypesString, forKey: .contentType)
}
try container.encodeIfPresent(headers, forKey: .headers)

if style != Self.defaultStyle {
Expand All @@ -77,7 +103,16 @@ extension OpenAPI.Content.Encoding: Decodable {
public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)

contentType = try container.decodeIfPresent(OpenAPI.ContentType.self, forKey: .contentType)
let contentTypesString = try container.decodeIfPresent(String.self, forKey: .contentType)
if let contentTypesString = contentTypesString {
contentTypes = contentTypesString
.split(separator: ",")
.compactMap { string in
OpenAPI.ContentType.init(rawValue: string.trimmingCharacters(in: .whitespaces))
}
} else {
contentTypes = []
}

headers = try container.decodeIfPresent(OpenAPI.Header.Map.self, forKey: .headers)

Expand Down
27 changes: 27 additions & 0 deletions Tests/OpenAPIKitTests/Content/ContentTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -570,6 +570,33 @@ extension ContentTests {
XCTAssertEqual(encoding, OpenAPI.Content.Encoding(contentType: .csv))
}

func test_encoding_multiple_contentTypes_encode() throws {
let encoding = OpenAPI.Content.Encoding(contentTypes: [.csv, .json])

let encodedEncoding = try! orderUnstableTestStringFromEncoding(of: encoding)

assertJSONEquivalent(
encodedEncoding,
"""
{
"contentType" : "text\\/csv, application\\/json"
}
"""
)
}

func test_encoding_multiple_contentTypes_decode() throws {
let encodingData =
"""
{
"contentType": "text/csv, application/json"
}
""".data(using: .utf8)!
let encoding = try! orderUnstableDecode(OpenAPI.Content.Encoding.self, from: encodingData)

XCTAssertEqual(encoding, OpenAPI.Content.Encoding(contentTypes: [.csv, .json]))
}

func test_encoding_headers_encode() throws {
let encoding = OpenAPI.Content.Encoding(headers: [
"X-CustomThing": .init(OpenAPI.Header(schema: .string))
Expand Down

0 comments on commit 4991b7e

Please sign in to comment.