Skip to content
This repository has been archived by the owner on Jul 5, 2020. It is now read-only.

Commit

Permalink
Merge pull request #21 from 55minutes/cdn
Browse files Browse the repository at this point in the history
Add SimpleCDN class, tests, refactor, and bump version to 3.2
  • Loading branch information
mattbrictson committed Jan 3, 2012
2 parents b7b877b + 40c7229 commit 6dd4b13
Show file tree
Hide file tree
Showing 22 changed files with 389 additions and 45 deletions.
38 changes: 19 additions & 19 deletions README.md
Expand Up @@ -25,7 +25,7 @@ mvn archetype:generate -U \
-DarchetypeGroupId=com.55minutes \
-DarchetypeArtifactId=fiftyfive-wicket-archetype \
-DarchetypeRepository=http://opensource.55minutes.com/maven-snapshots \
-DarchetypeVersion=3.1-SNAPSHOT
-DarchetypeVersion=3.2-SNAPSHOT
```

This creates a project directory with all the Java, Maven POM and web.xml scaffolding you need for a
Expand Down Expand Up @@ -225,7 +225,7 @@ dependency:
<dependency>
<groupId>com.55minutes</groupId>
<artifactId>fiftyfive-wicket-core</artifactId>
<version>3.1-SNAPSHOT</version>
<version>3.2-SNAPSHOT</version>
</dependency>
```

Expand Down Expand Up @@ -259,29 +259,29 @@ following snippet:

