根据 Apache 软件基金会(ASF)的一个或多个贡献者许可协议获得许可。有关版权所有权的更多信息,请参见随本作品分发的 NOTICE 文件。 ASF 根据 Apache 许可证 2.0 版(“许可证”)向您授予本文件的许可;除非遵守许可证,否则您不得使用本文件。您可以在以下位置获得许可证副本:
https://apache.ac.cn/licenses/LICENSE-2.0
除非适用法律要求或书面同意,否则软件是按“原样”分发的,没有任何形式的明示或暗示的担保或条件。 有关许可证下特定权限和限制的完整信息,请参阅许可证。
由 FiscalNote, Inc 提供
swift build
swift test
将以下内容添加到您的 podfile 中
pod 'Thrift-swift3', :git => 'git@github.com:apache/thrift.git', :branch => 'master'
不幸的是,由于 SPM 的一些限制,Package manifest 和 Sources 目录必须位于项目的根目录中。 为了暂时解决这个问题,您可以使用这个镜像仓库。 将以下内容添加到您的 Package.swift 中
dependencies: [
.Package(url: "https://github.com/apocolipse/Thrift-Swift.git", majorVersion: 1)
]
您可以使用以下命令为 Swift 3 编译 IDL 源代码
thrift --gen swift thrift_file
let transport = TSocketTransport(hostname: "localhost", port: 9090)!
// var proto = TCompactProtocol(transport: transport)
let proto = TBinaryProtocol(on: transport)
// var client = HermesClient(inoutProtocol: proto)
let client = ThriftTestClient(inoutProtocol: proto)
do {
try client.testVoid()
} catch let error {
print("\(error)")
}
TError
类型都有一个嵌套的 ErrorCode
枚举,以及一些在需要时的额外特性。TTransport
在值类型化的 Data
上运行,而不是引用类型化的 NSData
或 UnsafeBufferPointer
。func readString() throws -> String
func writeString(_ val: String) throws
已被重命名以消除冗余单词
func read() throws -> String
func write(_ val: String) throws
NSURLConnection
的 THTTPTransport
,因为它已弃用,并且在 Linux 的 Swift 3 中根本不可用。 来自 Swift2/Cocoa 库的 THTTPSessionTransport
,它使用 NSURLSession
已被重命名为 THTTPTransport
用于此库,并利用 URLSession
,提供同步(使用信号量)和异步行为。标志 | 描述 |
---|---|
async_clients | 生成通过块语法异步调用的客户端。 异步类附加 _Async |
no_strict* | 生成非严格结构体 |
debug_descriptions | 允许使用 debugDescription,以便应用程序可以通过类别/扩展添加描述 |
log_unexpected | 每次遇到意外的字段 ID 或类型时都记录。 |
safe_enums | 生成具有未知 case 的枚举类型,以处理未指定的值,而不是抛出序列化错误 |
*大多数 thrift 库允许 Structs 的空初始化,使用 nil/null/None(Python 和 Node 生成器)初始化 required
字段。 另一方面,Swift 要求初始化程序初始化所有非 Optional 字段,因此 Swift 3 生成器不提供默认值(与 Swift 2/Cocoa 生成器不同)。 在其他语言中,这允许在标记为 required
的字段中发送 NULL 值,因此将在尝试验证字段的 Swift 客户端中抛出错误。 此处的 no_strict
选项将忽略验证检查,并且行为类似于 Swift2/Cocoa 生成器,并使用空初始化程序初始化必需字段(如果可能)。
import PerfectLib
import PerfectHTTP
import PerfectHTTPServer
import Dispatch
let logQueue = DispatchQueue(label: "log", qos: .background, attributes: .concurrent)
let pQueue = DispatchQueue(label: "log", qos: .userInitiated, attributes: .concurrent)
class TPerfectServer<InProtocol: TProtocol, OutProtocol: TProtocol> {
private var server = HTTPServer()
private var processor: TProcessor
init(address: String? = nil,
path: String? = nil,
port: Int,
processor: TProcessor,
inProtocol: InProtocol.Type,
outProtocol: OutProtocol.Type) throws {
self.processor = processor
if let address = address {
server.serverAddress = address
}
server.serverPort = UInt16(port)
var routes = Routes()
var uri = "/"
if let path = path {
uri += path
}
routes.add(method: .post, uri: uri) { request, response in
pQueue.async {
response.setHeader(.contentType, value: "application/x-thrift")
let itrans = TMemoryBufferTransport()
if let bytes = request.postBodyBytes {
let data = Data(bytes: bytes)
itrans.reset(readBuffer: data)
}
let otrans = TMemoryBufferTransport(flushHandler: { trans, buff in
let array = buff.withUnsafeBytes {
Array<UInt8>(UnsafeBufferPointer(start: $0, count: buff.count))
}
response.status = .ok
response.setBody(bytes: array)
response.completed()
})
let inproto = InProtocol(on: itrans)
let outproto = OutProtocol(on: otrans)
do {
try processor.process(on: inproto, outProtocol: outproto)
try otrans.flush()
} catch {
response.status = .badRequest
response.completed()
}
}
}
server.addRoutes(routes)
}
func serve() throws {
try server.start()
}
}
class ServiceHandler : Service {
...
}
let server = try? TPerfectServer(port: 9090,
processor: ServiceProcessor(service: ServiceHandler()),
inProtocol: TBinaryProtocol.self,
outProtocol: TBinaryProtocol.self)
try? server?.serve()