You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@wicket.apache.org by mg...@apache.org on 2017/08/06 12:05:43 UTC

[2/8] wicket git commit: Fixes issue of pushing resources

Fixes issue of pushing resources

Project: http://git-wip-us.apache.org/repos/asf/wicket/repo
Commit: http://git-wip-us.apache.org/repos/asf/wicket/commit/50edbc4c
Tree: http://git-wip-us.apache.org/repos/asf/wicket/tree/50edbc4c
Diff: http://git-wip-us.apache.org/repos/asf/wicket/diff/50edbc4c

Branch: refs/heads/master
Commit: 50edbc4c01a8ed0e4e1f2394b9db4156d7332620
Parents: 620081b
Author: Tobias Soloschenko <ts...@sapient.com>
Authored: Tue Aug 1 07:32:47 2017 +0200
Committer: Martin Tzvetanov Grigorov <mg...@apache.org>
Committed: Sun Aug 6 14:59:33 2017 +0300

----------------------------------------------------------------------
 .../http2/markup/head/NoopPushBuilder.java      |   2 +-
 .../wicket/http2/markup/head/PushBuilder.java   |   6 +-
 .../http2/markup/head/PushHeaderItem.java       |  59 +++++++---
 .../wicket/http2/markup/head/PushItem.java      | 117 +++++++++++++++++--
 .../http2/markup/head/PushItemHeaderValue.java  | 101 ++++++++++++++++
 .../http2/markup/head/Jetty9PushBuilder.java    |  19 ++-
 .../wicket-http2/wicket-http2-tomcat/pom.xml    |   2 +-
 .../http2/markup/head/Tomcat85PushBuilder.java  |  17 ++-
 .../http2/markup/head/UndertowPushBuilder.java  |  17 ++-
 .../main/asciidoc/http2push/http2push_1.adoc    |   4 +-
 10 files changed, 301 insertions(+), 43 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/wicket/blob/50edbc4c/wicket-experimental/wicket-http2/wicket-http2-core/src/main/java/org/apache/wicket/http2/markup/head/NoopPushBuilder.java
----------------------------------------------------------------------
diff --git a/wicket-experimental/wicket-http2/wicket-http2-core/src/main/java/org/apache/wicket/http2/markup/head/NoopPushBuilder.java b/wicket-experimental/wicket-http2/wicket-http2-core/src/main/java/org/apache/wicket/http2/markup/head/NoopPushBuilder.java
index b9042a2..eb6dd4d 100644
--- a/wicket-experimental/wicket-http2/wicket-http2-core/src/main/java/org/apache/wicket/http2/markup/head/NoopPushBuilder.java
+++ b/wicket-experimental/wicket-http2/wicket-http2-core/src/main/java/org/apache/wicket/http2/markup/head/NoopPushBuilder.java
@@ -52,7 +52,7 @@ public class NoopPushBuilder implements PushBuilder
 	 * </p>
 	 */
 	@Override
-	public void push(HttpServletRequest httpServletRequest, String... paths)
+	public void push(HttpServletRequest httpServletRequest, PushItem... pushItems)
 	{
 		LOG.warn(
 			"This PushBuilder does nothing. Please use one of the other implementations - Jetty9 or Tomcat8.5+");

http://git-wip-us.apache.org/repos/asf/wicket/blob/50edbc4c/wicket-experimental/wicket-http2/wicket-http2-core/src/main/java/org/apache/wicket/http2/markup/head/PushBuilder.java
----------------------------------------------------------------------
diff --git a/wicket-experimental/wicket-http2/wicket-http2-core/src/main/java/org/apache/wicket/http2/markup/head/PushBuilder.java b/wicket-experimental/wicket-http2/wicket-http2-core/src/main/java/org/apache/wicket/http2/markup/head/PushBuilder.java
index 7f1eccd..c651899 100644
--- a/wicket-experimental/wicket-http2/wicket-http2-core/src/main/java/org/apache/wicket/http2/markup/head/PushBuilder.java
+++ b/wicket-experimental/wicket-http2/wicket-http2-core/src/main/java/org/apache/wicket/http2/markup/head/PushBuilder.java
@@ -28,8 +28,8 @@ public interface PushBuilder
 	 * 
 	 * @param httpServletRequest
 	 *            the http servlet request to get the push builder from
-	 * @param paths
-	 *            the paths of the resources to be pushed
+	 * @param pushItems
+	 *            the pushItems of the resources to be pushed
 	 */
-	void push(HttpServletRequest httpServletRequest, String... paths);
+	void push(HttpServletRequest httpServletRequest, PushItem... pushItems);
 }

