首页 > 解决方案 > 如何在 iOS 应用中使用 swift 进行 gRPC 调用

问题描述

我正在尝试使用https://github.com/grpc/grpc-swift访问一些谷歌云 RPC API

我所做的与Natural Language Example非常相似。
我能够从 master 分支上获得一个与 0.10.0 版本一起使用的版本,但自述文件说这个分支已被弃用,应该使用“nio”分支。
不幸的是,示例代码与项目不同步,无法编译。我尽力修复代码,但我无法让它工作。

class NaturalLanguageRPCTests {
    let authToken : String
    var service : Google_Cloud_Language_V1_LanguageServiceServiceClient?
    var clientConnection : ClientConnection?
    let eventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: 1)

    init(authToken: String) {
        self.authToken = authToken
    }

    func createService() {
        let host = "language.googleapis.com"
        let port = 443

        let tls = ClientConnection.Configuration.TLS(configuration: TLSConfiguration.forClient(applicationProtocols: ["h2"]))
        let configuration = ClientConnection.Configuration(target: .hostAndPort(host, port),
                                                           eventLoopGroup: self.eventLoopGroup,
                                                           errorDelegate: self,
                                                           connectivityStateDelegate: self,
                                                           tls: tls)
                                                           //connectionBackoff: ConnectionBackoff?)
        self.clientConnection = ClientConnection(configuration: configuration)
    }



    func makeRPCCall() {
        guard let connection = self.clientConnection, connection.connectivity.state == .ready else {
            fatalError()
        }
        if self.service == nil {
            self.service = Google_Cloud_Language_V1_LanguageServiceServiceClient(connection: connection)
        }
        guard let service = self.service else {
            print("SERVICE HASN'T BEEN CREATED YET")
            return
        }
        // Use CallOptions to send the auth token (necessary) and set a custom timeout (optional).
        let http_headers = HTTPHeaders([("authorization", "Bearer " + self.authToken)])
        let headers = HPACKHeaders(httpHeaders: http_headers)
        let timeout = try! GRPCTimeout.seconds(30)
        let callOptions = CallOptions(customMetadata: headers, timeout: timeout)
        print("CALL OPTIONS\n\(callOptions)\n")

        // Construct the API request.
        var document = Google_Cloud_Language_V1_Document()
        document.type = .plainText
        document.content = "The Caterpillar and Alice looked at each other for some time in silence: at last the Caterpillar took the hookah out of its mouth, and addressed her in a languid, sleepy voice. `Who are you?' said the Caterpillar."

        var features = Google_Cloud_Language_V1_AnnotateTextRequest.Features()
        features.extractSyntax = true
        features.extractEntities = true
        features.extractDocumentSentiment = true
        features.extractEntitySentiment = true
        features.classifyText = true

        var request = Google_Cloud_Language_V1_AnnotateTextRequest()
        request.document = document
        request.features = features
        print("REQUEST MESSAGE\n\(request)")


        // Create/start the API call.
        let call = service.annotateText(request, callOptions: callOptions)
        call.response.whenSuccess { response in
            print("CALL SUCCEEDED WITH RESPONSE\n\(response)")
        }
        call.response.whenFailure { error in
            print("CALL FAILED WITH ERROR\n\(error)")
        }
        do {
            // wait() on the status to stop the program from exiting.
            let status = try call.status.wait()
            print("CALL STATUS\n\(status)")
        } catch {
            print("EXAMPLE FAILED WITH ERROR\n\(error)")
        }
    }
}

当我调用 test.createService()并监视连接的状态时,它会转换为“就绪”,因此我假设正在建立连接。

但是,当我打电话时,test.makeRPCCall()我得到了错误。从日志:

2019-11-29T20:10:23-0800 info: path=/google.cloud.language.v1.LanguageService/AnnotateText 
request_id=0EAC0A92-2842-4D5A-BC94-B0BD4D6171EF starting rpc

CALL STATUS
unimplemented (12): invalid HTTP status: Not Found
2019-11-29T20:10:48-0800 info: duration_ms=46 request_id=0EAC0A92-2842-4D5A-BC94-B0BD4D6171EF status_code=12 rpc call finished
CALL FAILED WITH ERROR
unimplemented (12): invalid HTTP status: Not Found


我确定这很简单,我做错了,但我无法让它为我的生活工作。如果有人对此有所了解,我将不胜感激。谢谢。

标签: iosswiftgrpc

解决方案


回答我自己的问题。

  1. grpc-swift 中存在一个已修复的错误。那里的开发人员的响应时间真棒!!!因此,您必须从 nio 分支获取最新版本,因为还没有带有修复的版本。
  2. 这是工作代码

    class NaturalLanguageRPCTests {
    let authToken : String
    var service : Google_Cloud_Language_V1_LanguageServiceServiceClient?
    var clientConnection : ClientConnection?
    let eventLoopGroup = MultiThreadedEventLoopGroup(numberOfThreads: 1)
    
    init(authToken: String) {
        self.authToken = authToken
    }
    
    func createService() {
        let host = "language.googleapis.com"
        let port = 443
    
        let configuration = ClientConnection.Configuration(
            target: .hostAndPort(host, port),
            eventLoopGroup: eventLoopGroup,
            tls: .init()
        )
        self.clientConnection = ClientConnection(configuration: configuration)
    }
    
    func makeRPCCall() {
        guard let connection = self.clientConnection, connection.connectivity.state == .ready else {
            fatalError()
        }
        if self.service == nil {
            self.service = Google_Cloud_Language_V1_LanguageServiceServiceClient(connection: connection)
        }
        guard let service = self.service else {
            print("SERVICE HASN'T BEEN CREATED YET")
            return
        }
        // Use CallOptions to send the auth token (necessary) and set a custom timeout (optional).
        let headers: HPACKHeaders = ["authorization": "Bearer \(authToken)"]
        let callOptions = CallOptions(customMetadata: headers, timeout: .seconds(rounding: 30))
        print("CALL OPTIONS\n\(callOptions)\n")
    
        // Construct the API request.
        var document = Google_Cloud_Language_V1_Document()
        document.type = .plainText
        document.content = "The Caterpillar and Alice looked at each other for some time in silence: at last the Caterpillar took the hookah out of its mouth, and addressed her in a languid, sleepy voice. `Who are you?' said the Caterpillar."
    
        var features = Google_Cloud_Language_V1_AnnotateTextRequest.Features()
        features.extractSyntax = true
        features.extractEntities = true
        features.extractDocumentSentiment = true
        features.extractEntitySentiment = true
        features.classifyText = true
    
        var request = Google_Cloud_Language_V1_AnnotateTextRequest()
        request.document = document
        request.features = features
        print("REQUEST MESSAGE\n\(request)")
    
    
        // Create/start the API call.
        let call = service.annotateText(request, callOptions: callOptions)
        call.response.whenSuccess { response in
            print("CALL SUCCEEDED WITH RESPONSE\n\(response)")
        }
        call.response.whenFailure { error in
            print("CALL FAILED WITH ERROR\n\(error)")
        }
        do {
            // wait() on the status to stop the program from exiting.
            let status = try call.status.wait()
            print("CALL STATUS\n\(status)")
        } catch {
            print("EXAMPLE FAILED WITH ERROR\n\(error)")
        }
    }}
    

推荐阅读