Liviu Sosu
Liviu Sosu

Reputation: 1547

How to get the REST response in Groovy?

I have to write a small script within a web app. This web app has it's limitations but is similar to this online console: https://groovyconsole.appspot.com/ so if it works here, it should work for my problem as well.

I need to parse a JSON response. For simplicity I developed in C# my own web API and when I enter on the browser the link (http://localhost:3000/Test) it gives this string :

{"Code":1,"Message":"This is just a test"}

I want to get this string, and parse it afterwards, I guess with JsonSplunker. After hours of research, the most compelling sample would be this:

import groovyx.net.http.RESTClient

def client = new RESTClient( 'http://www.acme.com/' )
def resp = client.get( path : 'products/3322' ) // ACME boomerang

assert resp.status == 200  // HTTP response code; 404 means not found, etc.
println resp.getData()

(taken from here: http://rest.elkstein.org/2008/02/using-rest-in-groovy.html)

However it does not recognize import groovyx.net.http.RESTClient. You can try testing it in the groovy web sonsole provided and you will get the error.

I tried import groovyx.net.http.RESTClient.* but still no success.

Upvotes: 12

Views: 75140

Answers (3)

Tomas Bjerre
Tomas Bjerre

Reputation: 3500

I have tried to find an existing REST client to use but I always end up creating my own. I mostly use it in Jenkins pipelines, something like this:

new RestClient(this,"http://some-server.domain/gitlab")
 .get('/api/v4/projects/' + repo.id + '/hooks')
 .each { hook ->
  println "Hook: " + hook
 }

And here is the actual RestClient:

package se.bjurr.jenkinssandbox

public class RestClient {
  private def baseUrl
  private def steps

  public RestClient(def steps, def baseUrl='http://localhost') {
    this.steps = steps
    this.baseUrl = baseUrl
  }

  def get(def path) {
    def responseText = ""
    steps.withCredentials([steps.string(credentialsId: 'gitlab-token', variable: 'gitlabToken')]) {
      steps.println "Using token: "+steps.env.gitlabToken +" to get \"" + baseUrl + path + "\""
      def conn = null
      try {
        conn = new URL(baseUrl+path).openConnection();
        conn.setRequestMethod("GET")
        conn.setRequestProperty("Content-Type", "application/json")
        conn.setRequestProperty("Private-Token", steps.env.gitlabToken)
        conn.setDoOutput(false)
        def postRC = conn.getResponseCode();
        responseText = conn.getInputStream().getText()
        steps.println "Got: " + postRC + "\n"+responseText
      } finally {
        conn.disconnect()
      }
      //Because classic is serilizable
      return new groovy.json.JsonSlurperClassic().parseText(responseText)
    }
  }

  def delete(def path) {
    def responseText = ""
    steps.withCredentials([steps.string(credentialsId: 'gitlab-token', variable: 'gitlabToken')]) {
      steps.println "Using token: "+steps.env.gitlabToken +" to delete \"" + baseUrl + path + "\""
      def conn = null
      try {
        conn = new URL(baseUrl+path).openConnection();
        conn.setRequestMethod("DELETE")
        conn.setRequestProperty("Private-Token", steps.env.gitlabToken)
        conn.setDoOutput(false)
        def postRC = conn.getResponseCode();
        responseText = conn.getInputStream().getText()
        steps.println "Got: " + postRC + "\n"+responseText
      } finally {
        conn.disconnect()
      }
    }
  }

  def post(def path) {
    def responseText = ""
    steps.withCredentials([steps.string(credentialsId: 'gitlab-token', variable: 'gitlabToken')]) {
      steps.println "Using token: "+steps.env.gitlabToken +" to post \"" + baseUrl + path + "\""
      def conn = null
      try {
        conn = new URL(baseUrl+path).openConnection();
        conn.setRequestMethod("POST")
        conn.setRequestProperty("Content-Type", "application/json")
        conn.setRequestProperty("Private-Token", steps.env.gitlabToken)
        conn.setDoOutput(false)
        def postRC = conn.getResponseCode();
        responseText = conn.getInputStream().getText()
        steps.println "Got: " + postRC + "\n"+responseText
      } finally {
        conn.disconnect()
      }
      //Because classic is serilizable
      return new groovy.json.JsonSlurperClassic().parseText(responseText)
    }
  }

  def post(def path, def payload) {
    def responseText = ""
    steps.withCredentials([steps.string(credentialsId: 'gitlab-token', variable: 'gitlabToken')]) {
      String jsonString = new groovy.json.JsonBuilder(payload).toPrettyString()
      steps.println "Using token: "+steps.env.gitlabToken +" to post \"" + baseUrl + path + "\" with:\n"+jsonString
      def conn = null
      try {
        conn = new URL(baseUrl+path).openConnection();
        conn.setRequestMethod("POST")
        conn.setRequestProperty("Content-Type", "application/json")
        conn.setRequestProperty("Private-Token", steps.env.gitlabToken)
        conn.setDoOutput(true)
        conn.getOutputStream().write(jsonString.getBytes("UTF-8"));
        def postRC = conn.getResponseCode();
        responseText = conn.getInputStream().getText()
        steps.println "Got: " + postRC + "\n"+responseText
      } finally {
        conn.disconnect()
      }
      //Because classic is serilizable
      return new groovy.json.JsonSlurperClassic().parseText(responseText)
    }
  }
}

Upvotes: 10

Emmanuel Rosa
Emmanuel Rosa

Reputation: 9885

If your problem is with importing groovyx.net.http.RESTClient, then you're missing the dependency org.codehaus.groovy.modules.http-builder:http-builder.

If you're dealing with just a stand-alone Groovy script, you can use Groovy's Grape to fetch the dependency. Here's an example from RESTClient's home page:

@Grab('org.codehaus.groovy.modules.http-builder:http-builder:0.7')
@Grab('oauth.signpost:signpost-core:1.2.1.2')
@Grab('oauth.signpost:signpost-commonshttp4:1.2.1.2')

import groovyx.net.http.RESTClient
import static groovyx.net.http.ContentType.*

def twitter = new RESTClient( 'https://api.twitter.com/1.1/statuses/' )
// twitter auth omitted

try { // expect an exception from a 404 response:
    twitter.head path: 'public_timeline'
    assert false, 'Expected exception'
}
// The exception is used for flow control but has access to the response as well:
catch( ex ) { assert ex.response.status == 404 }

assert twitter.head( path: 'home_timeline.json' ).status == 200

If your web app uses a dependency system, such as Gradle, then you can use it instead of @Grab.

Upvotes: 4

Michael Easter
Michael Easter

Reputation: 24468

Here is a simple Groovy script that sends an HTTP POST to an online server and parses the response with JsonSlurper.

This script can run as standalone on your machine; it probably won't work in an online Groovy REPL. It uses the Apache HTTPClient jar, which is added to the classpath via @Grab.

For a project, one would not use this method but rather add the jar to the classpath in Gradle.

Upvotes: 10

Related Questions