Skip to content

Commit bf9ff2b

Browse files
authored
Use NWConnection instead of URLSessionWebSocketTask (#10)
- Replace URLSessionWebSocketTask with NWConnection - Conform to published behavior of web browsers' WebSocket - Add support for Swift Concurrency
1 parent 4532e16 commit bf9ff2b

20 files changed

Lines changed: 1507 additions & 946 deletions

.github/workflows/ci.yml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
on: push
2+
3+
jobs:
4+
test:
5+
runs-on: macos-12
6+
7+
steps:
8+
- uses: actions/checkout@v2
9+
# Available environments: https://github.com/actions/virtual-environments/blob/main/images/macos/macos-12-Readme.md#xcode
10+
- run: xcversion select 13.3
11+
- run: swift package resolve
12+
- run: swift test --skip-update

.github/workflows/swift.yml

Lines changed: 0 additions & 20 deletions
This file was deleted.

.swiftformat

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
--funcattributes prev-line
22
--minversion 0.47.2
3-
--maxwidth 100
3+
--maxwidth 96
44
--typeattributes prev-line
55
--wraparguments before-first
6+
--wrapparameters before-first
67
--wrapcollections before-first
8+
--xcodeindentation enabled

Package.resolved

Lines changed: 0 additions & 34 deletions
This file was deleted.

Package.swift

Lines changed: 7 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -4,36 +4,23 @@ import PackageDescription
44
let package = Package(
55
name: "WebSocket",
66
platforms: [
7-
.macOS(.v10_15), .iOS(.v13), .tvOS(.v13), .watchOS(.v6),
7+
.macOS(.v11), .iOS(.v14), .tvOS(.v14), .watchOS(.v7),
88
],
99
products: [
1010
.library(
1111
name: "WebSocket",
1212
targets: ["WebSocket"]
13-
)],
14-
dependencies: [
15-
.package(
16-
name: "Synchronized",
17-
url: "https://github.com/shareup/synchronized.git",
18-
from: "3.0.0"
1913
),
20-
.package(
21-
name: "WebSocketProtocol",
22-
url: "https://github.com/shareup/websocket-protocol.git",
23-
from: "2.3.2"
24-
),
25-
.package(name: "swift-nio", url: "https://github.com/apple/swift-nio.git", from: "2.0.0")],
14+
],
15+
dependencies: [],
2616
targets: [
2717
.target(
2818
name: "WebSocket",
29-
dependencies: ["Synchronized", "WebSocketProtocol"]),
19+
dependencies: []
20+
),
3021
.testTarget(
3122
name: "WebSocketTests",
32-
dependencies: [
33-
.product(name: "NIO", package: "swift-nio"),
34-
.product(name: "NIOHTTP1", package: "swift-nio"),
35-
.product(name: "NIOWebSocket", package: "swift-nio"),
36-
"WebSocket",
37-
])
23+
dependencies: ["WebSocket"]
24+
),
3825
]
3926
)

README.md

Lines changed: 22 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2,31 +2,32 @@
22

33
## _(macOS, iOS, iPadOS, tvOS, and watchOS)_
44

5-
A concrete implementation of a WebSocket client implemented by wrapping Apple's `URLSessionWebSocketTask` and conforming to [`WebSocketProtocol`](https://github.com/shareup/websocket-protocol). `WebSocket` exposes a simple API and conforms to Apple's Combine [`Publisher`](https://developer.apple.com/documentation/combine/publisher).
5+
A concrete implementation of a WebSocket client implemented by wrapping Apple's [`NWConnection`](https://developer.apple.com/documentation/network/nwconnection).
6+
7+
The public "interface" of `WebSocket` is a simple struct whose public "methods" are exposed as closures. The reason for this design is to make it easy to inject fake `WebSocket`s into your code for testing purposes.
8+
9+
The actual implementation is `SystemWebSocket`, but this type is not publicly accessible. Instead, you can access it via `WebSocket.system(url:)`. `SystemWebSocket` tries its best to mirror the documented behavior of web browsers' [`WebSocket`](http://developer.mozilla.org/en-US/docs/Web/API/WebSocket). Please report any deviations as bugs.
10+
11+
`WebSocket` exposes a simple API, makes heavy use of [Swift Concurrency](https://developer.apple.com/documentation/swift/swift_standard_library/concurrency), and conforms to Apple's Combine [`Publisher`](https://developer.apple.com/documentation/combine/publisher).
612

713
## Usage
814

915
```swift
10-
let socket = WebSocket(url: url(49999))
11-
12-
let sub = socket.sink(
13-
receiveCompletion: { print("Socket closed: \(String(describing: $0))") },
14-
receiveValue: { (result) in
15-
switch result {
16-
case .success(.open):
17-
socket.send("First message")
18-
case .success(.string(let incoming)):
19-
print("Received \(incoming)")
20-
case .failure:
21-
socket.close()
22-
default:
23-
break
24-
}
25-
}
26-
)
27-
defer { sub.cancel() }
28-
29-
socket.connect()
16+
// `WebSocket` starts connecting to the specified `URL` immediately.
17+
let socket = WebSocket.system(url: url(49999))
18+
19+
// Wait for `WebSocket` to be ready to send and receive messages.
20+
try await socket.open()
21+
22+
// Send a message to the server
23+
try await socket.send(.text("hello"))
24+
25+
// Receive messages from the server
26+
for await message in socket.messages {
27+
print(message)
28+
}
29+
30+
try await socket.close()
3031
```
3132

3233
## Tests

0 commit comments

Comments
 (0)