http://git-wip-us.apache.org/repos/asf/wicket/blob/50edbc4c/wicket-experimental/wicket-http2/wicket-http2-core/src/main/java/org/apache/wicket/http2/markup/head/PushHeaderItem.java
----------------------------------------------------------------------
diff --git a/wicket-experimental/wicket-http2/wicket-http2-core/src/main/java/org/apache/wicket/http2/markup/head/PushHeaderItem.java b/wicket-experimental/wicket-http2/wicket-http2-core/src/main/java/org/apache/wicket/http2/markup/head/PushHeaderItem.java
index 1660ef7..94d55ad 100644
--- a/wicket-experimental/wicket-http2/wicket-http2-core/src/main/java/org/apache/wicket/http2/markup/head/PushHeaderItem.java
+++ b/wicket-experimental/wicket-http2/wicket-http2-core/src/main/java/org/apache/wicket/http2/markup/head/PushHeaderItem.java
@@ -36,6 +36,7 @@ import org.apache.wicket.WicketRuntimeException;
 import org.apache.wicket.http2.Http2Settings;
 import org.apache.wicket.markup.head.HeaderItem;
 import org.apache.wicket.markup.html.WebPage;
+import org.apache.wicket.protocol.http.WebApplication;
 import org.apache.wicket.request.IRequestHandler;
 import org.apache.wicket.request.Request;
 import org.apache.wicket.request.Response;
@@ -97,7 +98,7 @@ public class PushHeaderItem extends HeaderItem
 	/**
 	 * The URLs of resources to be pushed to the client
 	 */
-	private Set<String> urls = new ConcurrentHashSet<String>(new TreeSet<String>());
+	private Set<PushItem> pushItems = new ConcurrentHashSet<PushItem>(new TreeSet<PushItem>());
 	/**
 	 * The web response of the page to apply the caching information to
 	 */
@@ -147,9 +148,9 @@ public class PushHeaderItem extends HeaderItem
 	public Iterable<?> getRenderTokens()
 	{
 		Set<String> tokens = new TreeSet<String>();
-		for (String url : urls)
+		for (PushItem pushItem : pushItems)
 		{
-			tokens.add(url + TOKEN_SUFFIX);
+			tokens.add(pushItem.getUrl() + TOKEN_SUFFIX);
 		}
 		return tokens;
 	}
@@ -305,7 +306,7 @@ public class PushHeaderItem extends HeaderItem
 		// Receives the vendor specific push builder
 		Http2Settings http2Settings = Http2Settings.Holder.get(Application.get());
 		PushBuilder pushBuilder = http2Settings.getPushBuilder();
