Repository: wicket Updated Branches: refs/heads/WICKET-6194 [created] eb730f297
WICKET-6194 Project: http://git-wip-us.apache.org/repos/asf/wicket/repo Commit: http://git-wip-us.apache.org/repos/asf/wicket/commit/eb730f29 Tree: http://git-wip-us.apache.org/repos/asf/wicket/tree/eb730f29 Diff: http://git-wip-us.apache.org/repos/asf/wicket/diff/eb730f29 Branch: refs/heads/WICKET-6194 Commit: eb730f2979dab6c937e87cefbbe84167cc5546e1 Parents: a6673f1 Author: Tobias Soloschenko <[email protected]> Authored: Sat Jul 2 01:25:22 2016 +0200 Committer: Tobias Soloschenko <[email protected]> Committed: Sat Jul 2 01:25:22 2016 +0200 ---------------------------------------------------------------------- wicket-experimental/wicket-http2/pom.xml | 37 ++++ .../wicket-http2/wicket-http2-core/pom.xml | 45 +++++ .../http2/markup/head/PushHeaderItem.java | 190 +++++++++++++++++++ .../wicket/http2/markup/head/PushItem.java | 95 ++++++++++ .../wicket-http2/wicket-http2-jetty/pom.xml | 38 ++++ 5 files changed, 405 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/wicket/blob/eb730f29/wicket-experimental/wicket-http2/pom.xml ---------------------------------------------------------------------- diff --git a/wicket-experimental/wicket-http2/pom.xml b/wicket-experimental/wicket-http2/pom.xml new file mode 100644 index 0000000..065b940 --- /dev/null +++ b/wicket-experimental/wicket-http2/pom.xml @@ -0,0 +1,37 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + 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. +--> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>org.apache.wicket.experimental.wicket8</groupId> + <artifactId>wicket-experimental</artifactId> + <version>8.0.0-SNAPSHOT</version> + <relativePath>../pom.xml</relativePath> + </parent> + <artifactId>wicket-http2</artifactId> + <version>0.1-SNAPSHOT</version> + <packaging>pom</packaging> + <name>Wicket Http/2</name> + <description> + Wicketâs implementation to use the PushBuilder API + to serve resource via http/2 with less requests + </description> + <modules> + <module>wicket-http2-core</module> + </modules> +</project> http://git-wip-us.apache.org/repos/asf/wicket/blob/eb730f29/wicket-experimental/wicket-http2/wicket-http2-core/pom.xml ---------------------------------------------------------------------- diff --git a/wicket-experimental/wicket-http2/wicket-http2-core/pom.xml b/wicket-experimental/wicket-http2/wicket-http2-core/pom.xml new file mode 100644 index 0000000..d5e6d4b --- /dev/null +++ b/wicket-experimental/wicket-http2/wicket-http2-core/pom.xml @@ -0,0 +1,45 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + 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. +--> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>org.apache.wicket.experimental.wicket8</groupId> + <artifactId>wicket-http2</artifactId> + <version>0.1-SNAPSHOT</version> + <relativePath>../pom.xml</relativePath> + </parent> + <artifactId>wicket-http2-core</artifactId> + <packaging>jar</packaging> + <name>Wicket Http/2 Core</name> + <description> + Wicketâs implementation to use the PushBuilder API + to serve resource via http/2 with less requests. This + is the core implementation which provides the header item + that uses the API. + </description> + <dependencies> + <dependency> + <groupId>org.apache.wicket</groupId> + <artifactId>wicket-core</artifactId> + </dependency> + <dependency> + <groupId>org.apache.wicket</groupId> + <artifactId>wicket-request</artifactId> + </dependency> + </dependencies> +</project> http://git-wip-us.apache.org/repos/asf/wicket/blob/eb730f29/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 new file mode 100644 index 0000000..a56b8bd --- /dev/null +++ b/wicket-experimental/wicket-http2/wicket-http2-core/src/main/java/org/apache/wicket/http2/markup/head/PushHeaderItem.java @@ -0,0 +1,190 @@ +package org.apache.wicket.http2.markup.head; + +import java.util.List; +import java.util.Set; +import java.util.TreeSet; + +import javax.servlet.http.HttpServletRequest; + +import org.apache.wicket.Page; +import org.apache.wicket.WicketRuntimeException; +import org.apache.wicket.markup.head.HeaderItem; +import org.apache.wicket.request.IRequestHandler; +import org.apache.wicket.request.Request; +import org.apache.wicket.request.Response; +import org.apache.wicket.request.Url; +import org.apache.wicket.request.cycle.RequestCycle; +import org.apache.wicket.request.mapper.parameter.PageParameters; +import org.apache.wicket.request.mapper.parameter.PageParametersEncoder; +import org.apache.wicket.request.resource.ResourceReference; +import org.apache.wicket.util.collections.ConcurrentHashSet; + +/** + * A push header item to be used in the http/2 context and to reduce the latency of the web + * application + * + * @author Tobias Soloschenko + * + */ +public class PushHeaderItem extends HeaderItem +{ + private static final long serialVersionUID = 1L; + + /** + * The http2 protocol string + */ + public static final String HTTP2_PROTOCOL = "http/2"; + + /** + * The token suffix to be used in this header item + */ + private static final String TOKEN_SUFFIX = HTTP2_PROTOCOL + "_pushed"; + + /** + * The URLs of resources to be pushed to the client + */ + private Set<String> urls = new ConcurrentHashSet<String>(new TreeSet<String>()); + + /** + * Uses the URLs that has already been pushed to the client to ensure not to push them again + */ + @Override + public Iterable<?> getRenderTokens() + { + Set<String> tokens = new TreeSet<String>(); + for (String url : urls) + { + tokens.add(url + TOKEN_SUFFIX); + } + return tokens; + } + + /** + * Pushes the previously created URLs to the client + */ + @Override + public void render(Response response) + { + HttpServletRequest request = getContainerRequest(RequestCycle.get().getRequest()); + // Check if the protocol is http/2 or http/2.0 to only push the resources in this case + if (isHttp2(request)) + { + for (String url : urls) + { + // TODO Jetty has to switch to the javax.servlet-api classes and handle + // SETTINGS_ENABLE_PUSH settings frame value and implement the default API against + // it. + org.eclipse.jetty.server.Request.getBaseRequest(request).getPushBuilder() + .path(url.toString()).push(); + } + } + } + + /** + * Creates a URL and pushes the resource to the client - this is only supported if http2 is + * enabled + * + * @param pushItems + * a list of items to be pushed to the client + * @return the current push header item + */ + @SuppressWarnings("unchecked") + public PushHeaderItem push(List<PushItem> pushItems) + { + RequestCycle requestCycle = RequestCycle.get(); + if (isHttp2(getContainerRequest(requestCycle.getRequest()))) + for (PushItem pushItem : pushItems) + { + Object object = pushItem.getObject(); + PageParameters parameters = pushItem.getPageParameters(); + + if (object == null) + { + throw new WicketRuntimeException( + "Please provide an object to the items to be pushed, so that the url can be created for the given resource."); + } + + CharSequence url = null; + if (object instanceof ResourceReference) + { + url = requestCycle.urlFor((ResourceReference)object, parameters); + } + else if (object instanceof Class) + { + url = requestCycle.urlFor((Class<? extends Page>)object, parameters); + } + else if (object instanceof IRequestHandler) + { + url = requestCycle.urlFor((IRequestHandler)object); + } + else + { + Url encoded = new PageParametersEncoder().encodePageParameters(parameters); + String queryString = encoded.getQueryString(); + url = object.toString() + (queryString != null ? "?" + queryString : ""); + } + + if (url.toString().equals(".")) + { + url = "/"; + } + else if (url.toString().startsWith(".")) + { + url = url.toString().substring(1); + } + + urls.add(url.toString()); + } + return this; + } + + /** + * Gets the container request + * + * @param request + * the wicket request to get the container request from + * @return the container request + */ + public HttpServletRequest getContainerRequest(Request request) + { + + return checkHttpServletRequest(request); + } + + /** + * Checks if the given request is a http/2 request + * + * @param request + * the request to check if it is a http/2 request + * @return if the request is a http/2 request + */ + public boolean isHttp2(HttpServletRequest request) + { + // detects http/2 and http/2.0 + return request.getProtocol().toLowerCase().contains(HTTP2_PROTOCOL); + } + + /** + * Checks if the container request from the given request is instance of + * {@link HttpServletRequest} if not the API of the PushHeaderItem can't be used and a + * {@link WicketRuntimeException} is thrown. + * + * @param request + * the request to get the container request from. The container request is checked if it + * is instance of {@link HttpServletRequest} + * @return the container request get from the given request casted to {@link HttpServletRequest} + * @throw {@link WicketRuntimeException} if the container request is not a + * {@link HttpServletRequest} + */ + public HttpServletRequest checkHttpServletRequest(Request request) + { + Object assumedHttpServletRequest = request.getContainerRequest(); + if (!(assumedHttpServletRequest instanceof HttpServletRequest)) + { + throw new WicketRuntimeException( + "The request is not a HttpServletRequest - the usage of PushHeaderItem is not support in the current environment: " + + request.getClass().getName()); + } + return (HttpServletRequest)assumedHttpServletRequest; + } +} http://git-wip-us.apache.org/repos/asf/wicket/blob/eb730f29/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 new file mode 100644 index 0000000..402ecb4 --- /dev/null +++ b/wicket-experimental/wicket-http2/wicket-http2-core/src/main/java/org/apache/wicket/http2/markup/head/PushItem.java @@ -0,0 +1,95 @@ +package org.apache.wicket.http2.markup.head; + +import org.apache.wicket.Component; +import org.apache.wicket.request.mapper.parameter.PageParameters; + +/** + * The object to be pushed. See the urlFor methods of {@link Component} to know what can be used in + * addition to {@link String}. + * + * @author Tobias Soloschenko + */ +public class PushItem +{ + private Object object; + + private PageParameters pageParameters; + + /** + * Creates a push item + * + * @param object + * the object + * @param pageParameters + * the page parameters + */ + public PushItem(Object object, PageParameters pageParameters) + { + this.object = object; + this.pageParameters = pageParameters; + } + + /** + * Creates a push item + * + * @param object + * the object + */ + public PushItem(Object object) + { + this.object = object; + } + + /** + * Creates a push item + */ + public PushItem() + { + } + + /** + * Gets the object + * + * @return the object + */ + public Object getObject() + { + return object; + } + + /** + * Sets the object + * + * @param object + * the object + * @return the push item + */ + public PushItem setObject(Object object) + { + this.object = object; + return this; + } + + /** + * Gets the page parameters + * + * @return the page parameters + */ + public PageParameters getPageParameters() + { + return pageParameters; + } + + /** + * Sets the page parameters + * + * @param pageParameters + * the page parameters + * @return the push item + */ + public PushItem setPageParameters(PageParameters pageParameters) + { + this.pageParameters = pageParameters; + return this; + } +} http://git-wip-us.apache.org/repos/asf/wicket/blob/eb730f29/wicket-experimental/wicket-http2/wicket-http2-jetty/pom.xml ---------------------------------------------------------------------- diff --git a/wicket-experimental/wicket-http2/wicket-http2-jetty/pom.xml b/wicket-experimental/wicket-http2/wicket-http2-jetty/pom.xml new file mode 100644 index 0000000..8dfb469 --- /dev/null +++ b/wicket-experimental/wicket-http2/wicket-http2-jetty/pom.xml @@ -0,0 +1,38 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + 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. +--> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>org.apache.wicket.experimental.wicket7</groupId> + <artifactId>wicket-http2</artifactId> + <version>0.1-SNAPSHOT</version> + <relativePath>../pom.xml</relativePath> + </parent> + <artifactId>wicket-http2-core</artifactId> + <packaging>jar</packaging> + <name>Wicket Http/2 Jetty</name> + <description> + Wicketâs implementation to use the PushBuilder API + to serve resource via http/2 with less requests. This + is the jetty implementation to resolve the PushBuilder API and + provide the IInitializer. + </description> + <dependencies> + <!-- TODO --> + </dependencies> +</project>
