Search code examples
groovycorsratpack

Can I allow DELETE from all origins with groovy-dsl?


Building a quick and dirty REST API with Ratpack script; can't figure out how to allow DELETE from all origins.

I've tried setting headers within delete, and using all (as in sample code.) Sending DELETE with curl, postman, everything always returns 405. Am I missing something simple?

@Grapes([
  @Grab('io.ratpack:ratpack-groovy:1.6.1')
])

ratpack {
    handlers {
        all {
            MutableHeaders headers = response.headers
            headers.set("Access-Control-Allow-Origin", "*")
            headers.set("Access-Control-Allow-Methods", "GET, PUT, POST, DELETE")
            next()
        }

        post("product") {
            ...
        }

        get("product/:id") {
            ...
        }

        delete("product/:productId") {
            // always returns 405
            ...
        }
    }
}

Solution

  • You see HTTP/1.1 405 Method Not Allowed response status because your request gets handled by the get("product/:id") handler. If you want to use the same path for multiple HTTP methods, you can use prefix combined with byMethod method to define multiple handlers for the same path.

    Consider the following example:

    import ratpack.http.MutableHeaders
    
    import static ratpack.groovy.Groovy.ratpack
    
    ratpack {
        handlers {
            all {
                MutableHeaders headers = response.headers
                headers.set("Access-Control-Allow-Origin", "*")
                headers.set("Access-Control-Allow-Methods", "GET, PUT, POST, DELETE")
                next()
            }
    
            prefix("product") {
                post {
                    render("POST /product")
                }
    
                prefix(":id") {
                    path {
                        byMethod {
                            get {
                                render("GET /product/${allPathTokens.id}")
                            }
    
                            delete {
                                render("DELETE /product/${allPathTokens.id}")
                            }
                        }
                    }
                }
            }
        }
    }
    

    As you can see in the example above, you can nest prefixes. We can test it with the following curl requests:

    $ curl -X POST http://localhost:5050/product
    POST /product%                                                                                                                                                                                                                                 
    
    $ curl -X GET http://localhost:5050/product/test
    GET /product/test%                                                                                                                                                                                                                             
    
    $ curl -X DELETE http://localhost:5050/product/test
    DELETE /product/test%  
    

    If you are interested in more details, I have written a blog post some time ago with a similar example - https://e.printstacktrace.blog/using-the-same-prefix-with-different-http-methods-in-ratpack/