code: public static SafeCloseable withContextCustomizer(Consumer<ClientRequestContext> contextCustomizer) {
          requireNonNull(contextCustomizer, "contextCustomizer");
  
          final Consumer<ClientRequestContext> oldCustomizer = THREAD_LOCAL_CONTEXT_CUSTOMIZER.get();
  
          if (oldCustomizer != null) {
              THREAD_LOCAL_CONTEXT_CUSTOMIZER.set(oldCustomizer.andThen(contextCustomizer));
              return () -> THREAD_LOCAL_CONTEXT_CUSTOMIZER.set(oldCustomizer);
          } else {
              THREAD_LOCAL_CONTEXT_CUSTOMIZER.set(contextCustomizer);
              return THREAD_LOCAL_CONTEXT_CUSTOMIZER::remove;
          }
      }
docs: Sets the specified {@link ClientRequestContext} customization function in a thread-local variable so that
  the customized context is used when the client invokes a request from the current thread. Use the
  `try-with-resources` block with the returned {@link SafeCloseable} to unset the thread-local variable
  automatically:
  <pre>{@code
  try (SafeCloseable ignored = withContextCustomizer(ctx -> {
  ctx.attr(USER_ID).set(userId);
  ctx.attr(USER_SECRET).set(secret);
  })) {
  client.executeSomething(..);
  }
  }</pre>
  You can also nest the request context customization:
  <pre>{@code
  try (SafeCloseable ignored = withContextCustomizer(ctx -> ctx.attr(USER_ID).set(userId))) {
  String secret = client.getSecret();
  try (SafeCloseable ignored2 = withContextCustomizer(ctx -> ctx.attr(USER_SECRET)
  .set(secret))) {
  // Both USER_ID and USER_SECRET will be set.
  client.executeSomething(..);
  }
  }
  }</pre>
  
  @see #withHttpHeaders(Function)