Configure the HTTP client

Quarkus Flow supports calling external services over HTTP and OpenAPI. All HTTP / OpenAPI tasks share a common, tunable HTTP client layer powered by RESTEasy Reactive and Vert.x.

This guide shows how to:

  • understand which HTTP client Quarkus Flow uses for a given workflow / task

  • configure the default HTTP client

  • define named HTTP clients

  • route specific workflows / tasks to a named client

  • configure static headers, logging, proxy, TLS and other network options

The low-level configuration reference for all HTTP properties lives in the Extension Configuration Reference page under the quarkus.flow.http.client.* namespace.

Prerequisites

1. Understand the HTTP client model

All Flow HTTP / OpenAPI tasks use a jakarta.ws.rs.client.Client managed by Quarkus Flow.

At runtime, Quarkus Flow:

  • builds a default client from quarkus.flow.http.client.*

  • optionally builds named clients from quarkus.flow.http.client.named.<name>.*

  • resolves which client to use for a given workflow + task using quarkus.flow.http.client.workflow.* routing

  • reuses and closes these clients automatically for you at the end of the application lifecycle

Internally, the extension maps these configuration properties to a RESTEasy Reactive ClientBuilderImpl and Vert.x HttpClientOptions, but the API you configure is purely Quarkus Flow configuration.

2. Configure the default HTTP client

The default HTTP client is used when no routing is configured for a workflow or task.

All default client properties live under:

quarkus.flow.http.client.<property>=<value>

Common examples:

# Basic timeouts (milliseconds)
quarkus.flow.http.client.connect-timeout=5000
quarkus.flow.http.client.read-timeout=10000

# HTTP connection pool and keep-alive
quarkus.flow.http.client.connection-pool-size=50
quarkus.flow.http.client.keep-alive-enabled=true
quarkus.flow.http.client.connection-ttl=60

# User agent
quarkus.flow.http.client.user-agent=quarkus-flow/1.0

These settings apply to all HTTP / OpenAPI tasks unless a more specific named client is selected via routing.

3. Create named HTTP clients

You can declare as many named HTTP clients as you need, each with its own tuning (timeouts, headers, logging, proxy, etc.).

Named clients live under:

quarkus.flow.http.client.named.<name>.<property>=<value>

Example: two named clients, secureA and internal:

# "secureA" – external API with strict timeouts and custom UA
quarkus.flow.http.client.named.secureA.connect-timeout=3000
quarkus.flow.http.client.named.secureA.read-timeout=8000
quarkus.flow.http.client.named.secureA.user-agent=MyCompanyBot/1.0
quarkus.flow.http.client.named.secureA.logging.scope=request-response
quarkus.flow.http.client.named.secureA.logging.body-limit=256
quarkus.flow.http.client.named.secureA.static-headers=X-Env=prod,X-Tenant=acme

# "internal" – internal service with a larger pool and relaxed timeouts
quarkus.flow.http.client.named.internal.connect-timeout=1000
quarkus.flow.http.client.named.internal.read-timeout=20000
quarkus.flow.http.client.named.internal.connection-pool-size=100
quarkus.flow.http.client.named.internal.keep-alive-enabled=true

If a named client is resolved but not configured, Quarkus Flow falls back to the default HTTP client.

4. Route workflows and tasks to clients

Routing is configured under the workflow section of the HTTP config:

# Use "secureA" for all HTTP/OpenAPI tasks in workflow "order-flow"
quarkus.flow.http.client.workflow.order-flow.name=secureA

# Override only the "fetchCustomers" task in "order-flow" to use "internal"
quarkus.flow.http.client.workflow.order-flow.task.fetchCustomers.name=internal

Resolution order for a call:

  1. Task-level override:
    quarkus.flow.http.client.workflow.<workflowId>.task.<taskId>.name

  2. Workflow-level default:
    quarkus.flow.http.client.workflow.<workflowId>.name

  3. Fallback to the global default client (quarkus.flow.http.client.*)

Here, <workflowId> is the workflow id (from the Workflow DSL), and <taskId> is the HTTP/OpenAPI task name.

Although you can have an inner task named the same as a parent task per specification, for HTTP clients it’s highly recommended that you keep HTTP-related task names unique.

5. Configure static headers

Use static-headers to attach headers to every request sent by a client.

The value is a comma-separated list of name=value pairs:

# Default client
quarkus.flow.http.client.static-headers=X-Env=prod,X-Tenant=acme

# Named client "secureA"
quarkus.flow.http.client.named.secureA.static-headers=X-Env=prod,X-Region=us-east-1

Rules:

  • entries are separated by commas ,

  • each entry must be name=value

  • whitespace around names/values is ignored

  • invalid entries are ignored with a warning in the logs

Example:

quarkus.flow.http.client.static-headers=X-Env=prod,X-Tenant=acme

results in:

  • X-Env: prod

  • X-Tenant: acme

on every request performed by the selected client.

6. Logging and debugging HTTP requests

When wiring workflows to external HTTP or OpenAPI services, seeing the actual requests and responses is crucial for debugging.

Quarkus Flow reuses the RESTEasy Reactive client logger, which you can enable and tune via quarkus.flow.http.client.* and standard Quarkus logging categories.

Enable request/response logging

At minimum, set the logging scope for the HTTP client and turn on DEBUG logging for the REST client logger:

# Log both request and response line + headers (+ body, see below)
quarkus.flow.http.client.logging.scope=request-response

# Truncate logged body after N characters
quarkus.flow.http.client.logging.body-limit=1024

