This is an automated email from the ASF dual-hosted git repository.
svenmeier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/wicket.git
The following commit(s) were added to refs/heads/master by this push:
new 813d420 WICKET-6821 fixed header decorator ordering
813d420 is described below
commit 813d42093fd3e064ed80c35e2e0e3295f1a9b1a3
Author: Sven Meier <[email protected]>
AuthorDate: Wed Oct 7 09:06:11 2020 +0200
WICKET-6821 fixed header decorator ordering
The CSP header decorator must be added after any filtering decorator
(i.e. immediately before the aggregator) so it has the chance to add CSP
nonce before a possible filter might move the header item elsewhere.
---
.../wicket/csp/ContentSecurityPolicySettings.java | 2 +-
.../html/HeaderResponseDecoratorCollection.java | 42 ++++++++++++++++---
.../wicket/markup/html/HeaderContributorTest.java | 48 ++++++++++++++++++++++
3 files changed, 86 insertions(+), 6 deletions(-)
diff --git
a/wicket-core/src/main/java/org/apache/wicket/csp/ContentSecurityPolicySettings.java
b/wicket-core/src/main/java/org/apache/wicket/csp/ContentSecurityPolicySettings.java
index de79be8..c6f550e 100644
---
a/wicket-core/src/main/java/org/apache/wicket/csp/ContentSecurityPolicySettings.java
+++
b/wicket-core/src/main/java/org/apache/wicket/csp/ContentSecurityPolicySettings.java
@@ -206,7 +206,7 @@ public class ContentSecurityPolicySettings
{
application.getRequestCycleListeners().add(new
CSPRequestCycleListener(this));
application.getHeaderResponseDecorators()
- .add(response -> new
CSPNonceHeaderResponseDecorator(response, this));
+ .addPreResourceAggregationDecorator(response -> new
CSPNonceHeaderResponseDecorator(response, this));
application.mount(new ReportCSPViolationMapper(this));
}
diff --git
a/wicket-core/src/main/java/org/apache/wicket/markup/html/HeaderResponseDecoratorCollection.java
b/wicket-core/src/main/java/org/apache/wicket/markup/html/HeaderResponseDecoratorCollection.java
index ce71f8b..1b94522 100644
---
a/wicket-core/src/main/java/org/apache/wicket/markup/html/HeaderResponseDecoratorCollection.java
+++
b/wicket-core/src/main/java/org/apache/wicket/markup/html/HeaderResponseDecoratorCollection.java
@@ -33,13 +33,15 @@ public class HeaderResponseDecoratorCollection implements
IHeaderResponseDecorat
{
private final List<IHeaderResponseDecorator> decorators = new
CopyOnWriteArrayList<>();
+ private IHeaderResponseDecorator resourceAggregation =
ResourceAggregator::new;
+
public HeaderResponseDecoratorCollection()
{
- decorators.add(response -> new ResourceAggregator(response));
+ decorators.add(resourceAggregation);
}
/**
- * Adds a new {@link IHeaderResponseDecorator} that will be invoked
prior to all already
+ * Adds a new {@link IHeaderResponseDecorator} that will decorates
prior to all already
* registered decorators. That means, the first to be added will be
wrapped by a
* {@link ResourceAggregator} like this: {@code new
ResourceAggregator(first)}. The second will
* be wrapped by the first and the aggregator: {@code new
ResourceAggregator(first(second))}.
@@ -56,15 +58,42 @@ public class HeaderResponseDecoratorCollection implements
IHeaderResponseDecorat
}
/**
- * Adds a new {@link IHeaderResponseDecorator} that will be invoked
after all already registered
+ * Adds a new {@link IHeaderResponseDecorator} that decorates
immediately prior to resource
+ * aggregation.
+ *
+ * @param decorator
+ * The decorator to add, cannot be null.
+ * @return {@code this} for chaining.
+ *
+ * @see ResourceAggregator
+ */
+ public HeaderResponseDecoratorCollection
addPreResourceAggregationDecorator(
+ IHeaderResponseDecorator decorator)
+ {
+ Args.notNull(decorator, "decorator");
+
+ for (int i = 0; i < decorators.size(); i++)
+ {
+ if (decorators.get(i) == resourceAggregation)
+ {
+ decorators.add(i, decorator);
+ return this;
+ }
+ }
+
+ throw new IllegalStateException("no resource aggregation");
+ }
+
+ /**
+ * Adds a new {@link IHeaderResponseDecorator} that decorates after all
already registered
* decorators.
*
* @param decorator
* The decorator to add, cannot be null.
* @return {@code this} for chaining.
*/
- public HeaderResponseDecoratorCollection
- addPostProcessingDecorator(IHeaderResponseDecorator
decorator)
+ public HeaderResponseDecoratorCollection addPostProcessingDecorator(
+ IHeaderResponseDecorator decorator)
{
Args.notNull(decorator, "decorator");
decorators.add(decorator);
@@ -83,6 +112,7 @@ public class HeaderResponseDecoratorCollection implements
IHeaderResponseDecorat
{
Args.notNull(decorator, "decorator");
decorators.clear();
+ resourceAggregation = null;
decorators.add(decorator);
return this;
}
@@ -92,7 +122,9 @@ public class HeaderResponseDecoratorCollection implements
IHeaderResponseDecorat
{
IHeaderResponse ret = response;
for (IHeaderResponseDecorator curDecorator : decorators)
+ {
ret = curDecorator.decorate(ret);
+ }
return ret;
}
}
diff --git
a/wicket-core/src/test/java/org/apache/wicket/markup/html/HeaderContributorTest.java
b/wicket-core/src/test/java/org/apache/wicket/markup/html/HeaderContributorTest.java
index f6d8d54..4936107 100644
---
a/wicket-core/src/test/java/org/apache/wicket/markup/html/HeaderContributorTest.java
+++
b/wicket-core/src/test/java/org/apache/wicket/markup/html/HeaderContributorTest.java
@@ -16,9 +16,11 @@
*/
package org.apache.wicket.markup.html;
+import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
import org.apache.wicket.Component;
import org.apache.wicket.MarkupContainer;
@@ -29,6 +31,8 @@ import
org.apache.wicket.ajax.attributes.AjaxRequestAttributes;
import org.apache.wicket.behavior.Behavior;
import org.apache.wicket.markup.IMarkupResourceStreamProvider;
import org.apache.wicket.markup.head.IHeaderResponse;
+import org.apache.wicket.markup.head.internal.HeaderResponse;
+import org.apache.wicket.request.Response;
import org.apache.wicket.util.resource.IResourceStream;
import org.apache.wicket.util.resource.StringResourceStream;
import org.apache.wicket.util.tester.WicketTestCase;
@@ -56,6 +60,50 @@ class HeaderContributorTest extends WicketTestCase
}
/**
+ * WICKET-6821 ensure correct ordering of header decorators
+ */
+ @Test
+ void testHeaderContributorOrder()
+ {
+ final AtomicInteger counter = new AtomicInteger();
+
+ class AssertOrder implements IHeaderResponseDecorator {
+
+ private int order;
+
+ AssertOrder(int order)
+ {
+ this.order = order;
+ }
+
+ @Override
+ public IHeaderResponse decorate(IHeaderResponse
response)
+ {
+ assertEquals(order, counter.getAndIncrement());
+
+ return response;
+ }
+ }
+
+ HeaderResponseDecoratorCollection decorators =
tester.getApplication().getHeaderResponseDecorators();
+ decorators.add(new AssertOrder(2));
+ decorators.add(new AssertOrder(1));
+ decorators.addPreResourceAggregationDecorator(new
AssertOrder(3));
+ decorators.add(new AssertOrder(0));
+ decorators.addPostProcessingDecorator(new AssertOrder(4));
+
+ tester.getApplication().decorateHeaderResponse(new
HeaderResponse()
+ {
+
+ @Override
+ protected Response getRealResponse()
+ {
+ return null;
+ }
+ });
+ }
+
+ /**
* A page for the test
*/
public static class HeaderContributorTestPage extends WebPage