Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -401,7 +401,12 @@ extension ServerFileTranslator {

var caseCodeBlocks: [CodeBlock] = []

let contentTypeHeaderValue = typedContent.content.contentType.headerValueForValidation
let contentType = typedContent.content.contentType
let contentTypeForServer = contentType.lowercasedTypeAndSubtype == "*/*"
? ContentType.applicationOctetStream
: contentType

let contentTypeHeaderValue = contentTypeForServer.headerValueForValidation
let validateAcceptHeader: Expression = .try(
.identifierPattern("converter").dot("validateAcceptIfPresent")
.call([
Expand All @@ -411,9 +416,8 @@ extension ServerFileTranslator {
)
caseCodeBlocks.append(.expression(validateAcceptHeader))

let contentType = typedContent.content.contentType
let extraBodyAssignArgs: [FunctionArgumentDescription]
if contentType.isMultipart {
if contentTypeForServer.isMultipart {
extraBodyAssignArgs = try translateMultipartSerializerExtraArgumentsInServer(typedContent)
} else {
extraBodyAssignArgs = []
Expand All @@ -422,7 +426,7 @@ extension ServerFileTranslator {
left: .identifierPattern("body"),
right: .try(
.identifierPattern("converter")
.dot("setResponseBodyAs\(contentType.codingStrategy.runtimeName)")
.dot("setResponseBodyAs\(contentTypeForServer.codingStrategy.runtimeName)")
.call(
[
.init(label: nil, expression: .identifierPattern("value")),
Expand All @@ -432,7 +436,7 @@ extension ServerFileTranslator {
),
.init(
label: "contentType",
expression: .literal(contentType.headerValueForSending)
expression: .literal(contentTypeForServer.headerValueForSending)
),
] + extraBodyAssignArgs
)
Expand Down
117 changes: 117 additions & 0 deletions Tests/OpenAPIGeneratorReferenceTests/SnippetBasedReferenceTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3604,6 +3604,123 @@ final class SnippetBasedReferenceTests: XCTestCase {
)
}


func testResponseWildcardContentTypeUsesApplicationOctetStreamInServer() throws {
try self.assertResponseInTypesClientServerTranslation(
"""
/download:
get:
operationId: download
responses:
'200':
description: ok
content:
'*/*':
schema:
type: string
format: binary
""",
output: """
@frozen public enum Output: Sendable, Hashable {
public struct Ok: Sendable, Hashable {
@frozen public enum Body: Sendable, Hashable {
case any(OpenAPIRuntime.HTTPBody)
public var any: OpenAPIRuntime.HTTPBody {
get throws {
switch self {
case let .any(body):
return body
}
}
}
}
public var body: Operations.download.Output.Ok.Body
public init(body: Operations.download.Output.Ok.Body) {
self.body = body
}
}
case ok(Operations.download.Output.Ok)
public var ok: Operations.download.Output.Ok {
get throws {
switch self {
case let .ok(response):
return response
default:
try throwUnexpectedResponseStatus(
expectedStatus: "ok",
response: self
)
}
}
}
case undocumented(statusCode: Swift.Int, OpenAPIRuntime.UndocumentedPayload)
}
""",
server: """
{ output, request in
switch output {
case let .ok(value):
suppressUnusedWarning(value)
var response = HTTPTypes.HTTPResponse(soar_statusCode: 200)
suppressMutabilityWarning(&response)
let body: OpenAPIRuntime.HTTPBody
switch value.body {
case let .any(value):
try converter.validateAcceptIfPresent(
"application/octet-stream",
in: request.headerFields
)
body = try converter.setResponseBodyAsBinary(
value,
headerFields: &response.headerFields,
contentType: "application/octet-stream"
)
}
return (response, body)
case let .undocumented(statusCode, _):
return (.init(soar_statusCode: statusCode), nil)
}
}
""",
client: """
{ response, responseBody in
switch response.status.code {
case 200:
let contentType = converter.extractContentTypeIfPresent(in: response.headerFields)
let body: Operations.download.Output.Ok.Body
let chosenContentType = try converter.bestContentType(
received: contentType,
options: [
"*/*"
]
)
switch chosenContentType {
case "*/*":
body = try converter.getResponseBodyAsBinary(
OpenAPIRuntime.HTTPBody.self,
from: responseBody,
transforming: { value in
.any(value)
}
)
default:
preconditionFailure("bestContentType chose an invalid content type.")
}
return .ok(.init(body: body))
default:
return .undocumented(
statusCode: response.status.code,
.init(
headerFields: response.headerFields,
body: responseBody
)
)
}
}
"""
)
}

func testRequestMultipartBodyReferencedRequestBody() throws {
try self.assertRequestInTypesClientServerTranslation(
"""
Expand Down