QGrpcInterceptorChain Class | Qt GRPC | Qt 6.11.1
Description: Stores and manages a sequence of interceptors.

- Qt 6.11
- Qt GRPC
- C++ Classes
- QGrpcInterceptorChain
- Qt 6.11.1 Reference Documentation

# QGrpcInterceptorChain Class

Stores and manages a sequence of interceptors. More...

Header: | `#include <QGrpcInterceptorChain>`
CMake: | `find_package(Qt6 REQUIRED COMPONENTS Grpc)` `target_link_libraries(mytarget PRIVATE Qt6::Grpc)`
Since: | Qt 6.11

- List of all members, including inherited members
- QGrpcInterceptorChain is part of Qt GRPC Interceptors.

## Public Functions

| QGrpcInterceptorChain()
| ~QGrpcInterceptorChain()
bool | add(T *interceptor)
bool | add(std::unique_ptr<T> &&interceptor)
QtGrpc::InterceptorCapabilities | capabilities() const
QtGrpc::InterceptorCapabilities | capabilitiesAt(qsizetype index) const
void | clear()
bool | empty() const
bool | hasHandlerFor(QtGrpc::InterceptorCapability cap) const
bool | isEmpty() const
bool | set(Ts *... interceptors)
bool | set(std::unique_ptr<Ts> &&... interceptors)
qsizetype | size() const
void | swap(QGrpcInterceptorChain &other)

## Detailed Description

QGrpcInterceptorChain stores interceptor instances that observe or modify different stages of an RPC. The chain is passed to a channel during construction, and the channel owns the chain for the remainder of its lifetime.

As an RCP progresses through its lifecycle, the channel invokes the interceptors stored in the chain at the corresponding interception points.

Interceptors are added to the chain in a defined order. The order is significant and determines how interceptors are invoked during outbound and inbound stages of an RPC. For details, see the Direction and flow section of the Qt GRPC Interceptors Overview.

Interceptors can be added using two primary ownership models:

- Owning: Add interceptors using `std::unique_ptr<T>`. On success, the chain takes ownership and destroys the interceptors when the chain (and therefore the channel) is destroyed.
- Non-owning: Add interceptors using raw pointers `T*`. The chain does not take ownership. The caller must ensure that interceptor objects remain valid for as long as the channel may invoke them.

Both models can be combined within the same chain. While supported, mixing owning and non-owning interceptors requires care to ensure that non-owning interceptors outlive all channels that may use them.

Note: QGrpcInterceptorChain is not copyable and can only be moved.

See also QtGrpc::InterceptorCapability.

## Member Function Documentation

### QGrpcInterceptorChain::QGrpcInterceptorChain()

Constructs an empty interceptor chain.

### `[noexcept]` QGrpcInterceptorChain::~QGrpcInterceptorChain()

Destroys the interceptor chain.

### template <typename T, QtGrpcPrivate::if_interceptor<T> = true> bool QGrpcInterceptorChain::add(T *interceptor)

Adds interceptor to the chain without taking ownership.

Returns `true` if the interceptor was added; otherwise returns `false`.

When setting interceptors by raw pointer, the caller retains ownership. The QGrpcInterceptorChain stores non-owning references to the provided interceptors.

The interceptor chain is transferred to and owned by the channel. As a result, all interceptor objects must remain valid for the entire lifetime of the channel that uses the chain.

The following code shows how to use a custom deleter to tie interceptor lifetime to a single channel:

     auto *metricsInterceptor = new MetricsInterceptor();
     auto *authInterceptor = new AuthInterceptor();
     ~~~
     QGrpcInterceptorChain chain;
     if (!chain.add(metricsInterceptor))
         qFatal("Failed to add metrics interceptor");
     if (!chain.add(authInterceptor))
         qFatal("Failed to add auth interceptor");

     auto channel = std::shared_ptr<QGrpcHttp2Channel>(
         new QGrpcHttp2Channel(QUrl("you_uri:port"), std::move(chain)),
         [&metricsInterceptor, &authInterceptor](QGrpcHttp2Channel* ptr) {
             delete ptr;
             qDebug() << "Channel destroyed.";
             // If these interceptors are not shared with any other channel,
             // this is an appropriate place to delete them. Otherwise their
             // lifetime must be managed externally.
             delete metricsInterceptor;
             delete authInterceptor;
             metricsInterceptor = nullptr;
             authInterceptor = nullptr;
         }
     );

Each interceptor type must implement at least one interceptor interface (for example, QGrpcStartInterceptor or QGrpcFinishedInterceptor) to provide interception capabilities.

See also set() and clear().

### template <typename T, QtGrpcPrivate::if_interceptor<T> = true> bool QGrpcInterceptorChain::add(std::unique_ptr<T> &&interceptor)

