Class Clients

java.lang.Object
com.linecorp.armeria.client.Clients

public final class Clients extends Object
Creates a new client that connects to a specified URI. If you are creating a WebClient, it is recommended to use the factory methods in WebClient.
  • Method Details

    • newClient

      public static <T> T newClient(String uri, Class<T> clientType)
      Creates a new client that connects to the specified uri using the default ClientFactory.
      Parameters:
      uri - the URI of the server endpoint
      clientType - the type of the new client
      Throws:
      IllegalArgumentException - if the specified uri is invalid, or the specified clientType is unsupported for the uri's scheme
    • newClient

      public static <T> T newClient(URI uri, Class<T> clientType)
      Creates a new client that connects to the specified URI using the default ClientFactory.
      Parameters:
      uri - the URI of the server endpoint
      clientType - the type of the new client
      Throws:
      IllegalArgumentException - if the specified URI is invalid, or the specified clientType is unsupported for the URI's scheme
    • newClient

      public static <T> T newClient(String scheme, EndpointGroup endpointGroup, Class<T> clientType)
      Creates a new client that connects to the specified EndpointGroup with the specified scheme using the default ClientFactory.
      Parameters:
      scheme - the Scheme represented as a String
      endpointGroup - the server EndpointGroup
      clientType - the type of the new client
      Throws:
      IllegalArgumentException - if the specified scheme is invalid or the specified clientType is unsupported for the specified scheme.
    • newClient

      public static <T> T newClient(String scheme, EndpointGroup endpointGroup, String path, Class<T> clientType)
      Creates a new client that connects to the specified EndpointGroup with the specified scheme and path using the default ClientFactory.
      Parameters:
      scheme - the Scheme represented as a String
      endpointGroup - the server EndpointGroup
      path - the path to the endpoint
      clientType - the type of the new client
      Throws:
      IllegalArgumentException - if the specified scheme is invalid or the specified clientType is unsupported for the specified scheme.
    • newClient

      public static <T> T newClient(Scheme scheme, EndpointGroup endpointGroup, Class<T> clientType)
      Creates a new client that connects to the specified EndpointGroup with the specified Scheme using the default ClientFactory.
      Parameters:
      scheme - the Scheme
      endpointGroup - the server EndpointGroup
      clientType - the type of the new client
      Throws:
      IllegalArgumentException - if the specified clientType is unsupported for the specified Scheme.
    • newClient

      public static <T> T newClient(Scheme scheme, EndpointGroup endpointGroup, String path, Class<T> clientType)
      Creates a new client that connects to the specified EndpointGroup with the specified Scheme and path using the default ClientFactory.
      Parameters:
      scheme - the Scheme
      endpointGroup - the server EndpointGroup
      path - the path to the endpoint
      clientType - the type of the new client
      Throws:
      IllegalArgumentException - if the specified clientType is unsupported for the specified Scheme.
    • newClient

      public static <T> T newClient(SessionProtocol protocol, EndpointGroup endpointGroup, Class<T> clientType)
      Creates a new client that connects to the specified EndpointGroup with the specified SessionProtocol using the default ClientFactory.
      Parameters:
      protocol - the SessionProtocol
      endpointGroup - the server EndpointGroup
      clientType - the type of the new client
      Throws:
      IllegalArgumentException - if the specified clientType is unsupported for the specified SessionProtocol or SerializationFormat is required.
    • newClient

      public static <T> T newClient(SessionProtocol protocol, EndpointGroup endpointGroup, String path, Class<T> clientType)
      Creates a new client that connects to the specified EndpointGroup with the specified SessionProtocol and path using the default ClientFactory.
      Parameters:
      protocol - the SessionProtocol
      endpointGroup - the server EndpointGroup
      path - the path to the endpoint
      clientType - the type of the new client
      Throws:
      IllegalArgumentException - if the specified clientType is unsupported for the specified SessionProtocol or SerializationFormat is required.
    • builder

      public static ClientBuilder builder(String uri)
      Returns a new ClientBuilder that builds the client that connects to the specified uri.
      Throws:
      IllegalArgumentException - if the specified uri is invalid, or the specified clientType is unsupported for the uri's scheme
    • builder

      public static ClientBuilder builder(URI uri)
      Returns a new ClientBuilder that builds the client that connects to the specified URI.
      Throws:
      IllegalArgumentException - if the specified URI is invalid, or the specified clientType is unsupported for the URI's scheme
    • builder

      public static ClientBuilder builder(String scheme, EndpointGroup endpointGroup)
      Returns a new ClientBuilder that builds the client that connects to the specified EndpointGroup with the specified scheme.
      Throws:
      IllegalArgumentException - if the scheme is invalid.
    • builder

      public static ClientBuilder builder(String scheme, EndpointGroup endpointGroup, String path)
      Returns a new ClientBuilder that builds the client that connects to the specified EndpointGroup with the specified scheme and path.
      Throws:
      IllegalArgumentException - if the scheme is invalid.
    • builder

      public static ClientBuilder builder(SessionProtocol protocol, EndpointGroup endpointGroup)
      Returns a new ClientBuilder that builds the client that connects to the specified EndpointGroup with the specified SessionProtocol.
    • builder

      public static ClientBuilder builder(SessionProtocol protocol, EndpointGroup endpointGroup, String path)
      Returns a new ClientBuilder that builds the client that connects to the specified EndpointGroup with the specified SessionProtocol and path.
    • builder

      public static ClientBuilder builder(Scheme scheme, EndpointGroup endpointGroup)
      Returns a new ClientBuilder that builds the client that connects to the specified EndpointGroup with the specified Scheme.
    • builder

      public static ClientBuilder builder(Scheme scheme, EndpointGroup endpointGroup, String path)
      Returns a new ClientBuilder that builds the client that connects to the specified EndpointGroup with the specified Scheme and path.
    • newDerivedClient

      public static <T> T newDerivedClient(T client, ClientOptionValue<?>... additionalOptions)
      Creates a new derived client that connects to the same URI with the specified client and the specified additionalOptions.
      See Also:
    • newDerivedClient

      public static <T> T newDerivedClient(T client, Iterable<ClientOptionValue<?>> additionalOptions)
      Creates a new derived client that connects to the same URI with the specified client and the specified additionalOptions.
      See Also:
    • newDerivedClient

      public static <T> T newDerivedClient(T client, Function<? super ClientOptions,ClientOptions> configurator)
      Creates a new derived client that connects to the same URI with the specified client but with different ClientOptions. For example:
      
       WebClient derivedWebClient = Clients.newDerivedClient(webClient, options -> {
           ClientOptionsBuilder builder = options.toBuilder();
           builder.decorator(...); // Add a decorator.
           builder.addHeader(...); // Add an HTTP header.
           return builder.build();
       });
       
      Parameters:
      configurator - a Function whose input is the original ClientOptions of the client being derived from and whose output is the ClientOptions of the new derived client
      See Also:
    • unwrap

      @Nullable public static <T> T unwrap(Object client, Class<T> type)
      Unwraps the specified client into the object of the specified type. Use this method instead of an explicit downcast. For example:
      
       WebClient client = WebClient.builder(...)
                                   .decorator(LoggingClient.newDecorator())
                                   .build();
      
       LoggingClient unwrapped = Clients.unwrap(client, LoggingClient.class);
      
       // If the client implements Unwrappable, you can just use the 'as()' method.
       LoggingClient unwrapped2 = client.as(LoggingClient.class);
       
      Parameters:
      type - the type of the object to return
      Returns:
      the object of the specified type if found, or null if not found.
      See Also:
    • withHeader

      @MustBeClosed public static SafeCloseable withHeader(CharSequence name, String value)
      Sets the specified HTTP header in a thread-local variable so that the header is sent by the client call made from the current thread. Use the try-with-resources block with the returned SafeCloseable to unset the thread-local variable automatically:
      
       import static com.linecorp.armeria.common.HttpHeaderNames.AUTHORIZATION;
      
       try (SafeCloseable ignored = withHeader(AUTHORIZATION, myCredential)) {
           client.executeSomething(..);
       }
       
      You can also nest the header manipulation:
      
       import static com.linecorp.armeria.common.HttpHeaderNames.AUTHORIZATION;
       import static com.linecorp.armeria.common.HttpHeaderNames.USER_AGENT;
      
       try (SafeCloseable ignored = withHeader(USER_AGENT, myAgent)) {
           for (String secret : secrets) {
               try (SafeCloseable ignored2 = withHeader(AUTHORIZATION, secret)) {
                   // Both USER_AGENT and AUTHORIZATION will be set.
                   client.executeSomething(..);
               }
           }
       }
       

      Note that the specified header will be stored into ClientRequestContext.additionalRequestHeaders() which takes precedence over HttpRequest.headers().

      See Also:
    • withHeader

      @MustBeClosed public static SafeCloseable withHeader(CharSequence name, Object value)
      Sets the specified HTTP header in a thread-local variable so that the header is sent by the client call made from the current thread. Use the try-with-resources block with the returned SafeCloseable to unset the thread-local variable automatically:
      
       import static com.linecorp.armeria.common.HttpHeaderNames.CONTENT_TYPE;
       import static com.linecorp.armeria.common.MediaType.JSON_UTF_8;
      
       try (SafeCloseable ignored = withHeader(CONTENT_TYPE, JSON_UTF_8)) {
           client.executeSomething(..);
       }
       
      You can also nest the header manipulation:
      
       import static com.linecorp.armeria.common.HttpHeaderNames.AUTHORIZATION;
       import static com.linecorp.armeria.common.HttpHeaderNames.CONTENT_TYPE;
       import static com.linecorp.armeria.common.MediaType.JSON_UTF_8;
      
       try (SafeCloseable ignored = withHeader(CONTENT_TYPE, JSON_UTF_8)) {
           for (String secret : secrets) {
               try (SafeCloseable ignored2 = withHeader(AUTHORIZATION, secret)) {
                   // Both CONTENT_TYPE and AUTHORIZATION will be set.
                   client.executeSomething(..);
               }
           }
       }
       

      Note that the specified header will be stored into ClientRequestContext.additionalRequestHeaders() which takes precedence over HttpRequest.headers().

      See Also:
    • withHeaders

      @MustBeClosed public static SafeCloseable withHeaders(Consumer<HttpHeadersBuilder> headerMutator)
      Sets the specified Consumer, which mutates HTTP headers, in a thread-local variable so that the mutated headers are sent by the client call made from the current thread. Use the try-with-resources block with the returned SafeCloseable to unset the thread-local variable automatically:
      
       import static com.linecorp.armeria.common.HttpHeaderNames.AUTHORIZATION;
       import static com.linecorp.armeria.common.HttpHeaderNames.USER_AGENT;
      
       try (SafeCloseable ignored = withHeaders(builder -> {
           builder.set(HttpHeaders.AUTHORIZATION, myCredential)
                  .set(HttpHeaders.USER_AGENT, myAgent);
       })) {
           client.executeSomething(..);
       }
       
      You can also nest the header mutation:
      
       import static com.linecorp.armeria.common.HttpHeaderNames.AUTHORIZATION;
       import static com.linecorp.armeria.common.HttpHeaderNames.USER_AGENT;
      
       try (SafeCloseable ignored = withHeaders(builder -> {
                builder.set(USER_AGENT, myAgent);
            })) {
           for (String secret : secrets) {
               try (SafeCloseable ignored2 = withHeaders(builder -> {
                        builder.set(AUTHORIZATION, secret);
                    })) {
                   // Both USER_AGENT and AUTHORIZATION will be set.
                   client.executeSomething(..);
               }
           }
       }
       

      Note that the mutated headers will be stored into ClientRequestContext.additionalRequestHeaders() which takes precedence over HttpRequest.headers().

      See Also:
    • withContextCustomizer

      @MustBeClosed public static SafeCloseable withContextCustomizer(Consumer<? super ClientRequestContext> contextCustomizer)
      Sets the specified 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 ClientBuilder.contextCustomizer(Consumer).

      Use the try-with-resources block with the returned SafeCloseable to unset the thread-local variable automatically:

      
       // 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(..);
           });
       }
       
      You can also nest the request context customization:
      
       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(..);
           }
       }
       

      Note that certain properties of ClientRequestContext, such as:

      may be null while the customizer function runs, because the target host of the Request is not determined yet.
      See Also:
    • newContextCaptor

      public static ClientRequestContextCaptor newContextCaptor()
      Prepare to capture the ClientRequestContext of the next request sent from the current thread. Use the try-with-resources block with the returned ClientRequestContextCaptor to retrieve the captured ClientRequestContext and to unset the thread-local variable automatically.
      
       try (ClientRequestContextCaptor captor = Clients.newContextCaptor()) {
           WebClient.of().get("https://www.example.com/hello");
           ClientRequestContext ctx = captor.get();
           assert ctx.path().equals("/hello");
       }
      Note that you can also capture more than one ClientRequestContext:
      
       try (ClientRequestContextCaptor captor = Clients.newContextCaptor()) {
           WebClient.of().get("https://www.example.com/foo");
           WebClient.of().get("https://www.example.com/bar");
           List<ClientRequestContext> contexts = captor.getAll();
           assert contexts.get(0).path().equals("/foo");
           assert contexts.get(1).path().equals("/bar");
       }
    • isUndefinedUri

      public static boolean isUndefinedUri(URI uri)
      Returns true if the specified uri is an undefined URI, which signifies that a Client, was created without a URI or EndpointGroup. For example, isUndefinedUri(WebClient.of().uri()) will return true.