-		pushBuilder.push(request, urls.toArray(new String[urls.size()]));
+		pushBuilder.push(request, pushItems.toArray(new PushItem[pushItems.size()]));
 	}
 
 	/**
@@ -337,7 +338,7 @@ public class PushHeaderItem extends HeaderItem
 				{
 					url = requestCycle.urlFor((ResourceReference)object, parameters);
 				}
-				else if (object instanceof Class)
+				else if (Page.class.isAssignableFrom(object.getClass()))
 				{
 					url = requestCycle.urlFor((Class<? extends Page>)object, parameters);
 				}
@@ -345,6 +346,10 @@ public class PushHeaderItem extends HeaderItem
 				{
 					url = requestCycle.urlFor((IRequestHandler)object);
 				}
+				else if (pushItem.getUrl() != null)
+				{
+					url = pushItem.getUrl();
+				}
 				else
 				{
 					Url encoded = new PageParametersEncoder().encodePageParameters(parameters);
@@ -361,7 +366,32 @@ public class PushHeaderItem extends HeaderItem
 					url = url.toString().substring(1);
 				}
 
-				urls.add(url.toString());
+				// The context path and the filter have to be applied to the URL, because otherwise
+				// the resource is not pushed correctly
+				StringBuffer partialUrl = new StringBuffer();
+				String contextPath = WebApplication.get().getServletContext().getContextPath();
+				partialUrl.append(contextPath);
+				if (!contextPath.equals("/"))
+				{
+					partialUrl.append("/");
+				}
+				String filterPath = WebApplication.get().getWicketFilter().getFilterPath();
+				if (filterPath.equals("/"))
+				{
+					filterPath = "";
+				}
+				else if (filterPath.endsWith("/"))
+				{
+					filterPath = filterPath.replaceAll(".$", "");
+				}
+				partialUrl.append(filterPath);
+				partialUrl.append(url.toString());
+
+				// Set the url the resource is going to be pushed with
+				pushItem.setUrl(partialUrl.toString());
+
+				// Apply the push item to be used during the push process
+				this.pushItems.add(pushItem);
 			}
 		return this;
 	}
@@ -419,18 +449,19 @@ public class PushHeaderItem extends HeaderItem
 	@Override
 	public boolean equals(Object o)
 	{
-		if (this == o) return true;
-		if (o == null || getClass() != o.getClass()) return false;
-		PushHeaderItem that = (PushHeaderItem) o;
-		return Objects.equals(urls, that.urls) &&
-				Objects.equals(pageWebResponse, that.pageWebResponse) &&
-				Objects.equals(pageWebRequest, that.pageWebRequest) &&
-				Objects.equals(page, that.page);
+		if (this == o)
+			return true;
+		if (o == null || getClass() != o.getClass())
+			return false;
+		PushHeaderItem that = (PushHeaderItem)o;
+		return Objects.equals(pushItems, that.pushItems) &&
+			Objects.equals(pageWebResponse, that.pageWebResponse) &&
+			Objects.equals(pageWebRequest, that.pageWebRequest) && Objects.equals(page, that.page);
 	}
 
 	@Override
 	public int hashCode()
 	{
-		return Objects.hash(urls, pageWebResponse, pageWebRequest, page);
+		return Objects.hash(pushItems, pageWebResponse, pageWebRequest, page);
 	}
 }

http://git-wip-us.apache.org/repos/asf/wicket/blob/50edbc4c/wicket-experimental/wicket-http2/wicket-http2-core/src/main/java/org/apache/wicket/http2/markup/head/PushItem.java
----------------------------------------------------------------------
diff --git a/wicket-experimental/wicket-http2/wicket-http2-core/src/main/java/org/apache/wicket/http2/markup/head/PushItem.java b/wicket-experimental/wicket-http2/wicket-http2-core/src/main/java/org/apache/wicket/http2/markup/head/PushItem.java
index e6f1f8d..1e73af9 100644
--- a/wicket-experimental/wicket-http2/wicket-http2-core/src/main/java/org/apache/wicket/http2/markup/head/PushItem.java
+++ b/wicket-experimental/wicket-http2/wicket-http2-core/src/main/java/org/apache/wicket/http2/markup/head/PushItem.java
@@ -16,6 +16,11 @@
  */
 package org.apache.wicket.http2.markup.head;
 
+import java.io.Serializable;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
 import org.apache.wicket.Component;
 import org.apache.wicket.request.mapper.parameter.PageParameters;
 
@@ -25,35 +30,74 @@ import org.apache.wicket.request.mapper.parameter.PageParameters;
  * 
  * @author Tobias Soloschenko
  */
