Search code examples
grails

Grails Dynamic Rest Endpoint Mapping


In my UrlMappings I have this mapping defined :

"/$controller/$action?/$id?(.$format)?"{}

and now I want to add a set of version 2 services.

for example : A new service at URI : /api/myaction

and I want to be able define a new endpoint /api/v2/myaction , where myaction will map to a new action called myactionV2


Solution

  • There are a number of ways to do this and the best solution depends on some factors that you haven't included in your question. Here is a solution that most closely maps to the question and a comment that the OP added above.

    See the project at https://github.com/jeffbrown/javaheadendpoints.

    https://github.com/jeffbrown/javaheadendpoints/blob/47f41b3943422c3c9e44a08ac646ecb2046972d1/grails-app/controllers/demo/v1/ApiController.groovy

    package demo.v1
    
    class ApiController {
        static namespace = 'v1'
    
        def myaction() {
            render 'This request was handled by version 1 of the api'
        }
    }
    

    https://github.com/jeffbrown/javaheadendpoints/blob/47f41b3943422c3c9e44a08ac646ecb2046972d1/grails-app/controllers/demo/v2/ApiController.groovy

    package demo.v2
    
    class ApiController {
        static namespace = 'v2'
    
        def myaction() {
            render 'This request was handled by version 2 of the api'
        }
    }
    

    https://github.com/jeffbrown/javaheadendpoints/blob/47f41b3943422c3c9e44a08ac646ecb2046972d1/grails-app/controllers/demo/v3/ApiController.groovy

    package demo.v3
    
    class ApiController {
        static namespace = 'v3'
    
        def myaction() {
            render 'This request was handled by version 3 of the api'
        }
    }
    

    https://github.com/jeffbrown/javaheadendpoints/blob/47f41b3943422c3c9e44a08ac646ecb2046972d1/grails-app/controllers/javaheadendpoints/UrlMappings.groovy

    package javaheadendpoints
    
    class UrlMappings {
    
        static mappings = {
            "/$controller/$action?/$id?(.$format)?"{
                constraints {
                    // apply constraints here
                }
            }
    
            "/$controller/$namespace/$action/$id?(.$format)?" {
                // ...
            }
    
            "/"(view:"/index")
            "500"(view:'/error')
            "404"(view:'/notFound')
        }
    }
    

    Sending requests yields what I think is the requested behavior:

    $ curl http://localhost:8080/api/v1/myaction
    This request was handled by version 1 of the api
    $ curl http://localhost:8080/api/v2/myaction
    This request was handled by version 2 of the api
    $ curl http://localhost:8080/api/v3/myaction
    This request was handled by version 3 of the api
    

    Other options include using a Version http header but because of some of the wording above, I think that is not going to be exactly what you want.

    I hope that helps.