Skip to content

Latest commit

 

History

History
61 lines (44 loc) · 2.48 KB

README.md

File metadata and controls

61 lines (44 loc) · 2.48 KB

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.4 Hummingbird gRPC supports Swift 5.10+ and requires Hummingbird 2.0.0-rc.2 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.

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 the channel will be handled directly by grpc-swift, if it is negotiated as vanilla h2 (HTTP/2), http/1.1, or as anything else it will be handled by Hummingbird.

Currently this requires forking grpc-swift to make HTTP2ToRawGRPCServerCodec public, and copying the HTTP2ChannelInitializer from HummingbirdHTTP2, it is hoped both of the changes can be made upstream, allowing Hummingbird gRPC to work with the sources directly.

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()