-public class PushItem
+public class PushItem implements Serializable
 {
-	private Object object;
+	private static final long serialVersionUID = 1L;
+
+	private Serializable object;
 
 	private PageParameters pageParameters;
 
+	private String url;
+
+	private Map<String, PushItemHeaderValue> headers = new HashMap<>();
+
 	/**
 	 * Creates a push item
 	 * 
 	 * @param object
-	 *            the object
+	 *            the object to extract the push URL information from
 	 * @param pageParameters
 	 *            the page parameters
+	 * @param headers
+	 *            the headers to be applied to the push
 	 */
-	public PushItem(Object object, PageParameters pageParameters)
+	public PushItem(Serializable object, PageParameters pageParameters,
+		Map<String, PushItemHeaderValue> headers)
 	{
 		this.object = object;
 		this.pageParameters = pageParameters;
+		if (headers != null)
+		{
+			this.headers = headers;
+		}
 	}
 
 	/**
 	 * Creates a push item
 	 * 
 	 * @param object
-	 *            the object
+	 *            the object to extract the push URL information from
+	 * @param headers
+	 *            the headers to be applied to the push
 	 */
-	public PushItem(Object object)
+	public PushItem(Serializable object, Map<String, PushItemHeaderValue> headers)
 	{
-		this.object = object;
+		this(object, null, headers);
+	}
+
+	/**
+	 * Creates a push item
+	 *
+	 * @param object
+	 *            the object to extract the push URL information from
+	 * @param pageParameters
+	 *            the page parameters
+	 */
+	public PushItem(Serializable object, PageParameters pageParameters)
+	{
+		this(object, pageParameters, null);
+	}
+
+	/**
+	 * Creates a push item
+	 *
+	 * @param object
+	 *            the object to extract the push URL information from
+	 */
+	public PushItem(Serializable object)
+	{
+		this(object, null, null);
 	}
 
 	/**
@@ -64,9 +108,9 @@ public class PushItem
 	}
 
 	/**
-	 * Gets the object
+	 * Gets the object which contains the push URL information
 	 * 
-	 * @return the object
+	 * @return the object to extract the push URL information from
 	 */
 	public Object getObject()
 	{
@@ -74,13 +118,14 @@ public class PushItem
 	}
 
 	/**
-	 * Sets the object
+	 * Sets the object which contains the push URL information
 	 * 
 	 * @param object
-	 *            the object
+	 *            the object to extract the push URL information from
+	 * @see {@link org.apache.wicket.request.cycle.RequestCycle} (urlFor methods)
 	 * @return the push item
 	 */
-	public PushItem setObject(Object object)
+	public PushItem setObject(Serializable object)
 	{
 		this.object = object;
 		return this;
@@ -108,4 +153,52 @@ public class PushItem
 		this.pageParameters = pageParameters;
 		return this;
 	}
+
+	/**
+	 * Gets the URL composed within the push header item
+	 *
+	 * @see {@link org.apache.wicket.http2.markup.head.PushHeaderItem#push(List)}
+	 * @return the URL to be pushed
+	 */
+	public String getUrl()
+	{
+		return url;
+	}
+
+	/**
+	 * Sets the URL composed within the push header item
+	 *
+	 * @see {@link org.apache.wicket.http2.markup.head.PushHeaderItem#push(List)}
+	 * @param url
+	 *            the URL used to push the resource
+	 * @return the push item
+	 */
+	public PushItem setUrl(String url)
+	{
+		this.url = url;
+		return this;
+	}
+
+	/**
+	 * Gets the headers to be added to the push response
+	 *
+	 * @return the headers to be added to the push response
+	 */
+	public Map<String, PushItemHeaderValue> getHeaders()
+	{
+		return headers;
+	}
+
+	/**
+	 * Sets the headers to be added to the push response
+	 *
+	 * @param headers
+	 *            the headers to be added to the push response
+	 * @return the push item
+	 */
+	public PushItem setHeaders(Map<String, PushItemHeaderValue> headers)
+	{
+		this.headers = headers;
+		return this;
+	}
 }

