package io.dropwizard.jetty;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.dropwizard.util.Duration;
import io.dropwizard.validation.MinDuration;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlets.PushCacheFilter;
import javax.annotation.Nullable;
import javax.servlet.DispatcherType;
import javax.validation.constraints.Min;
import java.util.EnumSet;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
A factory for building HTTP/2 PushCacheFilter
,
Configuration Parameters:
Name
Default
Description
enabled
false
If true, the filter will organize resources as primary resources (those referenced by the
Referer header) and secondary resources (those that have the Referer header).
Secondary resources that have been requested within a time window from the request of the
primary resource will be associated with the it. The next time a client will
request the primary resource, the server will send to the client the secondary resources
along with the primary in a single response.
associatePeriod
4 seconds
The time window within which a request for a secondary resource will be associated to a
primary resource.
maxAssociations
16
The maximum number of secondary resources that may be associated to a primary resource.
refererHosts
All hosts
The list of referrer hosts for which the server push technology is supported.
refererPorts
All ports
The list of referrer ports for which the server push technology is supported.
/**
* A factory for building HTTP/2 {@link PushCacheFilter},
* <p/>
* <b>Configuration Parameters:</b>
* <table>
* <tr>
* <td>Name</td>
* <td>Default</td>
* <td>Description</td>
* </tr>
* <tr>
* <td>{@code enabled}</td>
* <td>false</td>
* <td>
* If true, the filter will organize resources as primary resources (those referenced by the
* <i>Referer</i> header) and secondary resources (those that have the <i>Referer</i> header).
* Secondary resources that have been requested within a time window from the request of the
* primary resource will be associated with the it. The next time a client will
* request the primary resource, the server will send to the client the secondary resources
* along with the primary in a single response.
* </td>
* </tr>
* <tr>
* <td>{@code associatePeriod}</td>
* <td>4 seconds</td>
* <td>
* The time window within which a request for a secondary resource will be associated to a
* primary resource.
* </td>
* </tr>
* <tr>
* <td>{@code maxAssociations}</td>
* <td>16</td>
* <td>
* The maximum number of secondary resources that may be associated to a primary resource.
* </td>
* </tr>
* <tr>
* <td>{@code refererHosts}</td>
* <td>All hosts</td>
* <td>
* The list of referrer hosts for which the server push technology is supported.
* </td>
* </tr>
* <tr>
* <td>{@code refererPorts}</td>
* <td>All ports</td>
* <td>
* The list of referrer ports for which the server push technology is supported.
* </td>
* </tr>
* </table>
*/
public class ServerPushFilterFactory {
private boolean enabled = false;
@MinDuration(value = 1, unit = TimeUnit.MILLISECONDS)
private Duration associatePeriod = Duration.seconds(4);
@Min(1)
private int maxAssociations = 16;
@Nullable
private List<String> refererHosts;
@Nullable
private List<Integer> refererPorts;
@JsonProperty
public boolean isEnabled() {
return enabled;
}
@JsonProperty
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
@JsonProperty
public Duration getAssociatePeriod() {
return associatePeriod;
}
@JsonProperty
public void setAssociatePeriod(Duration associatePeriod) {
this.associatePeriod = associatePeriod;
}
@JsonProperty
public int getMaxAssociations() {
return maxAssociations;
}
@JsonProperty
public void setMaxAssociations(int maxAssociations) {
this.maxAssociations = maxAssociations;
}
@Nullable
@JsonProperty
public List<String> getRefererHosts() {
return refererHosts;
}
@JsonProperty
public void setRefererHosts(@Nullable List<String> refererHosts) {
this.refererHosts = refererHosts;
}
@Nullable
@JsonProperty
public List<Integer> getRefererPorts() {
return refererPorts;
}
@JsonProperty
public void setRefererPorts(@Nullable List<Integer> refererPorts) {
this.refererPorts = refererPorts;
}
public void addFilter(ServletContextHandler handler) {
if (!enabled) {
return;
}
handler.setInitParameter("associatePeriod", String.valueOf(associatePeriod.toMilliseconds()));
handler.setInitParameter("maxAssociations", String.valueOf(maxAssociations));
if (refererHosts != null) {
handler.setInitParameter("hosts", String.join(",", refererHosts));
}
if (refererPorts != null) {
final String ports = refererPorts.stream()
.map(Object::toString)
.collect(Collectors.joining(","));
handler.setInitParameter("ports", ports);
}
handler.addFilter(PushCacheFilter.class, "/*", EnumSet.of(DispatcherType.REQUEST));
}
}