[jetty]:http://jetty.codehaus.org/jetty/
[shiro]:http://shiro.apache.org/
[ffshiro]:http://opensource.55minutes.com/apidocs/fiftyfive-wicket-all/3.1-SNAPSHOT/index.html?fiftyfive/wicket/shiro/ShiroWicketPlugin.html
[ffshiro]:http://opensource.55minutes.com/apidocs/fiftyfive-wicket-all/3.2-SNAPSHOT/index.html?fiftyfive/wicket/shiro/ShiroWicketPlugin.html
[admin]:http://localhost:8080/admin
[shirotests]:http://opensource.55minutes.com/apidocs/fiftyfive-wicket-all/3.1-SNAPSHOT/index.html?fiftyfive/wicket/shiro/test/AbstractShiroJUnit4Tests.html
[shirotests]:http://opensource.55minutes.com/apidocs/fiftyfive-wicket-all/3.2-SNAPSHOT/index.html?fiftyfive/wicket/shiro/test/AbstractShiroJUnit4Tests.html
[pplace]:http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/beans.html#beans-factory-placeholderconfigurer
[spring]:http://www.springsource.org/about
[ffspring]:http://opensource.55minutes.com/apidocs/fiftyfive-wicket-all/3.1-SNAPSHOT/index.html?fiftyfive/wicket/spring/FoundationSpringApplication.html
[ffspring]:http://opensource.55minutes.com/apidocs/fiftyfive-wicket-all/3.2-SNAPSHOT/index.html?fiftyfive/wicket/spring/FoundationSpringApplication.html
[mockito]:http://code.google.com/p/mockito/
[wicketspring]:https://cwiki.apache.org/confluence/display/WICKET/Spring
[sass]:http://sass-lang.com/
[compass]:http://compass-style.org/
[cssf]:https://github.com/55minutes/css3-foundation
[shortcuts]:http://opensource.55minutes.com/apidocs/fiftyfive-wicket-all/3.1-SNAPSHOT/index.html?fiftyfive/wicket/util/Shortcuts.html
[ffwcore]:http://opensource.55minutes.com/apidocs/fiftyfive-wicket-core/3.1-SNAPSHOT/
[prompt]:http://opensource.55minutes.com/apidocs/fiftyfive-wicket-all/3.1-SNAPSHOT/index.html?fiftyfive/wicket/feedback/Prompt.html
[countl]:http://opensource.55minutes.com/apidocs/fiftyfive-wicket-all/3.1-SNAPSHOT/index.html?fiftyfive/wicket/basic/CountLabel.html
[trunc]:http://opensource.55minutes.com/apidocs/fiftyfive-wicket-all/3.1-SNAPSHOT/index.html?fiftyfive/wicket/basic/TruncatedLabel.html
[choices]:http://opensource.55minutes.com/apidocs/fiftyfive-wicket-all/3.1-SNAPSHOT/index.html?fiftyfive/wicket/form/RadioChoicesListView.html
[ffwtest]:http://opensource.55minutes.com/apidocs/fiftyfive-wicket-all/3.1-SNAPSHOT/index.html?fiftyfive/wicket/test/package-summary.html
[avalid]:http://opensource.55minutes.com/apidocs/fiftyfive-wicket-all/3.1-SNAPSHOT/fiftyfive/wicket/test/WicketTestUtils.html#assertValidMarkup(org.apache.wicket.util.tester.WicketTester)
[startc]:http://opensource.55minutes.com/apidocs/fiftyfive-wicket-all/3.1-SNAPSHOT/fiftyfive/wicket/test/WicketTestUtils.html#startComponentWithHtml(org.apache.wicket.util.tester.WicketTester,%20org.apache.wicket.Component,%20java.lang.String)
[axpath]:http://opensource.55minutes.com/apidocs/fiftyfive-wicket-all/3.1-SNAPSHOT/fiftyfive/wicket/test/WicketTestUtils.html#assertXPath(org.apache.wicket.util.tester.WicketTester,%20java.lang.String)
[ffwjs]:http://opensource.55minutes.com/apidocs/fiftyfive-wicket-all/3.1-SNAPSHOT/index.html?fiftyfive/wicket/js/package-summary.html
[dready]:http://opensource.55minutes.com/apidocs/fiftyfive-wicket-all/3.1-SNAPSHOT/index.html?fiftyfive/wicket/js/DomReadyTemplate.html
[jsdep]:http://opensource.55minutes.com/apidocs/fiftyfive-wicket-all/3.1-SNAPSHOT/index.html?fiftyfive/wicket/js/JavaScriptDependency.html
[jsbuild]:http://opensource.55minutes.com/apidocs/fiftyfive-wicket-all/3.1-SNAPSHOT/index.html?fiftyfive/wicket/js/MergedJavaScriptBuilder.html
[shortcuts]:http://opensource.55minutes.com/apidocs/fiftyfive-wicket-all/3.2-SNAPSHOT/index.html?fiftyfive/wicket/util/Shortcuts.html
[ffwcore]:http://opensource.55minutes.com/apidocs/fiftyfive-wicket-core/3.2-SNAPSHOT/
[prompt]:http://opensource.55minutes.com/apidocs/fiftyfive-wicket-all/3.2-SNAPSHOT/index.html?fiftyfive/wicket/feedback/Prompt.html
[countl]:http://opensource.55minutes.com/apidocs/fiftyfive-wicket-all/3.2-SNAPSHOT/index.html?fiftyfive/wicket/basic/CountLabel.html
[trunc]:http://opensource.55minutes.com/apidocs/fiftyfive-wicket-all/3.2-SNAPSHOT/index.html?fiftyfive/wicket/basic/TruncatedLabel.html
[choices]:http://opensource.55minutes.com/apidocs/fiftyfive-wicket-all/3.2-SNAPSHOT/index.html?fiftyfive/wicket/form/RadioChoicesListView.html
[ffwtest]:http://opensource.55minutes.com/apidocs/fiftyfive-wicket-all/3.2-SNAPSHOT/index.html?fiftyfive/wicket/test/package-summary.html
[avalid]:http://opensource.55minutes.com/apidocs/fiftyfive-wicket-all/3.2-SNAPSHOT/fiftyfive/wicket/test/WicketTestUtils.html#assertValidMarkup(org.apache.wicket.util.tester.WicketTester)
[startc]:http://opensource.55minutes.com/apidocs/fiftyfive-wicket-all/3.2-SNAPSHOT/fiftyfive/wicket/test/WicketTestUtils.html#startComponentWithHtml(org.apache.wicket.util.tester.WicketTester,%20org.apache.wicket.Component,%20java.lang.String)
[axpath]:http://opensource.55minutes.com/apidocs/fiftyfive-wicket-all/3.2-SNAPSHOT/fiftyfive/wicket/test/WicketTestUtils.html#assertXPath(org.apache.wicket.util.tester.WicketTester,%20java.lang.String)
[ffwjs]:http://opensource.55minutes.com/apidocs/fiftyfive-wicket-all/3.2-SNAPSHOT/index.html?fiftyfive/wicket/js/package-summary.html
[dready]:http://opensource.55minutes.com/apidocs/fiftyfive-wicket-all/3.2-SNAPSHOT/index.html?fiftyfive/wicket/js/DomReadyTemplate.html
[jsdep]:http://opensource.55minutes.com/apidocs/fiftyfive-wicket-all/3.2-SNAPSHOT/index.html?fiftyfive/wicket/js/JavaScriptDependency.html
[jsbuild]:http://opensource.55minutes.com/apidocs/fiftyfive-wicket-all/3.2-SNAPSHOT/index.html?fiftyfive/wicket/js/MergedJavaScriptBuilder.html
[readme]:https://github.com/55minutes/fiftyfive-wicket/blob/master/fiftyfive-wicket-archetype/src/main/resources/archetype-resources/README.md
2 changes: 1 addition & 1 deletion fiftyfive-wicket-all/pom.xml
Expand Up @@ -26,7 +26,7 @@
<parent>
<groupId>com.55minutes</groupId>
<artifactId>fiftyfive-wicket-parent</artifactId>
<version>3.1-SNAPSHOT</version>
<version>3.2-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<groupId>com.55minutes</groupId>
Expand Down
2 changes: 1 addition & 1 deletion fiftyfive-wicket-archetype/ci-test.sh
Expand Up @@ -10,7 +10,7 @@ mvn archetype:generate -B -U \
-DarchetypeGroupId=com.55minutes \
-DarchetypeArtifactId=fiftyfive-wicket-archetype \
-DarchetypeRepository=http://opensource.55minutes.com/maven-snapshots \
-DarchetypeVersion=3.1-SNAPSHOT \
-DarchetypeVersion=3.2-SNAPSHOT \
-DgroupId=com.55minutes \
-DartifactId=test-project \
-Dversion=999 \
Expand Down
2 changes: 1 addition & 1 deletion fiftyfive-wicket-archetype/pom.xml
Expand Up @@ -24,7 +24,7 @@
<parent>
<groupId>com.55minutes</groupId>
<artifactId>fiftyfive-wicket-parent</artifactId>
<version>3.1-SNAPSHOT</version>
<version>3.2-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>

