Sending custom HTTP headers

When sending an RPC request, it is sometimes required to send HTTP headers with it, such as an authentication token. There are four ways to customize the HTTP headers of your RPC request:

  • Using the Clients.withHttpHeaders() method

  • Using the ClientOption.HTTP_HEADERS option

  • Using the ClientBuilder.decorator() method

  • Using a derived client

Using Clients.withHttpHeaders()

import static com.linecorp.armeria.common.HttpHeaderNames.AUTHORIZATION;
import com.linecorp.armeria.common.util.SafeCloseable;
import com.linecorp.armeria.client.Clients;

HelloService.Iface client = Clients.newClient("tbinary+",
try (SafeCloseable ignored = Clients.withHttpHeaders(
        headers -> headers.set(AUTHORIZATION, credential))) {
    client.hello("authorized personnel");

If you are setting only a single header, you can use Clients.withHttpHeader() simply:

try (SafeCloseable ignored = Clients.withHttpHeader(AUTHORIZATION, credential)) {
    client.hello("authorized personnel");

You can also nest withHttpHeader(s). The following example will send both user-agent header and authorization header when calling client.hello():

import static com.linecorp.armeria.common.HttpHeaderNames.USER_AGENT;

try (SafeClosedble ignored1 = Clients.withHttpHeader(USER_AGENT, myUserAgent)) {
    for (String cred : credentials) {
        try (SafeCloseable ignored2 = Clients.withHttpHeaders(AUTHORIZATION, cred)) {
            client.hello("authorized personnel");

Using ClientOption.HTTP_HEADERS

If you have a custom HTTP header whose value does not change often, you can use ClientOption.HTTP_HEADERS which is more efficient:

import static com.linecorp.armeria.common.HttpHeaderNames.AUTHORIZATION;
import com.linecorp.armeria.common.HttpHeaders;
import com.linecorp.armeria.client.ClientBuilder;
import com.linecorp.armeria.client.ClientOption;

ClientBuilder cb = Clients.builder("tbinary+");
cb.setHttpHeader(AUTHORIZATION, credential);
// or:
// cb.option(ClientOption.HTTP_HEADERS, HttpHeaders.of(AUTHORIZATION, credential));
HelloService.Iface client =;
client.hello("authorized personnel");

Using ClientBuilder.decorator()

If you want more freedom on how you manipulate the request headers, use a decorator:

ClientBuilder cb = Clients.builder("tbinary+");

// Add a decorator that inserts the custom header.
cb.decorator((delegate, ctx, req) -> { // See DecoratingHttpClientFunction and DecoratingRpcClientFunction.
    HttpRequest newReq = req.withHeaders(req.headers().toBuilder().set(AUTHORIZATION, credential));
    return delegate.execute(ctx, newReq);

HelloService.Iface client =;
client.hello("authorized personnel");

Note that this method is as efficient as the ClientOption.HTTP_HEADERS option. Choose whichever you prefer.

Using a derived client

Although not as simple as using withHttpHeaders(), you can create a derived client to add more custom headers to an existing client:

import com.linecorp.armeria.client.ClientOptionsBuilder;

HelloService.Iface client = ...;
HelloService.Iface derivedClient = Clients.newDerivedClient(client, options -> {
    ClientOptionsBuilder builder = new ClientOptionsBuilder(options);
    builder.decorator(...);  // Add a decorator.
    builder.httpHeader(AUTHORIZATION, credential); // Add an HTTP header.