Search code examples
groovyratpack

Using `prefix {}` method instead of `all { byMethod { } }` in Ratpack causes 405 Method Not Allowed - what's wrong?


I've just started reading "Learn Ratpack", in one of the examples from the very beginning of the book, the author uses 'all', 'byMethod', 'get' and 'post' to exemplify how to parse request data, the way that he does it work, but I've tried using 'prefix', 'get' and 'post' but I can't get the same result, it's returning 405-Method Not Allowed.

I tried to find something in the docs, but I couldn't see why the behavior with 'prefix'.

Example version

import static ratpack.groovy.Groovy.ratpack
import ratpack.form.Form

ratpack {
    handlers {
        all {
            byMethod {
                get {
                  //In the exemple he sends a html form
                }
                post {
                  //And here he parses it.
                }
            }
        }
    }
}

405 version

import static ratpack.groovy.Groovy.ratpack
import ratpack.form.Form

ratpack {
    handlers {
        prefix("parsing-request-data") {
            get{
               //From here all the same

That's it, what am I missing?


Solution

  • If you want to use multiple different HTTP methods for the same relative path, you still need to create such handlers using byMethod {} method. Otherwise, the first handler in the chain that matches the relative path handles the request, and it may fail or succeed. (In your case POST request fails with 405 Method Not Allowed because the get handler handles the request and it finds an incorrect HTTP method in the request. If you would like to see the GET request to fail instead of the POST one - reorder methods so the post {} is the first handler in the chain.)

    This byMethod {} method allows to register multiple handlers for the same relative path, and those handlers will be resolved based on the request's HTTP method. In case of using prefix {} method you may access byMethod {} method in the path {} helper method:

    import static ratpack.groovy.Groovy.ratpack
    
    ratpack {
    
        handlers {
    
            prefix("parsing-request-data") {
                path {
                    byMethod {
                        post {
                            response.send("A response returned from POST /parsing-request-data\n ")
                        }
    
                        get {
                            response.send("A response returned from GET /parsing-request-data\n")
                        }
                    }
                }
    
                get("test") {
                    response.send("A response returned from GET /parsing-request-data/test\n")
                }
            }
        }
    }
    

    And a few curl commands to test it:

    $ curl -i -X GET http://localhost:5050/parsing-request-data    
    HTTP/1.1 200 OK
    content-type: text/plain;charset=UTF-8
    content-length: 51
    
    A response returned from GET /parsing-request-data
    
    $ curl -i -X POST http://localhost:5050/parsing-request-data    
    HTTP/1.1 200 OK
    content-type: text/plain;charset=UTF-8
    content-length: 53
    
    A response returned from POST /parsing-request-data
    
    $ curl -i -X GET http://localhost:5050/parsing-request-data/test
    HTTP/1.1 200 OK
    content-type: text/plain;charset=UTF-8
    content-length: 56
    
    A response returned from GET /parsing-request-data/test