Skip to content

Commit

Permalink
Add web socket support
Browse files Browse the repository at this point in the history
  • Loading branch information
enums committed Jan 1, 2022
1 parent 3aa3a83 commit f81bf46
Show file tree
Hide file tree
Showing 5 changed files with 158 additions and 1 deletion.
3 changes: 2 additions & 1 deletion Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,12 @@ let package = Package(
.package(url: "https://github.com/PerfectlySoft/Perfect-Markdown.git", from: "3.0.0"),
.package(url: "https://github.com/PerfectlySoft/Perfect-Session.git", from: "3.0.0"),
.package(url: "https://github.com/PerfectlySoft/Perfect-Session-MySQL.git", from: "3.0.0"),
.package(url: "https://github.com/PerfectlySoft/Perfect-WebSockets.git", from: "3.0.0"),
.package(url: "https://github.com/onevcat/Rainbow", from: "3.0.0"),
],
targets: [
.target(name: "HezeDemo", dependencies: ["Heze"]),
.target(name: "Heze", dependencies: ["PerfectHTTPServer", "PerfectMustache", "PerfectCrypto", "PerfectMySQL", "PerfectCURL", "PerfectMarkdown", "PerfectSession", "PerfectSessionMySQL", "Rainbow", "Virgo"]),
.target(name: "Heze", dependencies: ["PerfectHTTPServer", "PerfectMustache", "PerfectCrypto", "PerfectMySQL", "PerfectCURL", "PerfectMarkdown", "PerfectSession", "PerfectSessionMySQL", "PerfectWebSockets", "Rainbow", "Virgo"]),
.target(name: "Virgo", dependencies: ["Rainbow"]),
]
)
44 changes: 44 additions & 0 deletions Sources/Heze/Socket/HezeSocketClient.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
//
// HezeSocketClient.swift
// Heze
//
// Created by Yuu Zheng on 2022/1/1.
//

import Foundation
import PerfectWebSockets

open class HezeSocketClient: HezeSocketHandler {

open override var socketProtocol: String? {
return nil
}

public var isConnected: Bool {
return socket?.isConnected ?? false
}

open override func receiveBytes(_ bytes: [UInt8]) -> HezeResponsable? {
return nil
}

public func sendMessage(_ msg: String) {
socket?.sendStringMessage(string: msg, final: true) { }
}

public func sendBytes(_ bytes: [UInt8]) {
socket?.sendBinaryMessage(bytes: bytes, final: true) { }
}

public func close() {
socket?.close()
}

public override func connected() {

}

public override func closed() {

}
}
89 changes: 89 additions & 0 deletions Sources/Heze/Socket/HezeSocketHandler.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
//
// HezeSocketHandler.swift
// Heze
//
// Created by Yuu Zheng on 2022/1/1.
//

import Foundation
import PerfectHTTP
import PerfectWebSockets

open class HezeSocketHandler: HezeHandler, WebSocketSessionHandler {

public var socket: WebSocket? = nil
public var buffer = [UInt8]()

open var socketProtocol: String? {
return nil
}

open override func handleThenComplete(_ req: HTTPRequest, _ res: HTTPResponse) {
request = req
defer {
request = nil
}
guard requestVaild() else {
handleInvaild(req, res)
return
}
WebSocketHandler(handlerProducer: { (request, protocols) -> WebSocketSessionHandler? in
if let socketProtocol = self.socketProtocol {
guard protocols.contains(socketProtocol) else {
return nil
}
return self
} else {
return self
}
}).handleRequest(request: req, response: res)
}

open func handleSession(request req: HTTPRequest, socket: WebSocket) {
if self.socket != socket {
self.socket = socket
connected()
}
socket.readBytesMessage { [weak self] bytes, opcodeType, final in
guard let self = self else {
return
}
guard let bytes = bytes else {
socket.close()
self.closed()
return
}
if let bytes = self.handleBytes(bytes, opcodeType: opcodeType, final: final, socket: socket)?.toBytes() {
socket.sendBinaryMessage(bytes: bytes, final: final) {
self.handleSession(request: req, socket: socket)
}
} else {
self.handleSession(request: req, socket: socket)
}
}
}

open func handleBytes(_ bytes: [UInt8], opcodeType: WebSocket.OpcodeType, final: Bool, socket: WebSocket) -> HezeResponsable? {
buffer.append(contentsOf: bytes)
if final {
defer {
buffer.removeAll(keepingCapacity: false)
}
return receiveBytes(buffer)
} else {
return nil
}
}

open func receiveBytes(_ bytes: [UInt8]) -> HezeResponsable? {
return nil
}

public func connected() {

}

public func closed() {

}
}
19 changes: 19 additions & 0 deletions Sources/Heze/View/HezeResponsable.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import PerfectHTTP

public protocol HezeResponsable {
func setBody(for res: HTTPResponse)
func toBytes() -> [UInt8]?
}

public func HezeResponse(_ success: Bool, _ msg: String? = nil, data: JSON? = nil) -> JSON {
Expand All @@ -30,6 +31,13 @@ extension String: HezeResponsable {
res.setHeader(.contentLength, value: "\(self.lengthOfBytes(using: .utf8))")
}

public func toBytes() -> [UInt8]? {
guard let data = self.data(using: .utf8) else {
return nil
}
return [UInt8](data)
}

}

extension Array: HezeResponsable where Element == UInt8 {
Expand All @@ -39,11 +47,22 @@ extension Array: HezeResponsable where Element == UInt8 {
res.setHeader(.contentLength, value: "\(self.count)")
}

public func toBytes() -> [UInt8]? {
return self
}

}

extension JSON: HezeResponsable {

public func setBody(for res: HTTPResponse) {
self.rawString(.utf8, options: .init(rawValue: 0))?.setBody(for: res)
}

public func toBytes() -> [UInt8]? {
guard let data = try? self.rawData() else {
return nil
}
return [UInt8](data)
}
}
4 changes: 4 additions & 0 deletions Sources/HezeDemo/Base/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ class AppDelegate: HezeAppDelegate {
"student": [
.get: StudentListView.meta,
.post: StudentAddApi.meta,
],

"socket": [
.get: HezeSocketClient.meta,
]
]
}
Expand Down

0 comments on commit f81bf46

Please sign in to comment.