Fix event stream line parsing to handle CRLF and empty lines correctly (#89)
* Optimized code in `connectToEventStream` to use `.lines` computed value of `AsyncSequence` to produce a `AsyncLineSequence` instead of building a lines manually.
* - Reverter use of `lines` (it swallows newlines)
- Fiexed original issue I experienced with line 229 `while let newlineIndex = buffer.firstIndex(of: "\n") {` not handling "\r\n" properly
- Added unit test to test for "\r\n" scenario
- Simplified `end of event` test - `line` creation trims newline, added code trims carriage return. Only thing that should be left is an empty line
This commit is contained in:
parent
99517b0564
commit
f6e401aa97
1 changed files with 45 additions and 3 deletions
|
|
@ -411,6 +411,40 @@ import Testing
|
|||
let expectedData = #"{"key":"value"}"#.data(using: .utf8)!
|
||||
let receivedData = try await iterator.next()
|
||||
|
||||
#expect(receivedData == expectedData)
|
||||
}
|
||||
@Test("Receive Server-Sent Event (SSE) (CR-NL)", .httpClientTransportSetup)
|
||||
func testReceiveSSE_CRNL() async throws {
|
||||
let configuration = URLSessionConfiguration.ephemeral
|
||||
configuration.protocolClasses = [MockURLProtocol.self]
|
||||
|
||||
let transport = HTTPClientTransport(
|
||||
endpoint: testEndpoint, configuration: configuration, streaming: true,
|
||||
logger: nil)
|
||||
|
||||
let eventString = "id: event1\r\ndata: {\"key\":\"value\"}\r\n\n"
|
||||
let sseEventData = eventString.data(using: .utf8)!
|
||||
|
||||
await MockURLProtocol.requestHandlerStorage.setHandler {
|
||||
[testEndpoint] (request: URLRequest) in
|
||||
#expect(request.url == testEndpoint)
|
||||
#expect(request.httpMethod == "GET")
|
||||
#expect(request.value(forHTTPHeaderField: "Accept") == "text/event-stream")
|
||||
let response = HTTPURLResponse(
|
||||
url: testEndpoint, statusCode: 200, httpVersion: "HTTP/1.1",
|
||||
headerFields: ["Content-Type": "text/event-stream"])!
|
||||
return (response, sseEventData)
|
||||
}
|
||||
|
||||
try await transport.connect()
|
||||
try await Task.sleep(for: .milliseconds(100))
|
||||
|
||||
let stream = await transport.receive()
|
||||
var iterator = stream.makeAsyncIterator()
|
||||
|
||||
let expectedData = #"{"key":"value"}"#.data(using: .utf8)!
|
||||
let receivedData = try await iterator.next()
|
||||
|
||||
#expect(receivedData == expectedData)
|
||||
}
|
||||
#endif // !canImport(FoundationNetworking)
|
||||
|
|
|
|||
Loading…
Reference in a new issue