Skip to content

Commit a176fc4

Browse files
authored
Init with request (#18)
* Allow initializing WebSocket with a URLRequest * Use WebSocketKit utilities and add license info * Update dependencies * Update README
1 parent 32de0d7 commit a176fc4

File tree

12 files changed

+538
-165
lines changed

12 files changed

+538
-165
lines changed

.github/workflows/ci.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@ on: push
44

55
jobs:
66
test:
7-
runs-on: macos-13
7+
runs-on: macos-14
88

99
steps:
10-
- uses: actions/checkout@v3
10+
- uses: actions/checkout@v4
1111
- name: Select Xcode 15
12-
run: sudo xcode-select -s /Applications/Xcode_15.0.app
12+
run: sudo xcode-select -s /Applications/Xcode_15.4.app
1313
- name: Test
1414
run: swift test

LICENSE.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
The MIT License (MIT)
2+
3+
Copyright (c) 2024 Shareup Software Corporation
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

Package.resolved

Lines changed: 25 additions & 16 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Package.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ let package = Package(
2424
),
2525
.package(
2626
url: "https://github.com/vapor/websocket-kit.git",
27-
from: "2.14.0"
27+
from: "2.15.0"
2828
),
2929
.package(
3030
url: "https://github.com/apple/swift-nio.git",

README.md

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@
22

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

5-
A concrete implementation of a WebSocket client implemented by wrapping Apple's [`NWConnection`](https://developer.apple.com/documentation/network/nwconnection).
5+
A concrete implementation of a WebSocket client implemented by wrapping Apple's [`URLSessionWebSocketTask`](https://developer.apple.com/documentation/foundation/urlsessionwebsockettask).
66

77
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 WebSockets into your code for testing purposes.
88

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.
9+
The actual implementation is `SystemWebSocket`, but this type is not publicly accessible. Instead, you can access it via `WebSocket.system(url:)` or `WebSocket.system(request:)`. `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.
1010

1111
`WebSocket` exposes a simple API and makes heavy use of [Swift Concurrency](https://developer.apple.com/documentation/swift/swift_standard_library/concurrency).
1212

@@ -49,3 +49,7 @@ try await socket.close()
4949

5050
1. In your Terminal, navigate to the `websocket-apple` directory
5151
2. Run the tests using `swift test`
52+
53+
## Notices
54+
55+
This library includes code from [WebSocketKit](https://github.com/vapor/websocket-kit) and [SwiftNIO](https://github.com/apple/swift-nio), the use of which depends on their licenses.

Sources/WebSocket/SystemURLSession.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,14 @@ import Foundation
22
import Synchronized
33

44
func webSocketTask(
5-
for url: URL,
5+
for request: URLRequest,
66
options: WebSocketOptions,
77
onOpen: @escaping @Sendable () async -> Void,
88
onClose: @escaping @Sendable (WebSocketCloseCode, Data?) async -> Void
99
) -> URLSessionWebSocketTask {
1010
let session = session(for: options)
1111

12-
let task = session.webSocketTask(with: url)
12+
let task = session.webSocketTask(with: request)
1313
task.maximumMessageSize = options.maximumMessageSize
1414

1515
let delegate = session.delegate as! Delegate

Sources/WebSocket/SystemWebSocket.swift

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@ final actor SystemWebSocket: Publisher {
2424
return true
2525
} }
2626

27-
nonisolated let url: URL
27+
nonisolated var url: URL { request.url! }
28+
nonisolated let request: URLRequest
2829
nonisolated let options: WebSocketOptions
2930
nonisolated let onOpen: WebSocketOnOpen
3031
nonisolated let onClose: WebSocketOnClose
@@ -49,12 +50,12 @@ final actor SystemWebSocket: Publisher {
4950
)
5051

5152
init(
52-
url: URL,
53+
request: URLRequest,
5354
options: WebSocketOptions = .init(),
5455
onOpen: @escaping WebSocketOnOpen = {},
5556
onClose: @escaping WebSocketOnClose = { _ in }
5657
) async throws {
57-
self.url = url
58+
self.request = request
5859
self.options = options
5960
self.onOpen = onOpen
6061
self.onClose = onClose
@@ -180,7 +181,7 @@ private extension SystemWebSocket {
180181
func connect() throws {
181182
precondition(isUnopened)
182183
let task = webSocketTask(
183-
for: url,
184+
for: request,
184185
options: options,
185186
onOpen: { [weak self] in await self?.doOpen() },
186187
onClose: { [weak self] closeCode, reason async in

Sources/WebSocket/WebSocket.swift

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,9 +104,24 @@ public extension WebSocket {
104104
options: WebSocketOptions = .init(),
105105
onOpen: @escaping WebSocketOnOpen = {},
106106
onClose: @escaping WebSocketOnClose = { _ in }
107+
) async throws -> Self {
108+
try await system(
109+
request: URLRequest(url: url),
110+
options: options,
111+
onOpen: onOpen,
112+
onClose: onClose
113+
)
114+
}
115+
116+
/// System WebSocket implementation powered by `URLSessionWebSocketTask`.
117+
static func system(
118+
request: URLRequest,
119+
options: WebSocketOptions = .init(),
120+
onOpen: @escaping WebSocketOnOpen = {},
121+
onClose: @escaping WebSocketOnClose = { _ in }
107122
) async throws -> Self {
108123
let ws = try await SystemWebSocket(
109-
url: url,
124+
request: request,
110125
options: options,
111126
onOpen: onOpen,
112127
onClose: onClose

0 commit comments

Comments
 (0)