@MustBeClosed
    public static SafeCloseable withContextCustomizer(
            Consumer<? super ClientRequestContext> contextCustomizer) {
        requireNonNull(contextCustomizer, "contextCustomizer");

        final ClientThreadLocalState customizers = ClientThreadLocalState.maybeCreate();
        customizers.add(contextCustomizer);

        return new SafeCloseable() {
            boolean closed;

            @Override
            public void close() {
                if (closed) {
                    return;
                }

                closed = true;
                customizers.remove(contextCustomizer);
            }
        };
    }
Sets the specified {@link ClientRequestContext} customizer function in a thread-local variable so that
the customized context is used when the client invokes a request from the current thread.
The given customizer function is evaluated after the customizer function specified with
{@link ClientBuilder#contextCustomizer(Consumer)}.

<p>Use the {@code try-with-resources} block with the returned {@link SafeCloseable} to unset the
thread-local variable automatically:
<pre>{@code
// Good:
try (SafeCloseable ignored = withContextCustomizer(ctx -> {
    ctx.setAttr(USER_ID, userId);
    ctx.setAttr(USER_SECRET, secret);
})) {
    client.executeSomething(..);
}

// Bad:
try (SafeCloseable ignored = withContextCustomizer(ctx -> {
    ctx.setAttr(USER_ID, userId);
    ctx.setAttr(USER_SECRET, secret);
})) {
    executor.execute(() -> {
        // The variables in USER_ID and USER_SECRET will not be propagated to the context.
        // client.executeSomething() must be invoked by the same thread
        // that called withContextCustomizer().
        client.executeSomething(..);
    });
}
}</pre>
You can also nest the request context customization:
<pre>{@code
try (SafeCloseable ignored = withContextCustomizer(ctx -> ctx.setAttr(USER_ID, userId))) {
    String secret = client.getSecret();
    try (SafeCloseable ignored2 = withContextCustomizer(ctx -> ctx.setAttr(USER_SECRET, secret))) {
        // Both USER_ID and USER_SECRET will be set.
        client.executeSomething(..);
    }
}
}</pre>

<p>Note that certain properties of {@link ClientRequestContext}, such as:
<ul>
  <li>{@link ClientRequestContext#endpoint()}</li>
  <li>{@link ClientRequestContext#localAddress()}</li>
  <li>{@link ClientRequestContext#remoteAddress()}</li>
</ul>
may be {@code null} while the customizer function runs, because the target host of the {@link Request}
is not determined yet.

@see #withHeaders(Consumer)
@see ClientBuilder#contextCustomizer(Consumer)
core/src/main/java/com/linecorp/armeria/client/Clients.java