Skip to content

unsignedapps/hummingbird-grpc

Repository files navigation

Hummingbird gRPC

This is an early preview / proof of concept providing gRPC support for Hummingbird using grpc-swift. It has not been tested with production workloads yet, so it definitely not ready for use.

Status

Hummingbird gRPC supports:

  • gRPC using Protocol Buffers over HTTP/2.
  • Unary, client streaming, server streaming, and bidirectional streaming calls.
  • grpc-swift Server interceptors.
  • Async and SwiftNIO EventLoop based routing.
  • grpc-swift generated server providers.
  • proto2 and proto3.

Note

From version 0.0.5 Hummingbird gRPC supports Swift 6.0+ and requires Hummingbird 2.15.0+ and grpc-swift 1.23.0+.

Hummingbird gRPC does not currently support:

  • gRPC using JSON or other serialization formats.
  • gRPC Web (HTTP/1.1).
  • Hummingbird middleware with gRPC endpoints.

Implementation Details

Hummingbird gRPC uses the TLS Application-Later Protocol Negotiation to decide how to handle an incoming HTTP/2 channel. If it is negoiateed as grpc-exp or as h2 (HTTP/2) with a Content-Type of application/grpc the channel will be handled directly by grpc-swift, if it is negotiated as h2 (HTTP/2), with any other Content Type, as http/1.1, or as anything else it will be handled by Hummingbird.

Currently this requires forking grpc-swift to make HTTP2ToRawGRPCServerCodec public, it was hoped this change could be upstreamed so we could work directly with the official source but unfortunately grpc-swift 2.0.0 has gone in a different direction but it has embedded the their ways of working. We'd need to fork grpc-swift-nio-transport instead of the whole thing, but a fork is a fork.

On the Hummingbird side, our channel handling is

Usage

let app = HBApplication()

// Enable support for gRPC. You will need to configure TLS as well.
app.gRPC.addUpgrade(configuration: .init(), tlsConfiguration: .makeServerConfiguration())

// Add service providers that were generated by grpc-swift's protoc plugin
app.gRPC.addServiceProvider(EchoProvider())

// Alternatively, declare your gRPC endpoints directly using SwiftNIO EventLoop-based futures
app.gRPC.onUnary("echo.Echo", "Get", requestType: Echo_EchoRequest.self) { request, context in
    let response = Echo_EchoResponse.with {
        $0.text = "Swift echo get: " + request.text
    }
    return context.eventLoop.makeSucceededFuture(response)
}

// Or using async closures
app.gRPC.onUnary("echo.Echo", "Get", requestType: Echo_EchoRequest.self) { request, context async in
    Echo_EchoResponse.with {
        $0.text = "Swift echo get: " + request.text
    }
}

// Start the server like normal
app.start()
app.wait()

About

gRPC support for Hummingbird using grpc-swift

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages