Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Convert WebSocket URLRequest to RFC8441 HTTPRequest #92

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions Sources/HTTPTypesFoundation/URLRequest+HTTPTypes.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,23 @@ extension URLRequest {
/// Create a `URLRequest` from an `HTTPRequest`.
/// - Parameter httpRequest: The HTTP request to convert from.
public init?(httpRequest: HTTPRequest) {
// Translate an extended-CONNECT WebSocket request to the legacy form
if httpRequest.method == .connect && httpRequest.extendedConnectProtocol == "websocket" {
var legacyRequest = httpRequest
legacyRequest.method = .get
switch httpRequest.scheme?.lowercased() {
case "https":
legacyRequest.scheme = "wss"
case "http":
legacyRequest.scheme = "ws"
default:
break
}
legacyRequest.extendedConnectProtocol = nil
self.init(httpRequest: legacyRequest)
return
}

guard let url = httpRequest.url else {
return nil
}
Expand Down Expand Up @@ -63,6 +80,27 @@ extension URLRequest {
}
}
}

// Translate a legacy WebSocket request to the extended-CONNECT form
if method == .get, let scheme = request.scheme {
switch scheme.utf8.count {
case 3:
if scheme.lowercased() == "wss" {
request.method = .connect
request.scheme = "https"
request.extendedConnectProtocol = "websocket"
}
case 2:
if scheme.lowercased() == "ws" {
request.method = .connect
request.scheme = "http"
request.extendedConnectProtocol = "websocket"
}
default:
break
}
}

return request
}
}
Expand Down
16 changes: 16 additions & 0 deletions Tests/HTTPTypesFoundationTests/HTTPTypesFoundationTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,22 @@ final class HTTPTypesFoundationTests: XCTestCase {
XCTAssertEqual(request.headerFields[.init("x-foo")!], "Bar")
}

func testWebSocketRequest() throws {
let urlRequest = URLRequest(url: URL(string: "wss://www.example.com/")!)

let request = try XCTUnwrap(urlRequest.httpRequest)
XCTAssertEqual(request.method, .connect)
XCTAssertEqual(request.scheme, "https")
XCTAssertEqual(request.authority, "www.example.com")
XCTAssertEqual(request.path, "/")
XCTAssertEqual(request.extendedConnectProtocol, "websocket")

let urlRequestConverted = try XCTUnwrap(URLRequest(httpRequest: request))
XCTAssertEqual(urlRequestConverted.httpMethod, "GET")
XCTAssertEqual(urlRequestConverted.url, URL(string: "wss://www.example.com/"))
XCTAssertEqual(urlRequest, urlRequestConverted)
}

func testResponseToFoundation() throws {
let response = HTTPResponse(
status: .ok,
Expand Down