111

I heard that Groovy has a built-in REST/HTTP client. The only library I can find is HttpBuilder, is this it?

Basically I'm looking for a way to do HTTP GETs from inside Groovy code without having to import any libraries (if at all possible). But since this module doesn't appear to be a part of core Groovy I'm not sure if I have the right lib here.

doelleri
  • 19,232
  • 5
  • 61
  • 65
smeeb
  • 27,777
  • 57
  • 250
  • 447
  • 2
    To summarize the below answers `j = new groovy.json.JsonSlurper().parseText(new URL("https://httpbin.org/get").getText())` then `println j.headers["User-Agent"]` – MarkHu Mar 14 '17 at 20:31
  • 2
    You might also checkout an updated (re)version of the HttpBuilder library - https://http-builder-ng.github.io/http-builder-ng/ – cjstehno Apr 27 '17 at 18:16
  • If you use `@Grab` it makes http-builder fairly painless to use: `@Grab(group='org.codehaus.groovy.modules.http-builder', module='http-builder', version='0.7')` – thom_nic Jun 23 '17 at 14:20

7 Answers7

173

Native Groovy GET and POST

// GET
def get = new URL("https://httpbin.org/get").openConnection();
def getRC = get.getResponseCode();
println(getRC);
if (getRC.equals(200)) {
    println(get.getInputStream().getText());
}

