Skip to content
This repository has been archived by the owner on Sep 12, 2021. It is now read-only.

Remove global state and provide default DI modules #45

Merged
merged 1 commit into from
Oct 11, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
242 changes: 121 additions & 121 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@
In your project/Build.scala:
```scala
libraryDependencies ++= Seq(
"com.mohiva" %% "play-html-compressor" % "0.4.1"
"com.mohiva" %% "play-html-compressor" % "0.5.0"
)
```

### History

* For Play Framework 2.4 use version 0.4.1
* For Play Framework 2.4 use version 0.5.0
* For Play Framework 2.3 use version 0.3.1
* For Play Framework 2.2 use version 0.2.1
* For Play Framework 2.1 use version 0.1-SNAPSHOT
Expand All @@ -24,171 +24,171 @@ configurations, but it can also be used with user-defined configurations. The
following two examples shows how to define the filters with the default and the
user-defined configurations.

### Default filter
To provide the filters for your application you must define it as described in the Play
Documentation ([Scala](https://www.playframework.com/documentation/2.4.x/ScalaHttpFilters#Using-filters), [Java](https://www.playframework.com/documentation/2.4.x/JavaHttpFilters#Using-filters)).

The default HTMLCompressorFilter has the same configuration as the user-defined filter below.
### Provide filters

#### For Scala users

```scala
import play.api.mvc.WithFilters
import javax.inject.Inject

import com.mohiva.play.htmlcompressor.HTMLCompressorFilter
import com.mohiva.play.xmlcompressor.XMLCompressorFilter

/**
* Uses the default implementation of the HTML and XML compressor filters.
*/
object Global extends WithFilters(HTMLCompressorFilter(), XMLCompressorFilter())
import play.api.http.HttpFilters
import play.api.mvc.EssentialFilter

class Filters @Inject() (
htmlCompressorFilter: HTMLCompressorFilter,
xmlCompressorFilter: XMLCompressorFilter)
extends HttpFilters {

override def filters: Seq[EssentialFilter] = Seq(
htmlCompressorFilter,
xmlCompressorFilter
)
}
```

#### For Java users

```java
import play.GlobalSettings;
import com.mohiva.play.htmlcompressor.HTMLCompressorFilter;
import com.mohiva.play.xmlcompressor.XMLCompressorFilter;
import play.api.mvc.EssentialFilter;
import com.mohiva.play.htmlcompressor.java.HTMLCompressorFilter;
import com.mohiva.play.xmlcompressor.java.XMLCompressorFilter;

/**
* Uses the default implementations of the HTML and XML compressor filters.
*/
public class Global extends GlobalSettings {

/**
* Get the filters that should be used to handle each request.
*/
@SuppressWarnings("unchecked")
public <T extends EssentialFilter> Class<T>[] filters() {
return new Class[] {
HTMLCompressorFilter.class,
XMLCompressorFilter.class
import play.http.HttpFilters;

import javax.inject.Inject;

public class DefaultFilter implements HttpFilters {

private HTMLCompressorFilter htmlCompressorFilter;
private XMLCompressorFilter xmlCompressorFilter;

@Inject
public DefaultFilter(
HTMLCompressorFilter htmlCompressorFilter,
XMLCompressorFilter xmlCompressorFilter) {

this.htmlCompressorFilter = htmlCompressorFilter;
this.xmlCompressorFilter = xmlCompressorFilter;
}

@Override
public EssentialFilter[] filters() {
return new EssentialFilter[] {
htmlCompressorFilter,
xmlCompressorFilter
};
}
}

```

### Default filter

For the default filters we provide DI modules which will be automatically enabled if you
pull in the dependency. You must only provide your instance of `HttpFilters` as described
above.

### User-defined filter

#### For Scala users
For user defined filters there is a little bit mor to do. First you must create your instances of
the filter. As next you must provide your instance of `HttpFilters` as described above. At last
you must provide the bindings for you created filter and disable the default DI modules.

#### Implement filters

##### For Scala users

```scala
import javax.inject.Inject

import play.api.mvc.WithFilters
import play.api.Play
import play.api.Play.current
import com.googlecode.htmlcompressor.compressor.HtmlCompressor
import com.mohiva.play.htmlcompressor.HTMLCompressorFilter
import play.api.{Configuration, Environment, Mode}

class CustomHTMLCompressorFilter @Inject() (
val configuration: Configuration, environment: Environment)
extends HTMLCompressorFilter {

/**
* Uses a user-defined implementation of the HTML compressor filter.
*/
object Global extends WithFilters(HTMLCompressorFilter())

/**
* Defines a user-defined HTML compressor filter.
*/
object HTMLCompressorFilter {

/**
* Creates the HTML compressor filter.
*
* @return The HTML compressor filter.
*/
def apply() = new HTMLCompressorFilter({
val compressor = new HtmlCompressor()
if (Play.isDev) {
compressor.setPreserveLineBreaks(true)
override val compressor: HtmlCompressor = {
val c = new HtmlCompressor()
if (environment.mode == Mode.Dev) {
c.setPreserveLineBreaks(true)
}

compressor.setRemoveComments(true)
compressor.setRemoveIntertagSpaces(true)
compressor.setRemoveHttpProtocol(true)
compressor.setRemoveHttpsProtocol(true)
compressor
})
c.setRemoveComments(true)
c.setRemoveIntertagSpaces(false)
c.setRemoveHttpProtocol(true)
c.setRemoveHttpsProtocol(true)
c
}
}

```

#### For Java users
##### For Java users

```java
import play.Play;
import play.GlobalSettings;
import play.api.mvc.EssentialFilter;
import com.googlecode.htmlcompressor.compressor.HtmlCompressor
import com.mohiva.play.htmlcompressor.java.HTMLCompressorFilter;
import com.mohiva.play.htmlcompressor.java.HTMLCompressorBuilder;

/**
* Uses a user-defined implementation of the HTML compressor filter.
*/
public class Global extends GlobalSettings {

/**
* Get the filters that should be used to handle each request.
*/
@SuppressWarnings("unchecked")
public <T extends EssentialFilter> Class<T>[] filters() {
return new Class[]{CustomHTMLCompressorFilter.class};
import com.googlecode.htmlcompressor.compressor.HtmlCompressor;
import com.mohiva.play.htmlcompressor.HTMLCompressorFilter;
import play.Environment;
import play.Mode;
import play.api.Configuration;

import javax.inject.Inject;

public class CustomHTMLCompressorFilter extends HTMLCompressorFilter {

private Configuration configuration;
private Environment environment;

@Inject
public CustomHTMLCompressorFilter(
Configuration configuration, Environment environment) {

this.configuration = configuration;
this.environment = environment;
}

/**
* Custom implementation of the HTML compressor filter.
*/
public static class CustomHTMLCompressorFilter extends HTMLCompressorFilter {
public CustomHTMLCompressorFilter() {
super(new CustomHTMLCompressorBuilder());
}
@Override
public Configuration configuration() {
return configuration;
}

/**
* The builder for the custom HTML compressor.
*/
public static class CustomHTMLCompressorBuilder implements HTMLCompressorBuilder {
public HtmlCompressor build() {
HtmlCompressor compressor = new HtmlCompressor();
if (Play.isDev()) {
compressor.setPreserveLineBreaks(true);
}

compressor.setRemoveComments(true);
compressor.setRemoveIntertagSpaces(true);
compressor.setRemoveHttpProtocol(true);
compressor.setRemoveHttpsProtocol(true);
return compressor;
@Override
public HtmlCompressor compressor() {
HtmlCompressor compressor = new HtmlCompressor();
if (environment.mode() == Mode.DEV) {
compressor.setPreserveLineBreaks(true);
}
}
}
```

#### User-defined XMLCompressorFilter
compressor.setRemoveComments(true);
compressor.setRemoveIntertagSpaces(true);
compressor.setRemoveHttpProtocol(true);
compressor.setRemoveHttpsProtocol(true);

You can also use a user defined XMLCompressorFilter. The approach is analogical
to the examples given above.
return compressor;
}
}

