| --- |
| layout: default |
| title: Static Content |
| parent: |
| title: Core Developers |
| url: index |
| --- |
| |
| # Static Content |
| {:.no_toc} |
| |
| * Will be replaced with the ToC, excluding a header |
| {:toc} |
| |
| Struts can serve a static content like CSS and JavaScript files using a predefined path. By default, these resources |
| are served using `/static` path defined using a constant `struts.ui.staticContentPath` - see below for more details. |
| |
| Please remember to include this path in your filter mapping if you use a custom mapping, see [web.xml](web-xml.md) example config. |
| |
| ## Disabling static content |
| |
| You can disable this feature by setting the following constant to `false`. Once disabled you must provided the required |
| CSS & JavaScript files on your own, which can be a good thing when you want to use a CDN. |
| |
| ```xml |
| <constant name="struts.serve.static" value="false"/> |
| ``` |
| |
| > If you disable this feature, but you use the `xhtml`, or `css_xhtml` theme, make sure the JavasScript and CSS files |
| > shipped inside the core jar are extracted to your web application directory or served in some other way. |
| |
| ## Custom Static Content Loaders |
| |
| Static content is served by an implementation of `org.apache.struts2.dispatcher.StaticContentLoader`. To write your own |
| `StaticContentLoader`, implement `StaticContentLoader` and define a bean for the class: |
| |
| ```xml |
| <bean type="org.apache.struts2.dispatcher.StaticContentLoader" class="MyStaticContentLoader" name="myLoader"/> |
| <constant name="struts.staticContentLoader" value="myLoader"/> |
| ``` |
| |
| ## Default Content Loader |
| |
| The Apache Struts provides a default implementation of `StaticContentLoader` which |
| is `org.apache.struts2.dispatcher.DefaultStaticContentLoader`. This loader will handle urls that start with "/static/" |
| by default. |
| |
| This content loader can serve static content from the classpath, so when writing a plugin, you can put a file inside |
| your plugin's jar like "/static/image/banner.jpg" and it will be served when the url "/static/image/banner.jpg" is |
| requested. |
| |
| > This loader is not optimized to handle static content, and to improve performance, it is recommended that you extract |
| > your static content to the web application directory, and let the container handle them. |
| |
| ## Default path |
| |
| If needed you can change the default path at which static content is served. Just define a new `constant` in your |
| `struts.xml` with a path as below: |
| |
| ```xml |
| <constant name="struts.ui.staticContentPath" value="/my-static-content"/> |
| ``` |
| |
| This value is also used by the Default Content Loader. |
| |
| ## WebJars support |
| |
| {:.alert .alert-info} |
| Available since Struts 7.3.0. |
| |
| [WebJars](https://www.webjars.org/) package client-side libraries (Bootstrap, jQuery, …) as JARs, shipping their assets |
| under `META-INF/resources/webjars/<name>/<version>/…`. Instead of vendoring these files into your web application and |
| re-committing them on every upgrade, you add the WebJar as a regular dependency and let Struts resolve and serve it. |
| |
| Struts serves WebJar assets through the same static content pipeline described above, under |
| `<staticContentPath>/webjars/**` (by default `/static/webjars/**`). Resolution is **version-less**: you reference a |
| resource by its logical path and Struts resolves the version present on the classpath. For example, a request for: |
| |
| ``` |
| /static/webjars/bootstrap/css/bootstrap.min.css |
| ``` |
| |
| is served from `META-INF/resources/webjars/bootstrap/5.3.8/css/bootstrap.min.css` (whichever version is on the |
| classpath). To emit these URLs from a template without hardcoding the version, use the |
| [webjar tag](../tag-developers/webjar-tag): |
| |
| ```jsp |
| <link rel="stylesheet" href="<s:webjar path="bootstrap/css/bootstrap.min.css"/>"/> |
| ``` |
| |
| Struts resolves versions using [webjars-locator-lite](https://github.com/webjars/webjars-locator-lite), which is bundled |
| with `struts2-core`. |
| |
| ### Configuration |
| |
| | Constant | Default | Description | |
| |----------------------------|---------|---------------------------------------------------------------------------------------------------| |
| | `struts.webjars.enabled` | `true` | Master switch for resolving and serving WebJar assets under `<staticContentPath>/webjars/**`. | |
| | `struts.webjars.allowlist` | (empty) | Optional comma-separated allowlist of WebJar names. When empty, all WebJars on the classpath are allowed. | |
| |
| To restrict serving to specific WebJars: |
| |
| ```xml |
| <constant name="struts.webjars.allowlist" value="bootstrap,jquery"/> |
| ``` |
| |
| To disable the feature entirely: |
| |
| ```xml |
| <constant name="struts.webjars.enabled" value="false"/> |
| ``` |
| |
| ### Security |
| |
| Resolution is hard-constrained to the `META-INF/resources/webjars/` root: path traversal attempts (`..`, `.`, |
| backslashes) are rejected before resolution, the resolved path is re-checked for containment, and only paths that the |
| locator can resolve to a real WebJar are served. Disabled, unresolved, traversal, and allowlist-blocked requests all |
| **fail closed** - a `404` when serving and empty output when building URLs. |
| |
| ### Customizing resolution |
| |
| URL resolution is provided by the `org.apache.struts2.webjars.WebJarUrlProvider` container bean (default implementation |
| `DefaultWebJarUrlProvider`), which exposes `resolveResourcePath(String)` and `resolveUrl(String, HttpServletRequest)`. |
| Plugins and applications can replace it by declaring their own bean: |
| |
| ```xml |
| <bean type="org.apache.struts2.webjars.WebJarUrlProvider" class="com.example.MyWebJarUrlProvider" name="myProvider"/> |
| <constant name="struts.webjars.urlProvider" value="myProvider"/> |
| ``` |
| |
| ## Preventing Struts from handling a request |
| |
| If there is a request that Struts is handling as an action, and you wish to make Struts ignore it, |
| you can do so by specifying a comma separated list of regular expressions like: |
| |
| ```xml |
| <constant name="struts.action.excludePattern" value="/some/content/.*,/other/content/.*"/> |
| ``` |
| |
| These regular expression will be evaluated against the request's URI (`HttpServletRequest.getRequestURI()`), and if any |
| of them matches, then Struts will not handle the request. |
| |
| To evaluate each pattern the `Pattern` class from JDK will be used, you can find more about what kind of pattern you can |
| use in the [Pattern class JavaDoc](http://docs.oracle.com/javase/1.5.0/docs/api/java/util/regex/Pattern). |
| |
| Since Struts 6.1.0 you can use a custom separator. By default, the provided patterns are split using comma `,`, |
| but it can happen that you want to use comma in your patterns as well, e.g.: `/static/[a-z]{1,10}.json`. In such case |
| you can define a custom separator to be used to split the patterns, use `struts.action.excludePattern.separator` |
| constant: |
| |
| ```xml |
| <constant name="struts.action.excludePattern.separator" value="//"/> |
| <constant name="struts.action.excludePattern" value="/some/[a-zA-Z]{1,10}.json///other/content/.*"/> |
| ``` |