All Downloads are FREE. Search and download functionalities are using the official Maven repository.

se.webclient.adoc Maven / Gradle / Ivy

There is a newer version: 4.1.4
Show newest version
///////////////////////////////////////////////////////////////////////////////

    Copyright (c) 2020, 2024 Oracle and/or its affiliates.

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

        http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.

///////////////////////////////////////////////////////////////////////////////

= WebClient Introduction
:description: Helidon WebClient
:keywords: helidon, se, rest, httpclient, webclient
:feature-name: WebClient
:rootdir: {docdir}/..

include::{rootdir}/includes/se.adoc[]

== Contents

- <>
- <>
- <>
- <>
- <>
- <>

== Overview

WebClient is an HTTP client for Helidon SE. It can be used to send requests and retrieve corresponding responses in a programmatic way.

Helidon WebClient provides the following features:

* *Blocking approach* +
The Webclient uses the blocking approach to synchronously process a request and its correspond response. Both `HTTP/1.1` and `HTTP/2` request and response will run in the thread of the user. Additionally, for `HTTP/2`, virtual thread is employed to manage the connection.

* *Builder-like setup and execution* +
Creates every client and request as a builder pattern. This improves readability and code maintenance.

* *Redirect chain* +
Follows the redirect chain and perform requests on the correct endpoint by itself.

* *Tracing and security propagation* +
Automatically propagates the configured tracing and security settings of the Helidon WebServer to the WebClient and uses them during request and response.

include::{rootdir}/includes/dependencies.adoc[]

[source,xml]
----

    io.helidon.webclient
    helidon-webclient

----

The `helidon-webclient` dependency has built-in support for `HTTP/1.1`.

If support for `HTTP/2` is a requirement, below dependency needs to be added:

[source,xml]
----

    io.helidon.webclient
    helidon-webclient-http2

----

== Usage

=== Instantiating the WebClient

You can create an instance of a WebClient by executing `WebClient.create()` which will have default settings and without a base uri set.

To change the default settings and register
additional services, you can use simple builder that allows you to customize the client behavior.

.Create a WebClient with simple builder:
[source,java]
----
include::{sourcedir}/se/WebClientSnippets.java[tag=snippet_1, indent=0]
----

=== Creating the Request

WebClient offers a set of request methods that are used to specify the type of action to be performed on a given resource. Below are some examples of request methods:

* `get()`
* `post()`
* `put()`
* `method(String methodName)`

Check out link:{webclient-javadoc-base-url}.api/io/helidon/webclient/api/HttpClient.html[HttpClient] API to learn more about
request methods. These methods will create a new instance of link:{webclient-javadoc-base-url}.api/io/helidon/webclient/api/HttpClientRequest.html[HttpClientRequest] which can then be configured to add optional settings that will customize the behavior of the request.

=== Customizing the Request

Configuration can be set for every request type before it is sent.

.Customizing a request
[source,java]
----
include::{sourcedir}/se/WebClientSnippets.java[tag=snippet_12, indent=0]
----

<1> Overrides `baseUri` from WebClient
<2> Adds path to the uri
<3> Adds query parameter to the request
<4> Adds fragment to the request
<5> Adds header to the request

For more information about these optional parameters, check out link:{webclient-javadoc-base-url}.api/io/helidon/webclient/api/ClientRequestBase.html[ClientRequestBase] API, which is a parent class of link:{webclient-javadoc-base-url}.api/io/helidon/webclient/api/HttpClientRequest.html[HttpClientRequest].

link:{webclient-javadoc-base-url}.api/io/helidon/webclient/api/HttpClientRequest.html[HttpClientRequest] class also provides specific header methods that help the user to set a particular header. Some examples of these are:

* `contentType` (MediaType contentType)
* `accept` (MediaType... mediaTypes)

For more information about these methods, check out  link:{webclient-javadoc-base-url}.api/io/helidon/webclient/api/ClientRequest.html[ClientRequest] API, which is a parent class of link:{webclient-javadoc-base-url}.api/io/helidon/webclient/api/HttpClientRequest.html[HttpClientRequest].

=== Sending the Request

Once the request setup is completed, the following methods can be used to send it:

