Skip to content

Commit b02afe7

Browse files
calvincestarigh-action-runner
authored andcommitted
fix: Multipart close delimiter parsing (#852)
1 parent 5840bcd commit b02afe7

File tree

4 files changed

+54
-11
lines changed

4 files changed

+54
-11
lines changed

Tests/ApolloTests/DeferTests.swift

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -633,4 +633,48 @@ final class DeferTests: XCTestCase, MockResponseProvider {
633633
expect(requestCount).to(equal(2))
634634
}
635635

636+
func test__parsing__givenResponse_withDataAfterCloseDelimiter_shouldParseSuccessfully() async throws {
637+
await registerRequestHandler(
638+
responseData: """
639+
640+
--graphql
641+
content-type: application/json
642+
643+
{
644+
"hasNext": true,
645+
"data": {
646+
"show" : {
647+
"__typename": "show",
648+
"name": "The Scooby-Doo Show",
649+
"characters": [
650+
{
651+
"__typename": "Character",
652+
"name": "Scooby-Doo"
653+
},
654+
{
655+
"__typename": "Character",
656+
"name": "Shaggy Rogers"
657+
},
658+
{
659+
"__typename": "Character",
660+
"name": "Velma Dinkley"
661+
}
662+
]
663+
}
664+
}
665+
}
666+
--graphql--
667+
668+
""".crlfFormattedData()
669+
)
670+
671+
let results = try await network.send(
672+
query: TVShowQuery(),
673+
fetchBehavior: .NetworkOnly,
674+
requestConfiguration: RequestConfiguration(writeResultsToCache: false)
675+
).getAllValues()
676+
677+
expect(results.count).to(equal(1))
678+
}
679+
636680
}

Tests/ApolloTests/Network/AsyncHTTPResponseChunkSequenceTests.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ class AsyncHTTPResponseChunkSequenceTests: XCTestCase, MockResponseProvider {
5353
return request
5454
}
5555

56-
func test__multipartResponse__givenBeginWith_Delimeter_Boundary_shouldParseOut() async throws {
56+
func test__multipartResponse__givenBeginWith_Delimiter_Boundary_shouldParseOut() async throws {
5757
let url = URL(string: "http://www.test.com/multipart-single-chunk")!
5858
let boundary = "-"
5959
let multipartString = "\r\n--\(boundary)\r\nTest"
@@ -76,7 +76,7 @@ class AsyncHTTPResponseChunkSequenceTests: XCTestCase, MockResponseProvider {
7676
}.to(equal(expectedChunks))
7777
}
7878

79-
func test__multipartResponse__givenBeginWith_CRLF_Delimeter_Boundary_shouldParseOut() async throws {
79+
func test__multipartResponse__givenBeginWith_CRLF_Delimiter_Boundary_shouldParseOut() async throws {
8080
let url = URL(string: "http://www.test.com/multipart-single-chunk")!
8181
let boundary = "-"
8282
let multipartString = "\r\n\r\n--\(boundary)\r\nTest"
@@ -122,7 +122,7 @@ class AsyncHTTPResponseChunkSequenceTests: XCTestCase, MockResponseProvider {
122122
}.to(equal(expectedChunks))
123123
}
124124

125-
func test__multipartResponse__givenEndWithCloseDelimeterAfterBoundary_shouldParseOutDelimeter() async throws {
125+
func test__multipartResponse__givenEndWithCloseDelimiterAfterBoundary_shouldParseOutDelimiter() async throws {
126126
let url = URL(string: "http://www.test.com/multipart-single-chunk")!
127127
let boundary = "-"
128128
let multipartString = "\r\n--\(boundary)\r\nTest\r\n--\(boundary)--"
@@ -145,7 +145,7 @@ class AsyncHTTPResponseChunkSequenceTests: XCTestCase, MockResponseProvider {
145145
}.to(equal(expectedChunks))
146146
}
147147

148-
func test__multipartResponse__givenEndWithCRLF_Boundary_CloseDelimeter_shouldParseOutEnd() async throws {
148+
func test__multipartResponse__givenEndWithCRLF_Boundary_CloseDelimiter_shouldParseOutEnd() async throws {
149149
let url = URL(string: "http://www.test.com/multipart-single-chunk")!
150150
let boundary = "-"
151151
let multipartString = "\r\n--\(boundary)\r\nTest\r\n\r\n--\(boundary)--"

apollo-ios/Sources/Apollo/ResponseParsing/AsyncHTTPResponseChunkSequence.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ public struct AsyncHTTPResponseChunkSequence: AsyncChunkSequence {
5252
self.underlyingIterator = underlyingIterator
5353

5454
if let boundaryString = boundary?.data(using: .utf8) {
55-
self.boundary = Constants.Delimeter + boundaryString
55+
self.boundary = Constants.Delimiter + boundaryString
5656
} else {
5757
self.boundary = nil
5858
}
@@ -86,7 +86,7 @@ public struct AsyncHTTPResponseChunkSequence: AsyncChunkSequence {
8686
buffer.removeFirst(Constants.CRLF.count)
8787
}
8888

89-
if buffer == Constants.CloseDelimeter {
89+
if buffer.starts(with: Constants.CloseDelimiter) {
9090
buffer.removeAll()
9191
}
9292
}

apollo-ios/Sources/Apollo/ResponseParsing/MultipartResponseSpecificationParser.swift

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,12 @@ enum MultipartResponseParsing {
2727
/// Carriage Return Line Feed
2828
static let CRLF: Data = Data([0x0D, 0x0A]) // "\r\n"
2929

30-
static let Delimeter: Data = CRLF + [0x2D, 0x2D] // "\r\n--"
30+
static let Delimiter: Data = CRLF + [0x2D, 0x2D] // "\r\n--"
3131

32-
/// The delimeter that signifies the end of a multipart response.
32+
/// The delimiter that signifies the end of a multipart response.
3333
///
34-
/// This should immediately follow a Delimeter + Boundary.
35-
static let CloseDelimeter: Data = Data([0x2D, 0x2D]) // "--"
36-
34+
/// This should immediately follow a Delimiter + Boundary.
35+
static let CloseDelimiter: Data = Data([0x2D, 0x2D]) // "--"
3736

3837
struct DataLineIterator: IteratorProtocol {
3938
/// A double carriage return. Used as the separator between data lines within a multipart response chunk

0 commit comments

Comments
 (0)