Class EchoMixin
/echo/*
(configurable).
Sibling of AdminMixin (/admin/*) and RouteIndexMixin
(/options). All three classes live in the
org.apache.juneau.rest.server.ops ops/introspection mixin pack.
Compose into a host resource via
@Rest(mixins=EchoMixin.class); the /echo/* URL becomes
available alongside the host's own endpoints with no further wiring.
Configurable mount path:
The default mount /echo/* can be overridden via the SVL variable
${juneau.echo.path:echo} — set via system property
(-Djuneau.echo.path=introspect), environment variable
(JUNEAU_ECHO_PATH=introspect), or Config key
(juneau.echo.path = introspect) to change the runtime mount without subclassing.
Resolution happens once at RestContext construction time (SVL resolution in @RestOp(path)).
Override accepts bare token (echo), leading slash (/echo), trailing slash
(echo/), or wildcard suffix (/echo/*) — all resolve to the same mount.
Migration note (10.0.0): Earlier development snapshots of this mixin mounted at both
/echo/* and /debug/echo/* as historical aliases on a single op. That
dual default has been collapsed to a single SVL-configurable mount as part of the
"single path per op" principle. Deployers who relied on the
/debug/echo/* alias must now either set -Djuneau.echo.path=debug/echo or
compose a second instance with the override.
Mixin-only deployment:
This resource is designed for composition via @Rest(mixins=...). The mount path is
pinned at the op level by @RestOp(path="/{juneau.echo.path:echo}/*") on
echo(org.apache.juneau.rest.server.RestRequest, org.apache.juneau.rest.server.RestResponse, java.lang.String); a class-level @Rest(paths=...) declaration would be silently ignored
under the mixin pattern (see @Rest(paths) Javadoc).
Composition example:
Enablement:
The endpoint is disabled by default. Reachability is controlled by an explicit, non-logging switch and is
independent of the JUL logger level — raising a resource's (or operation's) logger to
FINE/FINEST never exposes /echo/*.
When the endpoint is disabled the handler returns 404 Not Found (so the existence of the endpoint isn't
disclosed).
Enablement is tri-state, resolved per request:
- An explicit
builder value(true/false) always wins. - When the builder value is left unset (
null, the default), the handler resolves the SVL expression${juneau.echo.enabled:false}throughRestRequest.getVarResolverSession()— i.e. the system property-Djuneau.echo.enabled=trueor the relaxed environment variableJUNEAU_ECHO_ENABLED=true. A per-resourceConfigkey is not consulted for this switch.
GLOBAL blast-radius warning: juneau.echo.enabled=true is a process-wide system-property /
environment switch. It enables /echo/* on every host in the JVM that mixes in EchoMixin
— including hosts the operator did not intend to open — and, because it is resolved per request, setting
it flips this security switch mid-process without a restart. It is a convenience for single-app deployments
and local testing, not the recommended production posture.
Recommended production posture: leave echo OFF by default and enable it per host explicitly via a
@Bean EchoMixin factory that calls EchoMixin.Builder.enabled(), gated behind an authorization guard chain.
Host-level @Rest(guards=...) inherit onto the mixed-in /echo/* operation, so declaring
guards at the host authorizes the endpoint.
Sensitive-header redaction:
Token-bearing headers must never be reflected back to the caller (would defeat any auth scheme
in front of the endpoint). The default redacted list is — case-insensitively —
Authorization, Cookie, Set-Cookie, Proxy-Authorization, and
X-API-Key. Each redacted header surfaces in the echo body with the literal value
"[REDACTED]" so the caller can see the header was present without leaking its value.
Override the default list via EchoMixin.Builder.redactedHeaders(String...) (replaces) or extend
via EchoMixin.Builder.redactHeader(String) (additive).
REDACTED and DEFAULT_REDACTED_HEADERS are re-exports of
RedactedHeaders.REDACTED and RedactedHeaders.DEFAULT respectively; masking is
performed by delegating to RedactedHeaders.redact(String, String, java.util.Collection).
Body capture and truncation:
The handler reads up to bodyLimit bytes (default
"1048576" = 1 MB) of the inbound body and emits it as a UTF-8 string in
the content field of the JSON response. When the body exceeds the cap, the captured
portion is truncated and the truncated flag is set to true so callers can see
the response is incomplete.
Response shape:
{
The endpoint is excluded from generated Swagger / OpenAPI specs via
@OpSwagger(ignore=true).
See Also:
- Since:
- 10.0.0
-
Nested Class Summary
Nested Classes -
Field Summary
FieldsModifier and TypeFieldDescriptionstatic final longDefault body capture cap, in bytes (1 MB).Default redacted-header set (case-insensitive lookup).static final StringSentinel value emitted in place of redacted header values. -
Constructor Summary
ConstructorsModifierConstructorDescriptionNo-arg constructor — usesDEFAULT_BODY_LIMITandDEFAULT_REDACTED_HEADERS.protectedEchoMixin(EchoMixin.Builder builder) Builder constructor. -
Method Summary
Modifier and TypeMethodDescriptionstatic EchoMixin.Buildercreate()Creates a new builder.voidecho(RestRequest req, RestResponse res, String remainder) [* /echo/*] — emit an introspection echo of the inbound request.longReturns the configured body-capture cap (test/inspection helper).Returns the explicit enablement tri-state configured on the builder (test/inspection helper).Returns the redacted-header set as lowercased, immutable strings (test/inspection helper).
-
Field Details
-
REDACTED
Sentinel value emitted in place of redacted header values. Re-exportsRedactedHeaders.REDACTED.- See Also:
-
DEFAULT_BODY_LIMIT
Default body capture cap, in bytes (1 MB).- See Also:
-
DEFAULT_REDACTED_HEADERS
Default redacted-header set (case-insensitive lookup). Re-exportsRedactedHeaders.DEFAULT.
-
-
Constructor Details
-
EchoMixin
public EchoMixin()No-arg constructor — usesDEFAULT_BODY_LIMITandDEFAULT_REDACTED_HEADERS. -
EchoMixin
Builder constructor.- Parameters:
builder- The builder. Must not benull.
-
-
Method Details
-
create
Creates a new builder.- Returns:
- A new builder.
-
echo
public void echo(RestRequest req, RestResponse res, @Path("/*") String remainder) throws IOException [* /echo/*] — emit an introspection echo of the inbound request.Returns
404 Not Foundwhen the endpoint is notenabledfor the current request. Reachability is independent of the JUL logger level (see the class-level Javadoc for the enablement rules and the global-fallback blast-radius warning).- Parameters:
req- The current REST request.res- The current REST response.remainder- The path remainder after the mount prefix (multi-segment, may be empty).- Throws:
IOException- If an I/O error occurs while reading the request or writing the response.NotFound- When the endpoint resolves to disabled for the current request.
-
getBodyLimit
Returns the configured body-capture cap (test/inspection helper).- Returns:
- The body capture cap, in bytes.
-
getRedactedHeadersLower
Returns the redacted-header set as lowercased, immutable strings (test/inspection helper).- Returns:
- The redacted-header set.
-
getEnabled
Returns the explicit enablement tri-state configured on the builder (test/inspection helper).- Returns:
Boolean.TRUE/Boolean.FALSEwhen explicitly configured, ornullwhen unset (deferred to the${juneau.echo.enabled:false}deployment fallback).
-