enkan-core package has middlewares as follows:
AuthenticationMiddleware enables to authenticate a request using some backends.
| Name | Description |
|---|---|
| backends | The list of authentication backends. |
app.use(new AuthenticationMiddleware(backends));
app.use(new ServiceUnavailableMiddleware(serviceUnavailableEndpoint));
| Name | Type | Description |
|---|---|---|
| endpoint | Endpoint | Returns the response when service is unavailable. |
enkan-web package has middlewares as follows:
AbsoluteRedirectsMiddleware rewrites the URL contains Location http response header to the absolute URL.
Location: /abc/123
↓
Location: http://myhost/abc/123
app.use(new AbsoluteRedirectsMiddleware());
AbsoluteRedirectsMiddleware has no properties.
AntiForgeryMiddleware appends the token check for protecting from the CSRF attack.
When the request method isn’t GET/HEAD/OPTIONS, AntiForgeryMiddleware validates the given token.
If the token is invalid, it returns the forbidden response.
Because AntiForgeryMiddleware requires Session, We recommend using Conversation instead of this.
app.use(new AntiForgeryMiddleware());
AntiForgeryMiddleware has no properties.
Parses the Accept header and sets the value to a request.
app.use(new ContentNegotiationMiddleware());
Adds the Content-Type header if the response does not contains a Content-Type header yet.
app.use(new ContentTypeMiddleware());
Creates a conversation and save states related with its conversation to the conversation store.
app.use(new ConversationMiddleware());
Parses Cookie header and sets the Set-Cookie header to the response.
app.use(new CookiesMiddleware());
Generates a cryptographically random per-request CSP nonce (128-bit, Base64url-encoded) and
injects it into the Content-Security-Policy script-src directive.
Place before SecurityHeadersMiddleware so the nonce is injected into the CSP header that
SecurityHeadersMiddleware adds.
The nonce is available to controllers and templates via:
String nonce = request.getExtension(CspNonceMiddleware.EXTENSION_KEY); // "cspNonce"
CspNonceMiddleware nonce = new CspNonceMiddleware();
nonce.setStrictDynamic(true); // adds 'strict-dynamic' to script-src
app.use(nonce);
app.use(new SecurityHeadersMiddleware()); // downstream
<!-- Thymeleaf / Freemarker template -->
<script th:nonce="${#request.getExtension('cspNonce')}">
// inline script
</script>
| Name | Type | Default | Description |
|---|---|---|---|
strictDynamic | boolean | false | Adds 'strict-dynamic' to the script-src directive |
Adds the default charset to the response.
app.use(new DefaultCharsetMiddleware());
Validates Content-Digest and Repr-Digest request headers per
RFC 9530. Supports sha-256 and sha-512.
Returns 400 if the digest does not match; passes through if neither header is present.
Note: The entire request body is buffered for digest computation. Do not apply to
large streaming uploads unconditionally — use a predicate to scope it to relevant routes.
app.use(new DigestValidationMiddleware());
Implements the W3C Resource Isolation Policy using
Sec-Fetch-Site and Sec-Fetch-Mode request headers. Blocks cross-origin, non-navigational
requests by default. Returns 403 for blocked requests.
Browsers that do not send Sec-Fetch-* headers (non-browser clients, legacy browsers) are
always allowed through. Combine with CSRF tokens for full defense against those clients.
When using CorsMiddleware, add the CORS-enabled paths to allowedPaths so preflight
(OPTIONS) requests are not blocked before reaching CorsMiddleware.
FetchMetadataMiddleware fm = new FetchMetadataMiddleware();
fm.setAllowedPaths(Set.of("/api/public/feed", "/health"));
app.use(fm);
| Name | Type | Default | Description |
|---|---|---|---|
allowedPaths | Set<String> | empty | Exact URI paths allowed to receive cross-origin requests |
Serializes and deserializes a flash value.
app.use(new FlashMiddleware());
Enkan Session has no expires in default. This middleware append the feature of timeout to the session.
app.use(new IdleSessionTimeoutMiddleware());
Override a request method.
app.use(new MethodOverrideMiddleware());
Parses the multipart request.
app.use(new MultipartParamsMiddleware());
NestedParamsMiddleware enables to parse nested parameters like foo[][bar]. It requires ParamMiddleware.
app.use(new NestedParamsMiddleware());
Normalize the parameter values. It’s for trimming spaces or converting letter case.
app.use(new NormalizationMiddleware());
ParamMiddleware enables to parse urlencoded query string and post body and set to a request object.
app.use(new ParamsMiddleware());
Enforces a per-request processing timeout using Java’s StructuredTaskScope (preview API).
Runs the downstream middleware chain in a virtual thread; returns the configured HTTP status
(default 504 Gateway Timeout) if processing exceeds the timeout.
Preview API: requires
--enable-previewat both compile and run time.ThreadLocal warning: ThreadLocal state is not inherited by the virtual thread spawned
internally. Doma2’sDomaTransactionMiddlewareuses ThreadLocal and must be placed
downstream (inside) ofRequestTimeoutMiddleware.
RequestTimeoutMiddleware timeout = new RequestTimeoutMiddleware();
timeout.setTimeoutMillis(30_000); // 30 seconds
timeout.setTimeoutStatus(504);
app.use(timeout);
| Name | Type | Default | Description |
|---|---|---|---|
timeoutMillis | long | 30000 | Timeout in milliseconds. Must be positive. |
timeoutStatus | int | 504 | HTTP status code returned on timeout (100–599). |
Returns the asset file that is searched from classpath.
app.use(new ResourceMiddleware());
| Name | Description |
|---|---|
| rootPath | The path prefix. Default value is public |
SessionMiddleware enables to store/load session objects to/from in-memory stores.
app.use(new SessionMiddleware());
| Name | Description |
|---|---|
| cookieName | A name of cookie for session id. Default value is enkan-session |
| store | A storage for session. |
Applies a suite of security-related HTTP response headers in a single middleware (similar to Helmet.js for Express).
All headers are enabled by default with safe values. Pass null to any setter to disable a specific header.
| Header | Default value |
|---|---|
Content-Security-Policy | default-src 'self' |
Strict-Transport-Security | max-age=15552000; includeSubDomains |
X-Content-Type-Options | nosniff |
X-Frame-Options | SAMEORIGIN |
X-XSS-Protection | 0 (disabled — use CSP instead) |
Referrer-Policy | strict-origin-when-cross-origin |
Cross-Origin-Opener-Policy | same-origin |
Cross-Origin-Resource-Policy | same-origin |
Cross-Origin-Embedder-Policy | require-corp |
Permissions-Policy | (disabled by default) |
// All defaults
app.use(new SecurityHeadersMiddleware());
// Custom CSP, disable HSTS for local development
SecurityHeadersMiddleware sec = new SecurityHeadersMiddleware();
sec.setContentSecurityPolicy("default-src 'self'; img-src *");
sec.setStrictTransportSecurity(null); // disable
app.use(sec);
| Name | Description |
|---|---|
contentSecurityPolicy | Content-Security-Policy value. null disables the header. |
strictTransportSecurity | Strict-Transport-Security value. null disables the header. |
contentTypeOptions | X-Content-Type-Options value. Default: nosniff. |
frameOptions | X-Frame-Options value. Default: SAMEORIGIN. |
xssProtection | X-XSS-Protection value. Default: 0. |
referrerPolicy | Referrer-Policy value. |
crossOriginOpenerPolicy | Cross-Origin-Opener-Policy value. |
crossOriginResourcePolicy | Cross-Origin-Resource-Policy value. |
crossOriginEmbedderPolicy | Cross-Origin-Embedder-Policy value. |
permissionsPolicy | Permissions-Policy value. null (default) disables the header. |
reportingEndpoints | Reporting-Endpoints value. null (default) disables the header. |
Verifies RFC 9421 HTTP Message Signatures on incoming
requests. Verified results are stored in the request extension under the key
SignatureVerificationMiddleware.EXTENSION_KEY ("signatureVerifyResults").
Returns 401 if required labels or components are missing/invalid; 400 on malformed headers.
See Security guide for full usage.
SignatureVerificationMiddleware verify =
new SignatureVerificationMiddleware(keyResolver);
verify.setRequiredLabels(Set.of("sig1"));
verify.setRequiredComponents(Set.of("@method", "@path", "content-type"));
app.use(verify);
| Name | Type | Description |
|---|---|---|
requiredLabels | Set<String> | Signature labels that must be present and valid |
requiredComponents | Set<String> | Component identifiers that must be covered by the signature |
Adds the response header for tracing using middlewares.
app.use(new TraceMiddleware());
Invoke a controller method.
app.use(new ControllerInvokerMiddleware());
Populate the request body to a Java bean object.
app.use(new FormMiddleware());
FormMiddleware has no properties.
Render HTML using a template. When a controller returns TemplatedHttpResponse, it has yet to be rendered.
app.use(new RenderTemplateMiddleware());
RenderTemplateMiddleware has no properties.
Routes the request to a controller method.
app.use(new RoutingMiddleware(routes));
| Name | Description |
|---|---|
| routes | Defined routes |
Deserialize the request body and serializes the response body.
app.use(new SerDesMiddleware());
| Name | Description |
|---|---|
| bodyReaders | |
| bodyWriters | |
Manages database transactions around controller invocation.
// requires enkan-component-doma2 dependency
app.use(new DomaTransactionMiddleware<>(config));
Validates the body object. If body object implements the Validatable interface, the error messages are set to it.
app.use(new ValidateBodyMiddleware());
ValidateBodyMiddleware has no properties.
CorsMiddleware handles Cross-Origin Resource Sharing (CORS) headers.
app.use(new CorsMiddleware());
ForwardedMiddleware applies forwarded-address information from trusted reverse proxies.
It supports both the standard Forwarded header (RFC 7239) and the legacy X-Forwarded-For,
X-Forwarded-Proto, and X-Forwarded-Host headers. Headers are only trusted when the
direct connection’s remote address matches a configured trusted proxy CIDR range,
preventing header spoofing by untrusted clients.
When headers are trusted, the middleware updates remoteAddr, scheme, and serverName
on the request.
// Default — trusts loopback only (127.0.0.0/8 and ::1/128)
app.use(new ForwardedMiddleware());
// With a custom trusted proxy range
ForwardedMiddleware fw = new ForwardedMiddleware();
fw.setTrustedProxies(List.of("10.0.0.0/8", "172.16.0.0/12", "127.0.0.0/8", "::1/128"));
app.use(fw);
| Property | Type | Default | Description |
|---|---|---|---|
trustedProxies | List<String> | ["127.0.0.0/8", "::1/128"] | CIDR ranges of trusted proxies |
preferStandard | boolean | true | Prefer RFC 7239 Forwarded over legacy X-Forwarded-* when both are present |
Sets Cache-Control response headers based on configurable rules.
A staticPattern regex distinguishes static assets from dynamic responses.
URIs matching the pattern receive the staticDirective; all others receive the dynamicDirective.
If a downstream handler already set Cache-Control, this middleware leaves it unchanged.
CacheControlMiddleware cache = new CacheControlMiddleware();
cache.setStaticPattern(Pattern.compile("^/assets/"));
cache.setStaticMaxAge(Duration.ofDays(365));
cache.setDynamicDirective("no-cache");
app.use(cache);
| Name | Type | Description | Default |
|---|---|---|---|
staticPattern | Pattern | Regex to identify static asset URIs | null (disabled) |
staticMaxAge | Duration | Convenience setter: produces public, max-age=N, immutable | — |
staticDirective | String | Full directive for static assets | "public, max-age=31536000, immutable" |
dynamicDirective | String | Directive for non-static responses; null to omit | "no-cache" |
Stores a non-transactional DSLContext in the request extensions under the key jooqDslContext.
Stack JooqTransactionMiddleware after this when transactional support is needed.
Requires JooqProvider component.
// requires enkan-component-jooq dependency
app.use(new JooqDslContextMiddleware());
Wraps the downstream handler in a jOOQ transaction when the matched controller class or method is annotated with @Transactional.
Method-level annotation overrides class-level. Only REQUIRED propagation is supported.
Requires JooqDslContextMiddleware to be stacked before this middleware.
app.use(new JooqDslContextMiddleware());
app.use(new JooqTransactionMiddleware());
Creates an OpenTelemetry SERVER span for each HTTP request.
Extracts W3C Trace Context (traceparent/tracestate) from incoming headers.
Records HTTP semantic convention attributes: method, URL path, query string, status code, server address/port, client address, and network protocol version.
Requires OpenTelemetryComponent.
// requires enkan-component-opentelemetry dependency
app.use(new TracingMiddleware());