### HTMLCompressorFilter & GzipFilter
```

Be careful when using HTMLCompressorFilter in combination with the Play
GzipFilter. HTMLCompressorFilter can not work on source that has already been
gzipped.
#### Provide bindings

Unfortunately, there is no official way to control the order in which filters
will be applied to responses.
To provide your bindings for your user defined filter you must either create a new module
or you can add the binding to your default DI module. This process is detailed documented
for [Scala](https://www.playframework.com/documentation/2.4.x/ScalaDependencyInjection) and
[Java](https://www.playframework.com/documentation/2.4.x/JavaDependencyInjection) users. So
please refer to this documentation.

Fortunately, Play Framework will apply the filters in reverse order of
appearance in the `WithFilters` constructor. So this code will work as expected
(applying HTMLCompressorFilter first and GzipFilter on the compressed HTML):
##### Disable default modules

```scala
object Global extends WithFilters(new GzipFilter(), HTMLCompressorFilter()) {
...
}
```
To disable the default modules you must append the modules to the `play.modules.disabled` property in `application.conf`:

This code will _not_ work, resulting in an empty response body (or worse):
```scala
object Global extends WithFilters(HTMLCompressorFilter(), new GzipFilter()) {
...
}
play.modules.disabled += "com.mohiva.play.htmlcompressor.HTMLCompressorFilterModule"
play.modules.disabled += "com.mohiva.play.xmlcompressor.XMLCompressorFilterModule"
```
28 changes: 21 additions & 7 deletions app/com/mohiva/play/compressor/CompressorFilter.scala
Original file line number Diff line number Diff line change
@@ -1,10 +1,19 @@
/**
* Play HTML Compressor
*
* LICENSE
*
* This source file is subject to the new BSD license that is bundled
* with this package in the file LICENSE.md.
* It is also available through the world-wide-web at this URL:
* https://github.com/mohiva/play-html-compressor/blob/master/LICENSE.md
*/
package com.mohiva.play.compressor

import play.api.http.HttpProtocol
import play.twirl.api.Content
import play.api.mvc._
import play.api.Play
import play.api.Play.current
import play.api.Configuration
import play.api.http.HeaderNames._
import play.api.libs.iteratee.{ Enumerator, Iteratee }
import scala.concurrent.Future
Expand All @@ -18,17 +27,22 @@ import com.googlecode.htmlcompressor.compressor.Compressor
* @see http://jazzy.id.au/default/2013/02/16/understanding_the_play_filter_api.html
* @see http://stackoverflow.com/questions/14154671/is-it-possible-to-prettify-scala-templates-using-play-framework-2
*/
abstract class CompressorFilter[C <: Compressor](f: => C) extends Filter {
abstract class CompressorFilter[C <: Compressor] extends Filter {

/**
* The charset used by Play.
* The compressor instance.
*/
lazy val charset = Play.configuration.getString("default.charset").getOrElse("utf-8")
val compressor: C

/**
* The compressor instance.
* The Play configuration instance.
*/
val configuration: Configuration

/**
* The charset used by Play.
*/
lazy val compressor = f
lazy val charset = configuration.getString("default.charset").getOrElse("utf-8")

/**
* Apply the filter.
Expand Down
Loading