Adds interceptor to the chain and takes ownership of it.

Returns `true` if the interceptor was added; otherwise returns `false`.

Ownership of interceptor is transferred to the chain only if the interceptor is successfully added. If the function returns `false`, ownership remains with the caller.

Each interceptor type must implement at least one interceptor interface (for example, QGrpcStartInterceptor or QGrpcFinishedInterceptor) to provide interception capabilities.

See also set() and clear().

### `[noexcept]` QtGrpc::InterceptorCapabilities QGrpcInterceptorChain::capabilities() const

Returns the combined capabilities of all interceptors stored in the chain.

The returned value is the bitwise OR of capabilities provided by the interceptors.

See also hasHandlerFor(), capabilitiesAt(), and QtGrpc::InterceptorCapability.

### QtGrpc::InterceptorCapabilities QGrpcInterceptorChain::capabilitiesAt(qsizetype index) const

Returns the capabilities provided by the interceptor at index.

Warning: Calling this function with an index that is not valid for the chain constitutes undefined behavior.

See also capabilities() and size().

### void QGrpcInterceptorChain::clear()

Clears the chain.

Removes all interceptors from the chain. Any interceptors owned by the chain are destroyed.

See also add() and set().

### `[noexcept]` bool QGrpcInterceptorChain::empty() const

Returns `true` if the chain contains no interceptors; otherwise returns `false`.

See also size() and isEmpty().

### `[noexcept]` bool QGrpcInterceptorChain::hasHandlerFor(QtGrpc::InterceptorCapability cap) const

Returns `true` if the chain contains at least one interceptor that provides a handler for capability cap; otherwise returns `false`.

See also capabilities() and capabilitiesAt().

### `[noexcept]` bool QGrpcInterceptorChain::isEmpty() const

Returns `true` if the chain contains no interceptors; otherwise returns `false`.

See also size() and empty().

### template <typename... Ts, QtGrpcPrivate::if_interceptor<Ts...> = true> bool QGrpcInterceptorChain::set(Ts *... interceptors)

Replaces the contents of the chain with interceptors without taking ownership of them.

Returns `true` if all interceptors were added successfully; otherwise returns `false` and leaves the chain unchanged.

When setting interceptors by raw pointer, the caller retains ownership. The QGrpcInterceptorChain stores non-owning references to the provided interceptors.

The interceptor chain is transferred to and owned by the channel. As a result, all interceptor objects must remain valid for the entire lifetime of the channel that uses the chain.

The following code shows how to use a custom deleter to tie interceptor lifetime to a single channel:

     auto *metricsInterceptor = new MetricsInterceptor();
     auto *authInterceptor = new AuthInterceptor();
     ~~~
     QGrpcInterceptorChain chain;
     if (!chain.set(metricsInterceptor, authInterceptor))
         qFatal("Failed to set interceptors to chain");

     auto channel = std::shared_ptr<QGrpcHttp2Channel>(
         new QGrpcHttp2Channel(QUrl("you_uri:port"), std::move(chain)),
         [&metricsInterceptor, &authInterceptor](QGrpcHttp2Channel* ptr) {
             delete ptr;
             qDebug() << "Channel destroyed.";
             // If these interceptors are not shared with any other channel,
             // this is an appropriate place to delete them. Otherwise their
             // lifetime must be managed externally.
             delete metricsInterceptor;
             delete authInterceptor;
             metricsInterceptor = nullptr;
             authInterceptor = nullptr;
         }
     );

Each interceptor type must implement at least one interceptor interface (for example, QGrpcStartInterceptor or QGrpcFinishedInterceptor) to provide interception capabilities.

See also add() and clear().

### template <typename... Ts, QtGrpcPrivate::if_interceptor<Ts...> = true> bool QGrpcInterceptorChain::set(std::unique_ptr<Ts> &&... interceptors)

Replaces the contents of the chain with interceptors and takes ownership of them.

Returns `true` if all interceptors were added successfully; otherwise returns `false` and leaves the chain unchanged.

Interceptors are processed in the order in which they are passed to this function. If all additions succeed, the chain is replaced with the new interceptors in that order.

Ownership is transferred incrementally as interceptors are processed. If the operation fails, any interceptors that were successfully added before the failure are destroyed, while the remaining (not yet processed) unique_ptrs remain valid.

Each interceptor type must implement at least one interceptor interface (for example, QGrpcStartInterceptor or QGrpcFinishedInterceptor) to provide interception capabilities.

See also add() and clear().

### `[noexcept]` qsizetype QGrpcInterceptorChain::size() const

Returns the number of interceptors stored in the chain.

See also isEmpty().

### `[noexcept]` void QGrpcInterceptorChain::swap(QGrpcInterceptorChain &other)

Swaps other with this object. This operation is very fast and never fails.