spdy: different push strategies per connection factory

This commit is contained in:
Thomas Becker 2012-07-06 13:36:57 +02:00
parent 723f53ec64
commit e7a52df43d
4 changed files with 71 additions and 50 deletions

View File

@ -11,11 +11,45 @@
<Set name="protocol">TLSv1</Set>
</New>
<!-- Uncomment to create a ReferrerPushStrategy that can be added to the Connectors -->
<!--
<New id="pushStrategy" class="org.eclipse.jetty.spdy.http.ReferrerPushStrategy">
<Arg type="List">
<Array type="String">
<Item>.*\.css</Item>
<Item>.*\.js</Item>
<Item>.*\.png</Item>
<Item>.*\.jpg</Item>
<Item>.*\.gif</Item>
</Array>
</Arg>
</New>
-->
<!--<Set class="org.eclipse.jetty.npn.NextProtoNego" name="debug" type="boolean">true</Set>-->
<Call name="addConnector">
<Arg>
<New class="org.eclipse.jetty.spdy.http.HTTPSPDYServerConnector">
<!-- uncomment to enable to apply ReferrerPushStrategy for spdy/3
if you want to support it in both spdy/2 and spdy/3, just replace the
value in the first map entry.
-->
<!--
<Arg name="pushStrategies">
<Map>
<Entry>
<Item type="short">2</Item>
<Item><New class="org.eclipse.jetty.spdy.http.PushStrategy$None" /></Item>
</Entry>
<Entry>
<Item type="short">3</Item>
<Item><Ref id="pushStrategy" /></Item>
</Entry>
</Map>
</Arg>
-->
<Set name="Port">8080</Set>
</New>
</Arg>
@ -26,6 +60,24 @@
<Arg>
<Ref id="sslContextFactory" />
</Arg>
<!-- uncomment to enable to apply ReferrerPushStrategy for spdy/3
if you want to support it in both spdy/2 and spdy/3, just replace the
value in the first map entry.
-->
<!--
<Arg name="pushStrategies">
<Map>
<Entry>
<Item type="short">2</Item>
<Item><New class="org.eclipse.jetty.spdy.http.PushStrategy$None" /></Item>
</Entry>
<Entry>
<Item type="short">3</Item>
<Item><Ref id="pushStrategy" /></Item>
</Entry>
</Map>
</Arg>
-->
<Set name="Port">8443</Set>
</New>
</Arg>

View File

@ -16,6 +16,9 @@
package org.eclipse.jetty.spdy.http;
import java.util.Collections;
import java.util.Map;
import org.eclipse.jetty.spdy.api.SPDY;
import org.eclipse.jetty.util.ssl.SslContextFactory;
@ -23,32 +26,41 @@ public class HTTPSPDYServerConnector extends AbstractHTTPSPDYServerConnector
{
public HTTPSPDYServerConnector()
{
this(null, new PushStrategy.None());
this(null, Collections.<Short, PushStrategy>emptyMap());
}
public HTTPSPDYServerConnector(PushStrategy pushStrategy)
public HTTPSPDYServerConnector(Map<Short, PushStrategy> pushStrategies)
{
this(null, pushStrategy);
this(null, pushStrategies);
}
public HTTPSPDYServerConnector(SslContextFactory sslContextFactory)
{
this(sslContextFactory, new PushStrategy.None());
this(sslContextFactory, Collections.<Short, PushStrategy>emptyMap());
}
public HTTPSPDYServerConnector(SslContextFactory sslContextFactory, PushStrategy pushStrategy)
public HTTPSPDYServerConnector(SslContextFactory sslContextFactory, Map<Short, PushStrategy> pushStrategies)
{
// We pass a null ServerSessionFrameListener because for
// HTTP over SPDY we need one that references the endPoint
super(null, sslContextFactory);
clearAsyncConnectionFactories();
// The "spdy/3" protocol handles HTTP over SPDY
putAsyncConnectionFactory("spdy/3", new ServerHTTPSPDYAsyncConnectionFactory(SPDY.V3, getByteBufferPool(), getExecutor(), getScheduler(), this, pushStrategy));
putAsyncConnectionFactory("spdy/3", new ServerHTTPSPDYAsyncConnectionFactory(SPDY.V3, getByteBufferPool(), getExecutor(), getScheduler(), this, getPushStrategy(SPDY.V3,pushStrategies)));
// The "spdy/2" protocol handles HTTP over SPDY
putAsyncConnectionFactory("spdy/2", new ServerHTTPSPDYAsyncConnectionFactory(SPDY.V2, getByteBufferPool(), getExecutor(), getScheduler(), this, pushStrategy));
putAsyncConnectionFactory("spdy/2", new ServerHTTPSPDYAsyncConnectionFactory(SPDY.V2, getByteBufferPool(), getExecutor(), getScheduler(), this, getPushStrategy(SPDY.V2,pushStrategies)));
// The "http/1.1" protocol handles browsers that support NPN but not SPDY
putAsyncConnectionFactory("http/1.1", new ServerHTTPAsyncConnectionFactory(this));
// The default connection factory handles plain HTTP on non-SSL or non-NPN connections
setDefaultAsyncConnectionFactory(getAsyncConnectionFactory("http/1.1"));
}
private PushStrategy getPushStrategy(short version, Map<Short, PushStrategy> pushStrategies)
{
PushStrategy pushStrategy = pushStrategies.get(version);
if(pushStrategy == null)
pushStrategy = new PushStrategy.None();
return pushStrategy;
}
}

