[
https://issues.apache.org/jira/browse/WW-5640?focusedWorklogId=1027815&page=com.atlassian.jira.plugin.system.issuetabpanels:worklog-tabpanel#worklog-1027815
]
ASF GitHub Bot logged work on WW-5640:
--------------------------------------
Author: ASF GitHub Bot
Created on: 01/Jul/26 10:19
Start Date: 01/Jul/26 10:19
Worklog Time Spent: 10m
Work Description: lukaszlenart opened a new pull request, #1765:
URL: https://github.com/apache/struts/pull/1765
Fixes [WW-5640](https://issues.apache.org/jira/browse/WW-5640)
## What
Adds first-class **WebJars** support to Struts core: client-side libraries
packaged as WebJars (`org.webjars:*`, shipped under
`META-INF/resources/webjars/<name>/<version>/…`) can be referenced by a
**version-less logical path** and are resolved + served through Struts'
existing static-content pipeline.
Example: a template references `bootstrap/css/bootstrap.min.css` → Struts
serves `META-INF/resources/webjars/bootstrap/5.3.8/css/bootstrap.min.css` at
`<ctx>/static/webjars/bootstrap/5.3.8/css/bootstrap.min.css`.
## Why
Plugins/apps currently vendor client-side assets on the classpath and
re-commit them each release (the struts2-bootstrap plugin commits ~2000 files
by hand). WebJars replace this with a dependency bump (auto-updatable via
Renovate/Dependabot). First intended consumer: the struts2-bootstrap plugin
(separate work).
## Changes
- **Dependency:** `org.webjars:webjars-locator-lite:1.1.3` (MIT; single
Apache-2.0 transitive dep `jspecify`; no Jackson/classpath-scanner — the
variant Spring Framework 6.2 adopted).
- **`WebJarUrlProvider`** (container bean, the public seam for plugins) +
`DefaultWebJarUrlProvider` wrapping a singleton `WebJarVersionLocator`.
- **Serving:** a `/webjars/**` branch in `DefaultStaticContentLoader`
reusing existing caching; content-type map extended for
fonts/svg/source-maps/json/ico.
- **`<s:webjar>` tag + `<@s.webjar>` macro** emitting the resolved URL
string (composes with `<s:script>`/`<s:link>`; supports `var`).
- **Config:** `struts.webjars.enabled` (default `true`),
`struts.webjars.allowlist` (comma-separated; empty = all).
## Security
Resolution is hard-constrained to the `META-INF/resources/webjars/` root:
per-segment `..`/`.` rejection and backslash rejection before the locator is
called, a containment re-check on the resolved path, locator-backed resolution
only (unknown webjar → null), plus the optional allowlist. Unresolved /
disabled / traversal / allowlist-blocked all **fail closed** (404 when serving,
empty output when building URLs). This is hardening for the new endpoint, not a
fix to existing shipped behavior.
## Testing
- Unit: resolution (known → versioned path/URL; unknown → empty), traversal
rejection (both `resolveResourcePath` and `resolveUrl`), allowlist, disabled;
content-type mappings.
- Serving: 200 + content-type for a known asset, 404 for unknown, 404 when
disabled (servlet-mocked).
- Tag/macro: renders the resolved URL; `var` storage; empty on unresolved.
- Full `core` suite: **2985 tests, 0 failures**. No regression to existing
static-content serving.
Backward compatible: `enabled=true` only activates the new
`<staticContentPath>/webjars/**` namespace; existing `/static/**` serving is
untouched.
Issue Time Tracking
-------------------
Worklog Id: (was: 1027815)
Remaining Estimate: 0h
Time Spent: 10m
> Add WebJars support to Struts core
> ----------------------------------
>
> Key: WW-5640
> URL: https://issues.apache.org/jira/browse/WW-5640
> Project: Struts 2
> Issue Type: New Feature
> Components: Core
> Reporter: Lukasz Lenart
> Priority: Major
> Fix For: 7.3.0
>
> Time Spent: 10m
> Remaining Estimate: 0h
>
> Add first-class WebJars support to Struts core so client-side libraries
> packaged as WebJars (shipped under
> {{META-INF/resources/webjars/<name>/<version>/…}}) can be referenced by a
> version-less logical path and served through Struts' existing static-content
> pipeline.
> Example: a template references bootstrap/css/bootstrap.min.css; Struts
> resolves and serves
> {{META-INF/resources/webjars/bootstrap/5.3.8/css/bootstrap.min.css}}.
> Today plugins and apps vendor client-side assets directly on the classpath
> and re-commit them on every upgrade (the struts2-bootstrap plugin commits
> ~2000 files by hand each release). WebJars replace this with a dependency
> bump (auto-updatable via Renovate/Dependabot).
> Scope (core only):
> - Add {{org.webjars:webjars-locator-lite}} (MIT; one Apache-2.0 transitive
> dep) for version resolution.
> - New {{WebJarUrlProvider}} container bean — the public, injectable seam for
> plugins.
> - Serve {{<staticContentPath>/webjars/**}} via a branch in
> {{DefaultStaticContentLoader}}, reusing existing caching; extend content-type
> coverage for fonts/svg/source-maps.
> - Thin {{<s:webjar>}} tag + {{<@s.webjar>}} macro emitting the resolved URL
> string.
> - New config: {{struts.webjars.enabled}} (default true),
> {{struts.webjars.allowlist}} (optional).
> - Security: constrain resolution to the webjars root, block .. traversal,
> fail closed (404 / no URL) on unresolved paths.
--
This message was sent by Atlassian Jira
(v8.20.10#820010)