Tim Visser
Tim Visser

Reputation: 919

Elegant way of setting headers in Play Framework 2.4.x

Is there a more elegant way to set the Content-Range, X-Content-Range and Content-Length headers in Play Framework 2.4.x?

public static Result stream(Long id) {
    byte[] data = Song.get(id).getData();
    RangeWrapper range = new RangeWrapper(request().getHeader("Range"), data.length);

    Chunks<byte[]> chunks = ByteChunks.whenReady(out -> {
        out.write(Arrays.copyOfRange(data, range.getFrom(), range.getTo()));
        out.close();
    });

    // Is there a way of saying @After(range.getFrom(), range.getTo(), range.getContentLength(), data.length)?
    response().setHeader("Content-Range", String.format("bytes %d-%d/%d", range.getFrom(), range.getTo(), data.length));
    response().setHeader("X-Content-Length", Integer.toString(range.getContentLength()));
    response().setHeader("Content-Length", Integer.toString(range.getContentLength()));

    return status(206, chunks);
}

Or am I stuck with the solution presented because you cannot specify parameters with @With, @Before and @After?

Upvotes: 0

Views: 1069

Answers (2)

gpgekko
gpgekko

Reputation: 3616

Aside from putting the setHeader(...) methods in a utility method and calling it from each action to reduce code duplication, there is not much to improve on your solution (sadly).

Both action composition and global intercepts only work well for a @Before type case, especially if you want to pass on variables from the action they are quite useless.

Upvotes: 1

biesior
biesior

Reputation: 55798

@Before and @After annotations were available in Play 1.x and they doesn't exists in Play 2.x anymore, you can use still @With with which you can incorporate your own class as interceptor for the controllers and/or actions.

Anyway I can't see nothing wrong in using setHeader(...) method within each action especially when they're depended on required resource's properties - like in chunked response.

Upvotes: 1

Related Questions