// POST
def post = new URL("https://httpbin.org/post").openConnection();
def message = '{"message":"this is a message"}'
post.setRequestMethod("POST")
post.setDoOutput(true)
post.setRequestProperty("Content-Type", "application/json")
post.getOutputStream().write(message.getBytes("UTF-8"));
def postRC = post.getResponseCode();
println(postRC);
if (postRC.equals(200)) {
    println(post.getInputStream().getText());
}
Jim Perris
  • 2,545
  • 1
  • 12
  • 15
  • 6
    How do you set headers on GET or POST calls with this? – DLeh Feb 20 '19 at 03:44
  • 4
    @DLeh The setRequestProperty method does that. I used it in the example to set the Content-Type header. See https://docs.oracle.com/javase/8/docs/api/java/net/URLConnection.html#setRequestProperty-java.lang.String-java.lang.String- – Jim Perris Feb 20 '19 at 14:16
  • 1
    In pipeline as code, you must do it in shared library otherwise jenkins will forbid it for security reasons, Overriding them is possible but then you may really add vulnerabilities. – old-monk Jun 21 '19 at 20:11
  • 1
    How to get the response headers? I can't find it out . – luxin.chen Jun 28 '20 at 11:03
  • 1
    @luxin.chen figure it out: `post.getHeaderFields()`, see more methods in http://www.docjar.com/docs/api/sun/net/www/protocol/https/HttpsURLConnectionImpl.html#getHeaderFields – luxin.chen Jun 29 '20 at 06:14
  • 1
    At what exact point is the HTTP Request actually sent? Sometime during `post.getResponseCode();` ? – Philipp Doerner Apr 21 '21 at 14:37
  • 2
    @PhilippDoerner The request is implicitly sent by `getResponseCode()` or any similar method that depends on the connection being connected. I believe you can also call `connect()` to explicitly send the request. https://docs.oracle.com/javase/8/docs/api/java/net/URLConnection.html – Jim Perris Apr 21 '21 at 19:37
  • 1
    @JimPerris Could it be that `post.getOutputStream().write(message.getBytes("UTF-8"));` also counts among those that implicitly send a request? I just encountered a bug where I set a request header after writing the body with that statement and it threw an error of "already connected", which was fixed by moving the writing of the body after the writing of the headers – Philipp Doerner Apr 22 '21 at 14:22
  • 1
    @PhilippDoerner sure, that could be the case. I haven't messed with Groovy or Java in a couple years, so kinda rusty on this stuff. – Jim Perris Apr 22 '21 at 15:42
  • `URL.getOpenConnection` returns an `URLConnection`. But `URLConnection` does not know the method `setRequestMethod`, because only `HttpURLConnection` (a child of `URLConnection`) knows the method. If I try this in [ScriptRunner](https://docs.adaptavist.com/sr4js/latest), I get a type error: `Cannot find matching method java.net.URLConnection#setRequestMethod(java.lang.String)`. – ceving Jul 25 '22 at 14:18
69

If your needs are simple and you want to avoid adding additional dependencies you may be able to use the getText() methods that Groovy adds to the java.net.URL class:

new URL("http://stackoverflow.com").getText()

// or

new URL("http://stackoverflow.com")
        .getText(connectTimeout: 5000, 
                readTimeout: 10000, 
                useCaches: true, 
                allowUserInteraction: false, 
                requestProperties: ['Connection': 'close'])

If you are expecting binary data back there is also similar functionality provided by the newInputStream() methods.

John Wagenleitner
  • 10,967
  • 1
  • 40
  • 39
40

The simplest one got to be:

def html = "http://google.com".toURL().text
John
  • 880
  • 7
  • 11
  • Brillient idea. what can I do if we need add proxy server name and port? – Heinz Jul 10 '17 at 20:57
  • proxy settings are controlled by the containing JVM as described [in the oracle documentation](https://docs.oracle.com/javase/8/docs/technotes/guides/net/proxies.html). – Matias Bjarland May 22 '18 at 14:06
31

You can take advantage of Groovy features like with(), improvements to URLConnection, and simplified getters/setters:

GET:

String getResult = new URL('http://mytestsite/bloop').text

POST:

String postResult
((HttpURLConnection)new URL('http://mytestsite/bloop').openConnection()).with({
    requestMethod = 'POST'
    doOutput = true
    setRequestProperty('Content-Type', '...') // Set your content type.
    outputStream.withPrintWriter({printWriter ->
        printWriter.write('...') // Your post data. Could also use withWriter() if you don't want to write a String.
    })
    // Can check 'responseCode' here if you like.
    postResult = inputStream.text // Using 'inputStream.text' because 'content' will throw an exception when empty.
})

Note, the POST will start when you try to read a value from the HttpURLConnection, such as responseCode, inputStream.text, or getHeaderField('...').

Daniel
  • 8,655
  • 5
  • 60
  • 87
  • 6
    Voted up for the 'note' that was the key. Thanks – xbmono Dec 11 '18 at 07:15
  • 3
    This looks very simple. What's with exception handling and ressource handling? Is there no `close()` and `disconnect()` necessary for the open connection? Is there a simple way to pass the content of a file through the http post outputstream? – CodingSamples Jan 20 '20 at 09:49
14

HTTPBuilder is it. Very easy to use.

import groovyx.net.http.HTTPBuilder

def http = new HTTPBuilder('https://google.com')
def html = http.get(path : '/search', query : [q:'waffles'])

It is especially useful if you need error handling and generally more functionality than just fetching content with GET.

Audrius Meškauskas
  • 20,936
  • 12
  • 75
  • 93
Dakota Brown
  • 730
  • 7
  • 20
  • Thanks @Dakota Brown - and can you confirm I don't need to import anything? – smeeb Sep 05 '14 at 19:55
  • 1
    That's the downside, you'll need the jar: http://groovy.codehaus.org/modules/http-builder/download.html. Nothing in groovy core for it. – Dakota Brown Sep 05 '14 at 19:57
  • Thanks @Dakota Brown - please see my comment underneath Will P's answer - I have the same question for you – smeeb Sep 05 '14 at 20:07
  • http://grails.org/plugin/rest will allow you to use HTTP Builder in GRAILS project – Dakota Brown Sep 05 '14 at 20:20
  • 7
    I downvoted because in 2020 this isn't working well. [http-builder](https://mvnrepository.com/artifact/org.codehaus.groovy.modules.http-builder/http-builder/0.7.1) hasn't been updated since 2014, and it uses a [JSON library](https://mvnrepository.com/artifact/net.sf.json-lib/json-lib/2.4) that hasn't been updated since 2010 and isn't actually on Maven central anymore (try downloading the JAR: you'll get a 404). – DavidS Nov 06 '20 at 18:44
1

I don't think http-builder is a Groovy module, but rather an external API on top of apache http-client so you do need to import classes and download a bunch of APIs. You are better using Gradle or @Grab to download the jar and dependencies:

@Grab(group='org.codehaus.groovy.modules.http-builder', module='http-builder', version='0.7.1' )
import groovyx.net.http.*
import static groovyx.net.http.ContentType.*
import static groovyx.net.http.Method.*

Note: since the CodeHaus site went down, you can find the JAR at (https://mvnrepository.com/artifact/org.codehaus.groovy.modules.http-builder/http-builder)

MarkHu
  • 1,694
  • 16
  • 29
Will
  • 14,348
  • 1
  • 42
  • 44
  • I don't know grails enough to answer and i don't think it belongs to the view, neither. You'd probably better downloading the dependencies or using `URL` as per @John's answer – Will Sep 05 '14 at 22:48
  • 1
    @smeeb the `@Grab` would be added in the `grails-app/conf/BuildConfig.groovy`. Then it would be working within controllers, services, ... -- but please don't add such code to the view. – cfrick Sep 06 '14 at 14:06
-2
import groovyx.net.http.HTTPBuilder;

public class HttpclassgetrRoles {
     static void main(String[] args){
         def baseUrl = new URL('http://test.city.com/api/Cirtxyz/GetUser')

         HttpURLConnection connection = (HttpURLConnection) baseUrl.openConnection();
         connection.addRequestProperty("Accept", "application/json")
         connection.with {
           doOutput = true
           requestMethod = 'GET'
           println content.text
         }

     }
}
SQA
  • 39
  • 11