* `HttpClientResponse request()`
* ` ClientResponseTyped request(Class type)`
* ` E requestEntity(Class type)`
* `HttpClientResponse submit(Object entity)`
* ` ClientResponseTyped submit(Object entity, Class requestedType)`
* `HttpClientResponse outputStream(OutputStreamHandler outputStreamConsumer)`
* ` ClientResponseTyped outputStream(OutputStreamHandler outputStreamConsumer, Class requestedType)`

Each of the methods will provide a way to allow response to be retrieved in a particular response type. Refer to link:{webclient-javadoc-base-url}.api/io/helidon/webclient/api/ClientRequest.html[ClientRequest API] for more details about these methods.

.Execute a simple GET request to endpoint and receive a String response:
[source,java]
----
include::{sourcedir}/se/WebClientSnippets.java[tag=snippet_2, indent=0]
----

=== Protocol Used
WebClient currently supports `HTTP/1.1` and `HTTP/2` protocols. Below are the rules on which specific protocol will be used:

* Using plain socket triggers WebClient to process a request using `HTTP/1.1`.
* When using TLS, the client will use ALPN (protocol negotiation) to use appropriate HTTP version (either 1.1, or 2). `HTTP/2` has a higher weight, so it is chosen if supported by both sides.
* A specific protocol can be explicitly selected by calling `HttpClientRequest#protocolId(String)`.
[source,java]
----
include::{sourcedir}/se/WebClientSnippets.java[tag=snippet_3, indent=0]
----
* If `HTTP/2` is used, an upgrade attempt will be performed. If it fails, the client falls-back to `HTTP/1.1`.
* The parameter `prior-knowledge` can be defined using `HTTP/2` protocol configuration. Please refer to <> on how to customize `HTTP/2`. In such a case, `prior-knowledge` will be used and fail if it is unable to switch to `HTTP/2`.

=== Adding Media Support

Webclient supports the following built-in Helidon Media Support libraries:

1. JSON Processing (JSON-P)
2. JSON Binding (JSON-B)
3. Jackson

They can be activated by adding their corresponding libraries into the classpath. This can simply be done by adding their corresponding dependencies.

.Add JSON-P support:
[source,xml]
----

    io.helidon.http.media
    helidon-http-media-jsonp

----
.Add JSON-B support:
[source,xml]
----

    io.helidon.http.media
    helidon-http-media-jsonb

----
.Add Jackson support:
[source,xml]
----

    io.helidon.http.media
    helidon-http-media-jackson

----

Users can also create their own Custom Media Support library and make them work by following either of the approaches:

* Create a Provider of the Custom Media Support and expose it via Service Loader followed by adding the Media Support library to the classpath.
* Explicitly register the Custom Media Support from WebClient.

[source,java]
----
include::{sourcedir}/se/WebClientSnippets.java[tag=snippet_4, indent=0]
----
<1> Register CustomMedia support from the WebClient.

=== DNS Resolving

Webclient provides three DNS resolver implementations out of the box:

* `Java DNS resolution` is the default.
* `*First* DNS resolution` uses the first IP address from a DNS lookup. To enable this option, add below dependency:

[source,xml]
----

    io.helidon.webclient.dns.resolver
    helidon-webclient-dns-resolver-first

----

* `*Round-Robin* DNS resolution` cycles through IP addresses from a DNS lookup. To enable this option, add this dependency:

[source,xml]
----

    io.helidon.webclient.dns.resolver
    helidon-webclient-dns-resolver-round-robin

----

== Configuring the WebClient

The class responsible for WebClient configuration is:

include::{rootdir}/config/io_helidon_webclient_api_WebClient.adoc[leveloffset=+1,tag=config]

=== Protocol Specific Configuration

Protocol specific configuration can be set using the  `protocol-configs` parameter. Webclient currently supports `HTTP/1.1.` and `HTTP/2`. Below are the options for each of the protocol type:

* `HTTP/1.1`

include::{rootdir}/config/io_helidon_webclient_http1_Http1ClientProtocolConfig.adoc[leveloffset=2,tag=config]


* `HTTP/2`

include::{rootdir}/config/io_helidon_webclient_http2_Http2ClientProtocolConfig.adoc[leveloffset=2,tag=config]

