Search

Dark theme | Light theme

December 23, 2015

Ratpacked: Respond To Custom MIME Types

In Ratpack we can use the byContent method on the Context object to send different responses based on the requested MIME type from the client. There is already support for application/json, application/xml, text/plain and text/html MIME types with corresponding methods of the ByContentSpec object that is passed as argument to the byContent method. We can match on a custom MIME type with the method type and specify the MIME type. If the type matches we can create a response.

In the following example application we have a custom renderer for a User object:

// File: src/main/groovy/com/mrhaki/ratpack/UserRenderer.groovy
package com.mrhaki.ratpack

import ratpack.handling.ByContentSpec
import ratpack.handling.Context
import ratpack.jackson.Jackson
import ratpack.render.RendererSupport

import static ratpack.groovy.Groovy.markupBuilder

class UserRenderer extends RendererSupport<User> {
    
    @Override
    void render(Context context, User user) throws Exception {
        context.byContent { ByContentSpec spec ->
            spec
                .type('application/vnd.com.mrhaki.user+json;v=1') {
                    context.render(Jackson.json(user))
                }
                .type('application/vnd.com.mrhaki.user+xml;v=1') {
                    context.render(markupBuilder('application/xml', 'UTF-8') {
                        delegate.user {
                            username(user.username)
                        }
                    })
                }
        }
    }
    
}

Next we use it in our Ratpack definition:

import com.mrhaki.ratpack.User
import com.mrhaki.ratpack.UserRenderer

import static ratpack.groovy.Groovy.ratpack

ratpack {
    bindings {
        // Register renderer for User objects.
        bind(UserRenderer)
        
        // Create two sample users.
        bindInstance(['mrhaki', 'hubert'].collect { String name ->
            new User(username: name)
        })        
    }

    handlers {
        get('user/:username') { List<User> users ->
            // Get value for username token.
            final String username = pathTokens.username
            
            // Find user in list of users.
            final User user = users.find { User user ->
                user.username == username
            }
            
            // Render user object.
            render(user)
        }
    }
}

When we make a request with different accept MIME types we see different results:

$ http localhost:5050/user/mrhaki Accept:application/vnd.com.mrhaki.user+xml;v=1
HTTP/1.1 200 OK
connection: keep-alive
content-encoding: gzip
content-type: application/xml
transfer-encoding: chunked

<user>
    <username>mrhaki</username>
</user>

$ http localhost:5050/user/mrhaki Accept:application/vnd.com.mrhaki.user+json;v=1
HTTP/1.1 200 OK
connection: keep-alive
content-encoding: gzip
content-type: application/vnd.com.mrhaki.user+json;v=1
transfer-encoding: chunked

{
    "username": "mrhaki"
}

$

Written with Ratpack 1.1.1.