Skip to content

Commit

Permalink
Set content length in request/response bodies (#96)
Browse files Browse the repository at this point in the history
### Motivation

A surprising oversight, we were never setting the `content-length`
header when sending out a known-length body.

Some transports might be already doing this, but this change makes
things more consistent.

### Modifications

Add the `content-length` header when setting a body and we know the
length from the `HTTPBody`.

### Result

More consistent experience.

### Test Plan

Adapted unit tests.
  • Loading branch information
czechboy0 authored Jan 18, 2024
1 parent 95307ba commit 76951d7
Show file tree
Hide file tree
Showing 3 changed files with 15 additions and 11 deletions.
8 changes: 6 additions & 2 deletions Sources/OpenAPIRuntime/Conversion/CurrencyExtensions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -435,8 +435,10 @@ extension Converter {
contentType: String,
convert: (T) throws -> HTTPBody
) rethrows -> HTTPBody {
let body = try convert(value)
headerFields[.contentType] = contentType
return try convert(value)
if case let .known(length) = body.length { headerFields[.contentLength] = String(length) }
return body
}

/// Sets the provided request body and the appropriate content type.
Expand Down Expand Up @@ -597,8 +599,10 @@ extension Converter {
contentType: String,
convert: (T) throws -> HTTPBody
) rethrows -> HTTPBody {
let body = try convert(value)
headerFields[.contentType] = contentType
return try convert(value)
if case let .known(length) = body.length { headerFields[.contentLength] = String(length) }
return body
}

/// Returns a decoded value for the provided path parameter.
Expand Down
14 changes: 7 additions & 7 deletions Tests/OpenAPIRuntimeTests/Conversion/Test_Converter+Client.swift
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ final class Test_ClientConverterExtensions: Test_Runtime {
contentType: "application/json"
)
try await XCTAssertEqualStringifiedData(body, testStructPrettyString)
XCTAssertEqual(headerFields, [.contentType: "application/json"])
XCTAssertEqual(headerFields, [.contentType: "application/json", .contentLength: "23"])
}

func test_setOptionalRequestBodyAsJSON_codable_string() async throws {
Expand All @@ -106,7 +106,7 @@ final class Test_ClientConverterExtensions: Test_Runtime {
contentType: "application/json"
)
try await XCTAssertEqualStringifiedData(body, testQuotedString)
XCTAssertEqual(headerFields, [.contentType: "application/json"])
XCTAssertEqual(headerFields, [.contentType: "application/json", .contentLength: "7"])
}

// | client | set | request body | JSON | required | setRequiredRequestBodyAsJSON |
Expand All @@ -118,7 +118,7 @@ final class Test_ClientConverterExtensions: Test_Runtime {
contentType: "application/json"
)
try await XCTAssertEqualStringifiedData(body, testStructPrettyString)
XCTAssertEqual(headerFields, [.contentType: "application/json"])
XCTAssertEqual(headerFields, [.contentType: "application/json", .contentLength: "23"])
}

// | client | set | request body | urlEncodedForm | codable | optional | setRequiredRequestBodyAsURLEncodedForm |
Expand All @@ -136,7 +136,7 @@ final class Test_ClientConverterExtensions: Test_Runtime {
}

try await XCTAssertEqualStringifiedData(body, testStructURLFormString)
XCTAssertEqual(headerFields, [.contentType: "application/x-www-form-urlencoded"])
XCTAssertEqual(headerFields, [.contentType: "application/x-www-form-urlencoded", .contentLength: "41"])
}

// | client | set | request body | urlEncodedForm | codable | required | setRequiredRequestBodyAsURLEncodedForm |
Expand All @@ -148,7 +148,7 @@ final class Test_ClientConverterExtensions: Test_Runtime {
contentType: "application/x-www-form-urlencoded"
)
try await XCTAssertEqualStringifiedData(body, testStructURLFormString)
XCTAssertEqual(headerFields, [.contentType: "application/x-www-form-urlencoded"])
XCTAssertEqual(headerFields, [.contentType: "application/x-www-form-urlencoded", .contentLength: "41"])
}

// | client | set | request body | binary | optional | setOptionalRequestBodyAsBinary |
Expand All @@ -160,7 +160,7 @@ final class Test_ClientConverterExtensions: Test_Runtime {
contentType: "application/octet-stream"
)
try await XCTAssertEqualStringifiedData(body, testString)
XCTAssertEqual(headerFields, [.contentType: "application/octet-stream"])
XCTAssertEqual(headerFields, [.contentType: "application/octet-stream", .contentLength: "5"])
}

// | client | set | request body | binary | required | setRequiredRequestBodyAsBinary |
Expand All @@ -172,7 +172,7 @@ final class Test_ClientConverterExtensions: Test_Runtime {
contentType: "application/octet-stream"
)
try await XCTAssertEqualStringifiedData(body, testString)
XCTAssertEqual(headerFields, [.contentType: "application/octet-stream"])
XCTAssertEqual(headerFields, [.contentType: "application/octet-stream", .contentLength: "5"])
}

// | client | set | request body | multipart | required | setRequiredRequestBodyAsMultipart |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,7 @@ final class Test_ServerConverterExtensions: Test_Runtime {
contentType: "application/json"
)
try await XCTAssertEqualStringifiedData(data, testStructPrettyString)
XCTAssertEqual(headers, [.contentType: "application/json"])
XCTAssertEqual(headers, [.contentType: "application/json", .contentLength: "23"])
}

// | server | set | response body | binary | required | setResponseBodyAsBinary |
Expand All @@ -328,7 +328,7 @@ final class Test_ServerConverterExtensions: Test_Runtime {
contentType: "application/octet-stream"
)
try await XCTAssertEqualStringifiedData(data, testString)
XCTAssertEqual(headers, [.contentType: "application/octet-stream"])
XCTAssertEqual(headers, [.contentType: "application/octet-stream", .contentLength: "5"])
}

// | server | set | response body | multipart | required | setResponseBodyAsMultipart |
Expand Down

0 comments on commit 76951d7

Please sign in to comment.