=== Example of a WebClient Runtime Configuration

[source,java]
----
include::{sourcedir}/se/WebClientSnippets.java[tag=snippet_5, indent=0]
----

=== Example of a WebClient YAML Configuration

[source, yaml]
----
client:
  connect-timeout-millis: 2000
  read-timeout-millis: 2000
  follow-redirects: true # <1>
  max-redirects: 5
  cookie-manager: # <2>
    automatic-store-enabled: true
    default-cookies:
      flavor3: strawberry
      flavor4: raspberry
  default-headers: # <3>
    Accept: '"application/json", "text/plain"'
  services: # <4>
    metrics:
      - methods: ["PUT", "POST", "DELETE"]
        type: METER
        name-format: "client.meter.overall"
      - type: TIMER
        # meter per method
        name-format: "client.meter.%1$s"
      - methods: ["GET"]
        type: COUNTER
        errors: false
        name-format: "client.counter.%1$s.success"
        description: "Counter of successful GET requests"
      - methods: ["PUT", "POST", "DELETE"]
        type: COUNTER
        success: false
        name-format: "wc.counter.%1$s.error"
        description: "Counter of failed PUT, POST and DELETE requests"
    tracing:
  protocol-configs: # <5>
    http_1_1:
      max-header-size: 20000
      validate-request-headers: true
    h2:
      prior-knowledge: true
  proxy: # <6>
    host: "hostName"
    port: 80
    no-proxy: ["localhost:8080", ".helidon.io", "192.168.1.1"]
  tls: # <7>
    trust:
      keystore:
        passphrase: "password"
        trust-store: true
        resource:
          resource-path: "client.p12"
----

<1> Client functional settings
<2> Cookie management
<3> Default client headers
<4> Client service configuration
<5> Protocol configuration
<6> Proxy configuration
<7> TLS configuration

== Examples

=== Webclient with Proxy
Configure Proxy setup either programmatically or via the Helidon configuration framework.

==== Configuring Proxy in your code
Proxy can be set directly from WebClient builder.
[source,java]
----
include::{sourcedir}/se/WebClientSnippets.java[tag=snippet_6, indent=0]
----

Alternative is to set proxy directly from the request via  `HttpClientRequest`.

[source,java]
----
include::{sourcedir}/se/WebClientSnippets.java[tag=snippet_7,indent=0]
----

<1> Proxy instance configured using system settings (environment variables and system properties)
<2> Configure the proxy per client request

==== Configuring Proxy in the config file

Proxy can also be configured in WebClient through the `application.yaml` configuration file.

[source,yaml]
.WebClient Proxy configuration in `application.yaml`
----
client:
  proxy:
    host: "hostName"
    port: 80
    no-proxy: ["localhost:8080", ".helidon.io", "192.168.1.1"]
----
Then, in your application code, load the configuration from that file.

[source,java]
.WebClient initialization using the `application.yaml` file located on the classpath
----
include::{sourcedir}/se/WebClientSnippets.java[tag=snippet_8,indent=0]
----
<1> `application.yaml` is a default configuration source loaded when YAML support is on classpath, so we can just use `Config.create()`
<2> Passing the client configuration node

=== WebClient TLS Setup

Configure TLS either programmatically or by the Helidon configuration framework.

==== Configuring TLS in your code

One way to configure TLS in WebClient is in your application code as shown below.

[source,java]
----
include::{sourcedir}/se/WebClientSnippets.java[tag=snippet_9,indent=0]
----

==== Configuring TLS in the config file

Another way to configure TLS in WebClient is through the `application.yaml` configuration file.

[source,yaml]
.WebClient TLS configuration in `application.yaml`
----
client:
  tls:
    trust:
      keystore:
        passphrase: "password"
        trust-store: true
        resource:
          resource-path: "client.p12"
----

NOTE: The `passphrase` value on the config file can be encrypted if stronger security is required. For more information on how secrets can be encrypted using a master password and store them in a configuration file, please see xref:{rootdir}/mp/security/configuration-secrets.adoc[Configuration Secrets].

In the application code, load the settings from the configuration file.

