How to get header using groovy

classic Classic list List threaded Threaded
7 messages Options
Reply | Threaded
Open this post in threaded view
|

How to get header using groovy

eaglet
This post was updated on .
What is the best way to process a GET request, retrieve an Authorization header (with Bearer token), and use it to make a call to another API on another system?

I am trying to use the Groovy DSL, Ratpack 1.1.1 and am having difficulty with examples that don't work in the current manual.
Reply | Threaded
Open this post in threaded view
|

Re: How to get header using groovy

PL99
ratpack {
  handlers {
    prefix("api") {
      handler {
        // common code for all api calls
        // log all HTTP request headers
        request.headers?.names?.each { name ->
          logger.debug("HEADER: ${name}, VALUES: ${request.headers?.getAll(name)}")
        }
        // call next handlers
      }
...


See full code example here https://gist.github.com/zedar/e6f6cda10236fed22b68
Reply | Threaded
Open this post in threaded view
|

Re: How to get header using groovy

eaglet
Thank you for the quick response PL99.  However I get the following 500 server error on the console when sending a request:

[ratpack-compute-1-3] WARN ratpack.server.internal.NettyHandlerAdapter - No response sent for GET request to /api/customers (last handler: closure at line 95 of file:///<project path removed>/build/resources/main/ratpack.groovy)

Is there a Ratpack default log that can provide more information on the error?  I get this generic WARN when just doing a println message to the console!

Also, what are the question marks used for?  I am not familiar with that notation.

Here is part of my Ratpack.groovy file structure.  Is there a problem with this structure?:

ratpack {
  handlers {
    get('login') {
        // redirects user to Azure AD to login and get token
    }
    get('') {
        // Renders a page with Javascript that gets the token from the fragment,
        // Also calls Ratpack server with GET /api/customers including the Authorization header
        render groovyMarkupTemplate("index.gtpl", title: "CC API Test")
    }
    prefix("api") {
        handler {
            // common code for all api calls
            // log all HTTP request headers
            request.headers?.names?.each { name ->
                logger.debug("HEADER: ${name}, VALUES: ${request.headers?.getAll(name)}")
            }
        }
        get("customers") {
            // calls customer
            logger.debug("./customers called")
        }
    }
    post('...') {
    ...
    }
}
Reply | Threaded
Open this post in threaded view
|

Re: How to get header using groovy

PL99
eaglet, sorry for copy-paste
Next lines of code was testing and works fine for me
import ratpack.groovy.template.MarkupTemplateModule

import static ratpack.groovy.Groovy.groovyMarkupTemplate
import static ratpack.groovy.Groovy.ratpack

ratpack {
  bindings {
    module MarkupTemplateModule
  }

  handlers {
    get (''){
      render groovyMarkupTemplate("index.gtpl", title: "CC API Test") 
    }
        prefix ("myapi"){
            all {
                request.headers?.names?.each { name ->
                    println ("HEADER: ${name}, VALUES: ${request.headers?.getAll(name)}")
                }
                next()
            }
            path("customers"){
                byMethod(){
                    get(){
                        render "./customers get method called"
                    }
                    post(){
                        render "./customers post method called"
                    }
                }
            }
        }
  }
}

I hope this example will help you.

NettyHandlerAdapter warning reports that the client receives no response. In this example I use the next () call to transfer control to another handler.

Question marks in code is groovy safe navigation operator
Reply | Threaded
Open this post in threaded view
|

Re: How to get header using groovy

eaglet
Thank you!  Your example is working for me too.  I can now access the Authorization header and print it.

However, I keep getting this error when trying to make the call to the other API:
[ratpack-compute-1-3] WARN ratpack.server.internal.NettyHandlerAdapter - No response sent for GET request to /api/customers (last handler: closure at line 86 of file:///<file-location-removed>/ratpack.groovy)

Line 86 is the path() line

        prefix ("api") {
            all {
                request.headers?.names?.each { name ->
                    println ("HEADER: ${name}, VALUES: ${request.headers?.getAll(name)}")
                }
                next()
            }
            path("customers") {
                byMethod() {
                    get() { HttpClient httpClient ->
                        URI proxyUri = new URI(request.rawUri)
                        proxyUri.host = 'localhost'
                        proxyUri.port = ccapiPort
                        proxyUri.scheme = 'https'
                        httpClient.requestStream(proxyUri) { RequestSpec spec ->
                            spec.headers.copy(request.headers)
                        }.then { StreamedResponse responseStream ->
                            responseStream.send(response)
                        }
                    }
                    post() {
                        render "./customers post method called"
                    }
                }
            }
        }

What is the best way to do a simple request from the Ratpack HttpClient?

rus
Reply | Threaded
Open this post in threaded view
|

Re: How to get header using groovy

rus
I think your problem is that you have

    get() { HttpClient httpClient ->

`get` is not a handler in this context and so you can't inject objects from the registry to it like that.  It's actually a method on `ByMethodSpec` that takes a `Block` https://ratpack.io/manual/current/api/ratpack/handling/ByMethodSpec.html#get-ratpack.func.Block-

Try moving it up to path

     path("customers") { HttpClient httpClient ->
         byMethod {
             get {
Reply | Threaded
Open this post in threaded view
|

Re: How to get header using groovy

eaglet
Thanks Rus.  I didn't realize that the get() within a byMethod was not a handler.  I ran into trouble moving the closure up to path, so I tried simplifying the code a bit.

This is what I eventually came up with.  It takes the Authorization header from the request and propagates it for an authenticated call to a web service.  Its not the best, I know, but it works.  

The most difficult part was not having a stack trace to peruse when there was a syntax error within the closures.  If anyone knows of a better way to debug DSL code, please let me know.

        prefix ("api") {
            all {
                request.headers?.names?.each { name ->
                    println ("HEADER: ${name}, VALUES: ${request.headers?.getAll(name)}")
                }
                next()
            }
            get("customers") { HttpClient httpClient ->
                auth = request.headers?.Authorization
                URI proxyUri = new URI(clientCred.ccLocalhostBaseUrl + "/api/customers")
                httpClient.get(proxyUri) { RequestSpec spec ->
                    spec.headers.set("Authorization", auth)
                } onError {
                    println "Something went wrong: ${proxyUri.toString()}: ${it}"
                    render it.toString()
                } then { ReceivedResponse ccResponse ->
                    def jsonOutput = JsonOutput.prettyPrint(ccResponse.body.text)
                    render jsonOutput
                }
            }
        }

Thank you everyone for your help!