Expand Down
Expand Up @@ -32,7 +32,7 @@
<!-- ==================================================================== -->

<properties>
<fiftyfive.version>3.1-SNAPSHOT</fiftyfive.version>
<fiftyfive.version>3.2-SNAPSHOT</fiftyfive.version>
<jetty.version>6.1.26</jetty.version>
<slf4j.version>1.6.2</slf4j.version>
<spring.version>3.1.0.RELEASE</spring.version>
Expand Down
Expand Up @@ -62,7 +62,7 @@ <h2>Project structure</h2>
<h1>Javadoc</h1>
<ul>
<li><a href="http://wicket.apache.org/apidocs/1.5/">Wicket</a></li>
<li><a href="http://opensource.55minutes.com/apidocs/fiftyfive-wicket-all/3.1-SNAPSHOT/">fiftyfive-wicket</a></li>
<li><a href="http://opensource.55minutes.com/apidocs/fiftyfive-wicket-all/3.2-SNAPSHOT/">fiftyfive-wicket</a></li>
<li><a href="http://opensource.55minutes.com/apidocs/fiftyfive-util/1.0-SNAPSHOT/">fiftyfive-util</a></li>
<li><a href="http://download.oracle.com/javase/6/docs/api/">JavaSE</a></li>
<li><a href="http://download.oracle.com/docs/cd/E17802_01/products/products/servlet/2.5/docs/servlet-2_5-mr2/">Servlet</a></li>
Expand Down
2 changes: 1 addition & 1 deletion fiftyfive-wicket-core/pom.xml
Expand Up @@ -28,7 +28,7 @@
<parent>
<groupId>com.55minutes</groupId>
<artifactId>fiftyfive-wicket-parent</artifactId>
<version>3.1-SNAPSHOT</version>
<version>3.2-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<groupId>com.55minutes</groupId>
Expand Down
@@ -0,0 +1,152 @@
/**
* Copyright 2012 55 Minutes (http://www.55minutes.com)
*
* Licensed 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 fiftyfive.wicket.resource;

import org.apache.wicket.protocol.http.WebApplication;
import org.apache.wicket.request.IRequestHandler;
import org.apache.wicket.request.IRequestMapper;
import org.apache.wicket.request.Request;
import org.apache.wicket.request.Url;
import org.apache.wicket.request.handler.resource.ResourceReferenceRequestHandler;
import org.apache.wicket.util.string.Strings;

/**
* Enables a Wicket application to have its static resources proxied by a CDN, for example
* by Amazon Cloudfront. This works by intercepting Wicket's default behavior for rendering
* URLs of resource references, and then rewriting those URLs by prepending a CDN hostname
* (or any arbitrary URL fragment). The web browser will therefore make requests to the
* CDN host instead of the Wicket app.
* <p>
* Here's an example. Normally a CSS resource reference is rendered by Wicket like this:
* <pre class="example">
* /wicket/resource/com.mycompany.WicketApplication/test.css</pre>
* <p>
* With {@code SimpleCDN} installed, that resource reference URL is transformed into this:
* <pre class="example">
* //age39p8hg23.cloudfront.net/wicket/resource/com.mycompany.WicketApplication/test.css</pre>
* <p>
* <b>Please note: {@code SimpleCDN} will not rewrite resource reference URLs that
* include query string parameters.</b> Our reasoning is that parameterized URLs usually
* indicate that the resource is dynamic, and therefore not appropriate for serving via
* CDN. Furthermore it should be noted that Amazon CloudFront will refuse to proxy
* URLs that contain query string parameters (it strips the parameters off).
* <p>
* When configuring the CDN host, the easiest setup is a reverse-proxy. For example, with
* Amazon CloudFront, you would specify your Wicket app as the <em>custom origin</em>, and specify
* the CloudFront host when constructing this SimpleCDN. It's that easy.
* <pre class="example">
* public class MyApplication extends WebApplication
* {
* &#064;Override
* protected void init()
* {
* super.init();
* // Enable CDN when in deployment mode
* if(usesDeploymentConfig())
* {
* new SimpleCDN("//age39p8hg23.cloudfront.net").install(this);
* }
* }
* }</pre>
* <p>
* Notice in this example that we've used "//" instead of "http://" for the CDN URL.
* This trick ensures that "http" or "https" will be automatically selected by the
* browser based on the enclosing web page.
* <p>
* <em>For those familiar with Ruby on Rails, {@code SimpleCDN} is inspired by the Rails
* {@code action_controller.asset_host} configuration setting.</em>
*
* @since 3.2
*/
public class SimpleCDN implements IRequestMapper
{
private String baseUrl;
private IRequestMapper delegate;
private boolean delegated = false;

/**
* Construct a {@code SimpleCDN} that will rewrite resource reference URLs by prepending
* the given {@code baseUrl}.
*
* @param baseUrl For example, "//age39p8hg23.cloudfront.net"
*/
public SimpleCDN(String baseUrl)
{
this.baseUrl = baseUrl;
}

/**
* Install this {@code SimpleCDN} into the given application. The {@code SimpleCDN} instance
* will not have any effect unless it is installed.
*/
public void install(WebApplication app)
{
this.delegate = app.getRootRequestMapperAsCompound();
app.mount(this);
}

/**
* If the {@code requestHandler} is a {@link ResourceReferenceRequestHandler}, delegate to
* Wicket's default mapper for creating an appropriate URL, and then prepend the CDN
* {@code baseUrl} that was provided to the {@code SimpleCDN} constructor.
*
* @return a rewritten Url to the resource, or {@code null} if {@code requestHandler} is
* not for a resource reference
*/
public Url mapHandler(IRequestHandler requestHandler)
{
// CDN doesn't apply to non-resources
if(!(requestHandler instanceof ResourceReferenceRequestHandler)) return null;

// Prevent infinite recursion in case this SimpleCDN is also contained within the delegate
if(this.delegated) return null;

Url url = null;
try
{
this.delegated = true;
url = this.delegate.mapHandler(requestHandler);
if(url != null && url.getQueryParameters().isEmpty())
{
url = Url.parse(Strings.join("/", this.baseUrl, url.toString()));
}
}
finally
{
this.delegated = false;
}
return url;
}

/**
* Always return {@code null}, since {@code SimpleCDN} does not play any part in handling requests
* (they will be handled by Wicket's default mechanism).
*/
public IRequestHandler mapRequest(Request request)
{
return null;
}

/**
* Always return {@code 0}, since {@code SimpleCDN} does not play any part in handling requests
* (they will be handled by Wicket's default mechanism).
*/
public int getCompatibilityScore(Request request)
{
return 0;
}
}
Expand Up @@ -23,8 +23,6 @@

import org.apache.wicket.markup.html.WebPage;
import org.apache.wicket.protocol.http.WebApplication;
import org.apache.wicket.protocol.http.mock.MockHttpServletRequest;
import org.apache.wicket.protocol.http.mock.MockHttpSession;
import org.apache.wicket.request.resource.caching.NoOpResourceCachingStrategy;
import org.apache.wicket.util.io.IOUtils;
import org.apache.wicket.util.tester.DummyHomePage;
Expand Down Expand Up @@ -67,18 +65,7 @@ protected void assertDownloaded(WicketTester tester, String uri, String... files
IOUtils.closeQuietly(is);
}
}

MockHttpSession session = new MockHttpSession(tester.getApplication().getServletContext());
MockHttpServletRequest request = new MockHttpServletRequest(
tester.getApplication(),
session,
tester.getApplication().getServletContext()
);
request.setURL(uri);
tester.processRequest(request);

byte[] actual = tester.getLastResponse().getBinaryContent();
assertArrayEquals(expected.toByteArray(), actual);
WicketTestUtils.assertDownloadEquals(tester, uri, expected.toByteArray());
}

protected abstract void onAppInit(WebApplication app);
Expand Down

0 comments on commit 6dd4b13

Please sign in to comment.