connectrpc / connect-swift

The Swift implementation of Connect: Protobuf RPC that works.
https://connectrpc.com/docs/swift/getting-started
Apache License 2.0
98 stars 20 forks source link

Revamp interceptors to be protocol-based and expose typed messages #208

Closed rebello95 closed 1 year ago

rebello95 commented 1 year ago

This PR revamps Connect-Swift's interceptor implementation to:

The most notable changes are in UnaryInterceptor.swift and StreamInterceptor.swift. The new interceptor interfaces are:

public protocol UnaryInterceptor: Interceptor {
    /// Observe and/or mutate a typed request message to be sent to the server.
    ///
    /// Order of invocation during a request's lifecycle: 1
    ///
    /// - parameter request: The typed request and message to be sent.
    /// - parameter proceed: Closure which must be called to pass (potentially altered) request
    ///                      to the next interceptor.
    @Sendable
    func handleUnaryRequest<Message: ProtobufMessage>(
        _ request: HTTPRequest<Message>,
        proceed: @escaping @Sendable (Result<HTTPRequest<Message>, ConnectError>) -> Void
    )

    /// Observe and/or mutate a raw (serialized) request to be sent to the server.
    ///
    /// Order of invocation during a request's lifecycle: 2 (after `handleUnaryRequest()`)
    ///
    /// - parameter request: The raw (serialized) request to be sent.
    /// - parameter proceed: Closure which must be called to pass (potentially altered) request
    ///                      to the next interceptor.
    @Sendable
    func handleUnaryRawRequest(
        _ request: HTTPRequest<Data?>,
        proceed: @escaping @Sendable (Result<HTTPRequest<Data?>, ConnectError>) -> Void
    )

    /// Observe and/or mutate a raw (serialized) response received from the server.
    ///
    /// Order of invocation during a request's lifecycle: 3
    ///
    /// - parameter response: The raw (serialized) response that was received.
    /// - parameter proceed: Closure which must be called to pass (potentially altered) response
    ///                      to the next interceptor.
    @Sendable
    func handleUnaryRawResponse(
        _ response: HTTPResponse,
        proceed: @escaping @Sendable (HTTPResponse) -> Void
    )

    /// Observe and/or mutate a typed (deserialized) response received from the server.
    ///
    /// Order of invocation during a request's lifecycle: 4 (after `handleUnaryRawResponse()`)
    ///
    /// - parameter response: The typed (deserialized) response received from the server.
    /// - parameter proceed: Closure which must be called to pass (potentially altered) response
    ///                      to the next interceptor.
    @Sendable
    func handleUnaryResponse<Message: ProtobufMessage>(
        _ response: ResponseMessage<Message>,
        proceed: @escaping @Sendable (ResponseMessage<Message>) -> Void
    )
}
/// Interceptor that can observe and/or mutate streams.
public protocol StreamInterceptor: Interceptor {
    /// Observe and/or mutate the creation of a stream and its associated headers.
    ///
    /// Order of invocation during a stream's lifecycle: 1
    ///
    /// - parameter request: The request being used to create the stream.
    /// - parameter proceed: Closure which must be called to pass (potentially altered) request
    ///                      to the next interceptor.
    @Sendable
    func handleStreamStart(
        _ request: HTTPRequest<Void>,
        proceed: @escaping @Sendable (Result<HTTPRequest<Void>, ConnectError>) -> Void
    )

    /// Observe and/or mutate a typed message to be sent to the server over a stream.
    ///
    /// Order of invocation during a stream's lifecycle: 2 (after `handleStreamStart()`)
    ///
    /// - parameter input: The message to be sent over the stream.
    /// - parameter proceed: Closure which must be called to pass (potentially altered) message
    ///                      to the next interceptor.
    @Sendable
    func handleStreamInput<Message: ProtobufMessage>(
        _ input: Message,
        proceed: @escaping @Sendable (Message) -> Void
    )

    /// Observe and/or mutate a message's serialized raw data to be sent to the server
    /// over a stream.
    ///
    /// Order of invocation during a stream's lifecycle: 3 (after `handleStreamInput()`)
    ///
    /// - parameter input: The raw data to be sent over the stream.
    /// - parameter proceed: Closure which must be called to pass (potentially altered) data
    ///                      to the next interceptor.
    @Sendable
    func handleStreamRawInput(
        _ input: Data,
        proceed: @escaping @Sendable (Data) -> Void
    )

    /// Observe and/or mutate a raw result (such as a serialized message) received from the server
    /// over a stream.
    ///
    /// Order of invocation during a stream's lifecycle: 4
    ///
    /// - parameter result: The raw result that was received over the stream.
    /// - parameter proceed: Closure which must be called to pass (potentially altered) result
    ///                      to the next interceptor.
    @Sendable
    func handleStreamRawResult(
        _ result: StreamResult<Data>,
        proceed: @escaping @Sendable (StreamResult<Data>) -> Void
    )

    /// Observe and/or mutate a typed deserialized result received from the server over a stream.
    ///
    /// Order of invocation during a stream's lifecycle: 5 (after `handleStreamRawResult()`)
    ///
    /// - parameter result: The deserialized result that was received over the stream.
    /// - parameter proceed: Closure which must be called to pass (potentially altered) message
    ///                      to the next interceptor.
    @Sendable
    func handleStreamResult<Message: ProtobufMessage>(
        _ result: StreamResult<Message>,
        proceed: @escaping @Sendable (StreamResult<Message>) -> Void
    )
}