# Enable the REST client logger
quarkus.log.category."org.jboss.resteasy.reactive.client.logging".level=DEBUG

The logging.scope property maps to LoggingScope:

  • none – no logging (default)

  • request-response – log one line per request/response, plus headers and body (up to logging.body-limit chars)

  • all – most verbose; includes additional internal details

The logging.body-limit controls how much of the request/response body is included in the logs, helping avoid flooding your logs with very large payloads.

You can configure them per named client:

quarkus.flow.http.client.named.secureA.logging.scope=request-response
quarkus.flow.http.client.named.secureA.logging.body-limit=256

quarkus.flow.http.client.named.internal.logging.scope=none

The logging category stays the same:

quarkus.log.category."org.jboss.resteasy.reactive.client.logging".level=DEBUG

Once enabled, every HTTP/OpenAPI task that uses those clients will emit debug logs with the full HTTP interaction, which is especially useful when iterating on workflow definitions or diagnosing failures against third-party APIs.

7. HTTP/2 and ALPN

You can enable HTTP/2 and ALPN per client:

# Default client
quarkus.flow.http.client.http2=true
quarkus.flow.http.client.alpn=true

# Named client
quarkus.flow.http.client.named.secureA.http2=true
quarkus.flow.http.client.named.secureA.alpn=true

Quarkus Flow passes these flags to the underlying Vert.x HttpClientOptions. If you also configure TLS, ALPN is used to negotiate the protocol when supported by the server.

8. Proxy support

Proxy support is exposed as a thin layer over the RESTEasy Reactive ClientBuilderImpl API. All properties follow the usual quarkus.flow.http.client naming:

# Default client proxy (host/port)
quarkus.flow.http.client.proxy-host=proxy.mycorp.internal
quarkus.flow.http.client.proxy-port=3128

# Optional credentials
quarkus.flow.http.client.proxy-user=api-user
quarkus.flow.http.client.proxy-password=change-me

# Pipe-separated non-proxy hosts pattern (mirrors Java proxy syntax)
quarkus.flow.http.client.non-proxy-hosts=localhost|127.*|[::1]|*.svc.cluster.local

# Connect timeout (milliseconds) for proxy handshake
quarkus.flow.http.client.proxy-connect-timeout=5000

Named clients use the same pattern:

quarkus.flow.http.client.named.secureA.proxy-host=proxy.mycorp.internal
quarkus.flow.http.client.named.secureA.proxy-port=3128

If proxy-host is not set, the client falls back to standard JVM system properties (http(s).proxyHost, etc.), consistent with the underlying Vert.x behavior.

9. Redirects, compression and chunk size

Additional tuning is available:

# Max redirects
quarkus.flow.http.client.max-redirects=5

# Follow redirects at the client level
quarkus.flow.http.client.follow-redirects=true

# Enable transparent decompression
quarkus.flow.http.client.enable-compression=true

# HTTP chunk size (bytes)
quarkus.flow.http.client.max-chunk-size=16384

All of these can be set per named client as well:

quarkus.flow.http.client.named.internal.max-redirects=2
quarkus.flow.http.client.named.internal.enable-compression=true

10. Multi-valued query parameters

If you rely on repeated query parameters (for example, ?tag=a&tag=b), you can control how the underlying REST client encodes them:

# See MultiQueryParamMode enum in RESTEasy Reactive for supported values
quarkus.flow.http.client.multi-query-param-mode=multi

This maps to ClientBuilderImpl.multiQueryParamMode(…​).

11. TLS, trust and host verification

For most use cases, you configure TLS using standard Quarkus SSL / REST client facilities.

Quarkus Flow exposes two booleans that directly map to ClientBuilderImpl.trustAll(boolean) and verifyHost(boolean):

# Trust all certificates (including self-signed)
quarkus.flow.http.client.trust-all=true

# Disable hostname verification
quarkus.flow.http.client.verify-host=false
Only enable trust-all or disable verify-host in controlled environments (for example, local development). In production these settings significantly reduce TLS security.

12. Putting it all together

Example: a typical setup using both default and named clients:

# Default client: used by most workflows
quarkus.flow.http.client.connect-timeout=5000
quarkus.flow.http.client.read-timeout=10000
quarkus.flow.http.client.user-agent=quarkus-flow/1.0
quarkus.flow.http.client.logging.scope=request-response
quarkus.flow.http.client.logging.body-limit=512

# Named client for a SaaS API
quarkus.flow.http.client.named.crm.connect-timeout=3000
quarkus.flow.http.client.named.crm.read-timeout=8000
quarkus.flow.http.client.named.crm.user-agent=MyCRMIntegrator/1.0
quarkus.flow.http.client.named.crm.static-headers=X-Env=prod
quarkus.flow.http.client.named.crm.http2=true
quarkus.flow.http.client.named.crm.enable-compression=true

# Route "customer-sync-flow" to the CRM client
quarkus.flow.http.client.workflow.customer-sync-flow.name=crm

# Override only a specific task in another flow
quarkus.flow.http.client.workflow.order-flow.task.pushOrderToCrm.name=crm

With this configuration:

  • most workflows use the default client

  • any HTTP / OpenAPI task in customer-sync-flow uses the crm client

  • within order-flow, only the pushOrderToCrm task uses crm; other tasks fall back to the default client

This lets you centralize all HTTP behavior (timeouts, logging, headers, proxy, TLS) per logical client, and route workflows and tasks declaratively without touching your Java or DSL code.

See also