[source,java]
.WebClient initialization using the `application.yaml` file located on the classpath
----
include::{sourcedir}/se/WebClientSnippets.java[tag=snippet_8,indent=0]
----
<1> `application.yaml` is a default configuration source loaded when YAML support is on classpath, so we can just use `Config.create()`
<2> Passing the client configuration node

=== Adding Service to WebClient

WebClient currently supports 3 built-in services namely `metrics`, `tracing` and `security`.

==== Enabling the service

In order for a service to function, their dependency needs to be added in the application's pom.xml. Below are examples on how to enable the built-in services:

* `metrics`
[source,xml]
----

    io.helidon.webclient
    helidon-webclient-metrics

----
* `tracing`
[source,xml]
----

    io.helidon.webclient
    helidon-webclient-tracing

----
* `security`
[source,xml]
----

    io.helidon.webclient
    helidon-webclient-security

----

==== Adding a service in your code

Services can be added in WebClient as shown in the code below.

[source,java]
----
include::{sourcedir}/se/WebClientSnippets.java[tag=snippet_10,indent=0]
----
<1> Creates new metric which will count all GET requests and has format of `example.metric.GET.`
<2> Register the service in the client instance

==== Adding service in the config file

Adding service in WebClient can also be done through the `application.yaml` configuration file.

[source,yaml]
.WebClient Service configuration in `application.yaml`
----
webclient:
  services:
    metrics:
      - type: METER
        name-format: "client.meter.overall"
      - type: TIMER
        # meter per method
        name-format: "client.meter.%1$s"
      - methods: ["PUT", "POST", "DELETE"]
        type: COUNTER
        success: false
        name-format: "wc.counter.%1$s.error"
        description: "Counter of failed PUT, POST and DELETE requests"
    tracing:
----
Then, in your application code, load the configuration from that file.

[source,java]
.WebClient initialization using the `application.yaml` file located on the classpath
----
include::{sourcedir}/se/WebClientSnippets.java[tag=snippet_8,indent=0]
----

<1> `application.yaml` is a default configuration source loaded when YAML support is on classpath, so we can just use `Config.create()`
<2> Passing the client configuration node

=== Setting Protocol configuration
Individual protocols can be customized using the `protocol-config` parameter.

==== Setting up protocol configuration in your code

Below is an example of customizing `HTTP/1.1` protocol in the application code.

[source,java]
----
include::{sourcedir}/se/WebClientSnippets.java[tag=snippet_11,indent=0]
----

==== Setting up protocol configuration in the config file

Protocol configuration can also be set in the `application.yaml` configuration file.

[source,yaml]
.Setting up `HTTP/1.1` and `HTTP/2` protocol using `application.yaml` file.
----
webclient:
  protocol-configs:
    http_1_1:
      max-header-size: 20000
      validate-request-headers: true
    h2:
      prior-knowledge: true
----
Then, in your application code, load the configuration from that file.

[source,java]
.WebClient initialization using the `application.yaml` file located on the classpath
----
include::{sourcedir}/se/WebClientSnippets.java[tag=snippet_8,indent=0]
----

<1> `application.yaml` is a default configuration source loaded when YAML support is on classpath, so we can just use `Config.create()`
<2> Passing the client configuration node

== Reference

* link:{webclient-javadoc-base-url}.api/module-summary.html[Helidon Webclient API]
* link:{webclient-javadoc-base-url}.http1/module-summary.html[Helidon WebClient HTTP/1.1 Support]
* link:{webclient-javadoc-base-url}.http2/module-summary.html[Helidon WebClient HTTP/2 Support]
* link:{webclient-javadoc-base-url}.dns.resolver.first/module-summary.html[Helidon WebClient DNS Resolver First Support]
* link:{webclient-javadoc-base-url}.dns.resolver.roundrobin/module-summary.html[Helidon WebClient DNS Resolver Round Robin Support]
* link:{webclient-javadoc-base-url}.metrics/module-summary.html[Helidon WebClient Metrics Support]
* link:{webclient-javadoc-base-url}.security/module-summary.html[Helidon WebClient Security Support]
* link:{webclient-javadoc-base-url}.tracing/module-summary.html[Helidon WebClient Tracing Support]





© 2015 - 2025 Weber Informatics LLC | Privacy Policy