View File

@ -27,7 +27,6 @@ import java.util.concurrent.TimeUnit;
import java.util.regex.Pattern;
import org.eclipse.jetty.spdy.api.Headers;
import org.eclipse.jetty.spdy.api.SPDY;
import org.eclipse.jetty.spdy.api.Stream;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
@ -62,7 +61,6 @@ public class ReferrerPushStrategy implements PushStrategy
private final Set<Pattern> pushRegexps = new HashSet<>();
private final Set<String> pushContentTypes = new HashSet<>();
private final Set<Pattern> allowedPushOrigins = new HashSet<>();
private final HashSet<Short> supportedSPDYVersions = new HashSet<Short>();
private volatile int maxAssociatedResources = 32;
private volatile int referrerPushPeriod = 5000;
@ -94,9 +92,6 @@ public class ReferrerPushStrategy implements PushStrategy
this.pushContentTypes.addAll(pushContentTypes);
for (String allowedPushOrigin : allowedPushOrigins)
this.allowedPushOrigins.add(Pattern.compile(allowedPushOrigin.replace(".", "\\.").replace("*", ".*")));
// by default we support v2 and v3
supportedSPDYVersions.add(SPDY.V2);
supportedSPDYVersions.add(SPDY.V3);
}
public int getMaxAssociatedResources()
@ -119,29 +114,11 @@ public class ReferrerPushStrategy implements PushStrategy
this.referrerPushPeriod = referrerPushPeriod;
}
public void removeSPDYVersionSupport(Short version)
{
supportedSPDYVersions.remove(version);
}
public void addSPDYVersionSupport(Short version)
{
// consider to make SPDY.Vx an enum when we add support for more than two drafts
if (version == SPDY.V2 || version == SPDY.V3)
supportedSPDYVersions.add(version);
}
@Override
public Set<String> apply(Stream stream, Headers requestHeaders, Headers responseHeaders)
{
Set<String> result = Collections.<String>emptySet();
short version = stream.getSession().getVersion();
if (!supportedSPDYVersions.contains(version))
{
logger.debug("SPDY version {} not supported. Returning empty Set.", version);
return result;
}
if (!isIfModifiedSinceHeaderPresent(requestHeaders) && isValidMethod(requestHeaders.get(HTTPSPDYHeader.METHOD.name(version)).value()))
{
String scheme = requestHeaders.get(HTTPSPDYHeader.SCHEME.name(version)).value();

View File

@ -65,26 +65,6 @@ public class ReferrerPushStrategyUnitTest
assertThat("pushResources contains two elements image.jpg and style.css", pushResources.size(), is(2));
}
@Test
public void testDisablePushByVersion() throws InterruptedException
{
referrerPushStrategy.removeSPDYVersionSupport(SPDY.V2);
Headers requestHeaders = getBaseHeaders(VERSION);
setMockExpectations();
String referrerUrl = fillPushStrategyCache(requestHeaders);
requestHeaders.put(HTTPSPDYHeader.URI.name(VERSION), MAIN_URI);
Set<String> pushResources = referrerPushStrategy.apply(stream, requestHeaders, new Headers());
assertThat("pushResources contains two elements image.jpg and style.css", pushResources.size(), is(2));
requestHeaders = getBaseHeaders(SPDY.V2);
when(session.getVersion()).thenReturn(SPDY.V2);
pushResources = referrerPushStrategy.apply(stream, requestHeaders, new Headers());
assertThat("no push resources are returned for SPDY.V2", pushResources.size(), is(0));
}
private Headers getBaseHeaders(short version)
{
Headers requestHeaders = new Headers();