http://git-wip-us.apache.org/repos/asf/wicket/blob/50edbc4c/wicket-experimental/wicket-http2/wicket-http2-core/src/main/java/org/apache/wicket/http2/markup/head/PushItemHeaderValue.java
----------------------------------------------------------------------
diff --git a/wicket-experimental/wicket-http2/wicket-http2-core/src/main/java/org/apache/wicket/http2/markup/head/PushItemHeaderValue.java b/wicket-experimental/wicket-http2/wicket-http2-core/src/main/java/org/apache/wicket/http2/markup/head/PushItemHeaderValue.java
new file mode 100644
index 0000000..2c3c72c
--- /dev/null
+++ b/wicket-experimental/wicket-http2/wicket-http2-core/src/main/java/org/apache/wicket/http2/markup/head/PushItemHeaderValue.java
@@ -0,0 +1,101 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.wicket.http2.markup.head;
+
+/**
+ * A push header to be applied when the resource is pushed
+ *
+ * @author Tobias Soloschenko
+ *
+ */
+public class PushItemHeaderValue
+{
+	/**
+	 * The header operation to be used
+	 *
+	 * @author Tobias Soloschenko
+	 *
+	 */
+	public enum HeaderOperation {
+		/**
+		 * Header value is going to be set
+		 */
+		SET,
+		/**
+		 * Header value is going to be add
+		 */
+		ADD
+	}
+
+	private String value;
+
+	private HeaderOperation operation;
+
+	/**
+	 * @param value
+	 *            the value of the header
+	 * @param operation
+	 *            the header operation
+	 */
+	public PushItemHeaderValue(String value, HeaderOperation operation)
+	{
+		this.value = value;
+		this.operation = operation;
+	}
+
+	/**
+	 * The value of the header
+	 *
+	 * @return the value of the header
+	 */
+	public String getValue()
+	{
+		return value;
+	}
+
+	/**
+	 * Sets the value of the header
+	 *
+	 * @param value
+	 *            the value of the header
+	 */
+	public void setValue(String value)
+	{
+		this.value = value;
+	}
+
+	/**
+	 * Gets the header operation
+	 *
+	 * @return the header operation
+	 */
+	public HeaderOperation getOperation()
+	{
+		return operation;
+	}
+
+	/**
+	 * Sets the header operation
+	 *
+	 * @param operation
+	 *            the header operation
+	 */
+	public void setOperation(HeaderOperation operation)
+	{
+		this.operation = operation;
+	}
+}

http://git-wip-us.apache.org/repos/asf/wicket/blob/50edbc4c/wicket-experimental/wicket-http2/wicket-http2-jetty/src/main/java/org/apache/wicket/http2/markup/head/Jetty9PushBuilder.java
----------------------------------------------------------------------
diff --git a/wicket-experimental/wicket-http2/wicket-http2-jetty/src/main/java/org/apache/wicket/http2/markup/head/Jetty9PushBuilder.java b/wicket-experimental/wicket-http2/wicket-http2-jetty/src/main/java/org/apache/wicket/http2/markup/head/Jetty9PushBuilder.java
index be7f44f..8b632dc 100644
--- a/wicket-experimental/wicket-http2/wicket-http2-jetty/src/main/java/org/apache/wicket/http2/markup/head/Jetty9PushBuilder.java
+++ b/wicket-experimental/wicket-http2/wicket-http2-jetty/src/main/java/org/apache/wicket/http2/markup/head/Jetty9PushBuilder.java
@@ -18,6 +18,7 @@ package org.apache.wicket.http2.markup.head;
 
 import javax.servlet.http.HttpServletRequest;
 
+import org.apache.wicket.http2.markup.head.PushItemHeaderValue.HeaderOperation;
 import org.apache.wicket.request.Request;
 import org.apache.wicket.request.cycle.RequestCycle;
 import org.slf4j.Logger;
@@ -33,16 +34,26 @@ public class Jetty9PushBuilder implements PushBuilder
 	private static final Logger LOG = LoggerFactory.getLogger(Jetty9PushBuilder.class);
 
 	@Override
-	public void push(HttpServletRequest httpServletRequest, String... paths)
+	public void push(HttpServletRequest httpServletRequest, PushItem... pushItems)
 	{
 		Request request = RequestCycle.get().getRequest();
 		HttpServletRequest httpRequest = (HttpServletRequest) request.getContainerRequest();
-		org.eclipse.jetty.server.PushBuilder pushBuilder = org.eclipse.jetty.server.Request.getBaseRequest(httpRequest).getPushBuilder();
+		final org.eclipse.jetty.server.PushBuilder pushBuilder = org.eclipse.jetty.server.Request.getBaseRequest(httpRequest).getPushBuilder();
 		if (pushBuilder != null)
 		{
-			for (String path : paths)
+			for (PushItem pushItem : pushItems)
 			{
-				pushBuilder.path(path).push();
+				pushBuilder.path(pushItem.getUrl());
+				pushItem.getHeaders().entrySet().stream().forEach(pushHeader -> {
+					String key = pushHeader.getKey();
+					PushItemHeaderValue value = pushHeader.getValue();
+					if(value.getOperation() == HeaderOperation.ADD){
+						pushBuilder.addHeader(key, value.getValue());
+					}else{
+						pushBuilder.setHeader(key, value.getValue());
+					}
+				});
+				pushBuilder.push();
 			}
 		}
 		else

http://git-wip-us.apache.org/repos/asf/wicket/blob/50edbc4c/wicket-experimental/wicket-http2/wicket-http2-tomcat/pom.xml
----------------------------------------------------------------------
diff --git a/wicket-experimental/wicket-http2/wicket-http2-tomcat/pom.xml b/wicket-experimental/wicket-http2/wicket-http2-tomcat/pom.xml
index ad6dafd..0796f9e 100644
--- a/wicket-experimental/wicket-http2/wicket-http2-tomcat/pom.xml
+++ b/wicket-experimental/wicket-http2/wicket-http2-tomcat/pom.xml
@@ -40,7 +40,7 @@
 		<dependency>
 			<groupId>org.apache.tomcat</groupId>
 			<artifactId>tomcat-catalina</artifactId>
-			<version>8.5.15</version>
+			<version>8.5.19</version>
 			<scope>provided</scope>
 		</dependency>
 	</dependencies>

http://git-wip-us.apache.org/repos/asf/wicket/blob/50edbc4c/wicket-experimental/wicket-http2/wicket-http2-tomcat/src/main/java/org/apache/wicket/http2/markup/head/Tomcat85PushBuilder.java
----------------------------------------------------------------------
diff --git a/wicket-experimental/wicket-http2/wicket-http2-tomcat/src/main/java/org/apache/wicket/http2/markup/head/Tomcat85PushBuilder.java b/wicket-experimental/wicket-http2/wicket-http2-tomcat/src/main/java/org/apache/wicket/http2/markup/head/Tomcat85PushBuilder.java
index b436e68..1aac741 100644
--- a/wicket-experimental/wicket-http2/wicket-http2-tomcat/src/main/java/org/apache/wicket/http2/markup/head/Tomcat85PushBuilder.java
+++ b/wicket-experimental/wicket-http2/wicket-http2-tomcat/src/main/java/org/apache/wicket/http2/markup/head/Tomcat85PushBuilder.java
@@ -18,6 +18,7 @@ package org.apache.wicket.http2.markup.head;
 
 import javax.servlet.http.HttpServletRequest;
 
+import org.apache.wicket.http2.markup.head.PushItemHeaderValue.HeaderOperation;
 import org.apache.wicket.request.Request;
 import org.apache.wicket.request.cycle.RequestCycle;
 import org.slf4j.Logger;
@@ -31,7 +32,7 @@ public class Tomcat85PushBuilder implements PushBuilder
 	private static final Logger LOG = LoggerFactory.getLogger(Tomcat85PushBuilder.class);
 
 	@Override
-	public void push(HttpServletRequest httpServletRequest, String... paths)
+	public void push(HttpServletRequest httpServletRequest, PushItem... pushItems)
 	{
 		Request request = RequestCycle.get().getRequest();
 		HttpServletRequest httpRequest = (HttpServletRequest) request.getContainerRequest();
@@ -39,9 +40,19 @@ public class Tomcat85PushBuilder implements PushBuilder
 		org.apache.catalina.servlet4preview.http.PushBuilder pushBuilder = tomcatRequest.newPushBuilder();
 		if (pushBuilder != null)
 		{
-			for (String path : paths)
+			for (PushItem pushItem : pushItems)
 			{
-				pushBuilder.path(path).push();
+				pushBuilder.path(pushItem.getUrl());
+				pushItem.getHeaders().entrySet().stream().forEach(pushHeader -> {
+					String key = pushHeader.getKey();
+					PushItemHeaderValue value = pushHeader.getValue();
+					if(value.getOperation() == HeaderOperation.ADD){
+						pushBuilder.addHeader(key, value.getValue());
+					}else{
+						pushBuilder.setHeader(key, value.getValue());
+					}
+				});
+				pushBuilder.push();
 			}
 		}
 		else

http://git-wip-us.apache.org/repos/asf/wicket/blob/50edbc4c/wicket-experimental/wicket-http2/wicket-http2-undertow/src/main/java/org/apache/wicket/http2/markup/head/UndertowPushBuilder.java
----------------------------------------------------------------------
diff --git a/wicket-experimental/wicket-http2/wicket-http2-undertow/src/main/java/org/apache/wicket/http2/markup/head/UndertowPushBuilder.java b/wicket-experimental/wicket-http2/wicket-http2-undertow/src/main/java/org/apache/wicket/http2/markup/head/UndertowPushBuilder.java
index c14aecd..7833870 100644
--- a/wicket-experimental/wicket-http2/wicket-http2-undertow/src/main/java/org/apache/wicket/http2/markup/head/UndertowPushBuilder.java
+++ b/wicket-experimental/wicket-http2/wicket-http2-undertow/src/main/java/org/apache/wicket/http2/markup/head/UndertowPushBuilder.java
@@ -18,6 +18,7 @@ package org.apache.wicket.http2.markup.head;
 
 import javax.servlet.http.HttpServletRequest;
 
+import org.apache.wicket.http2.markup.head.PushItemHeaderValue.HeaderOperation;
 import org.apache.wicket.request.Request;
 import org.apache.wicket.request.cycle.RequestCycle;
 import org.slf4j.Logger;
@@ -33,7 +34,7 @@ public class UndertowPushBuilder implements PushBuilder
 	private static final Logger LOG = LoggerFactory.getLogger(UndertowPushBuilder.class);
 
 	@Override
-	public void push(HttpServletRequest httpServletRequest, String... paths)
+	public void push(HttpServletRequest httpServletRequest, PushItem... pushItems)
 	{
 		Request request = RequestCycle.get().getRequest();
 		HttpServletRequest httpRequest = (HttpServletRequest) request.getContainerRequest();
@@ -42,9 +43,19 @@ public class UndertowPushBuilder implements PushBuilder
 		io.undertow.servlet.spec.PushBuilderImpl pushBuilder = (io.undertow.servlet.spec.PushBuilderImpl)undertowRequest.getPushBuilder();
 		if (pushBuilder != null)
 		{
-			for (String path : paths)
+			for (PushItem pushItem : pushItems)
 			{
-				pushBuilder.path(path).push();
+				pushBuilder.path(pushItem.getUrl());
+				pushItem.getHeaders().entrySet().stream().forEach(pushHeader -> {
+					String key = pushHeader.getKey();
+					PushItemHeaderValue value = pushHeader.getValue();
+					if(value.getOperation() == HeaderOperation.ADD){
+						pushBuilder.addHeader(key, value.getValue());
+					}else{
+						pushBuilder.setHeader(key, value.getValue());
+					}
+				});
+				pushBuilder.push();
 			}
 		}
 		else

http://git-wip-us.apache.org/repos/asf/wicket/blob/50edbc4c/wicket-user-guide/src/main/asciidoc/http2push/http2push_1.adoc
----------------------------------------------------------------------
diff --git a/wicket-user-guide/src/main/asciidoc/http2push/http2push_1.adoc b/wicket-user-guide/src/main/asciidoc/http2push/http2push_1.adoc
index ebce17b..138ec5b 100644
--- a/wicket-user-guide/src/main/asciidoc/http2push/http2push_1.adoc
+++ b/wicket-user-guide/src/main/asciidoc/http2push/http2push_1.adoc
@@ -34,9 +34,9 @@ public class HTTP2Page extends WebPage
 {
 	private static final long serialVersionUID = 1L;
 
-	private Response webPageResponse;
+	private transient Response webPageResponse;
 
-	private Request webPageRequest;
+	private transient Request webPageRequest;
 
 	public HTTP2Page()
 	{