HttpBuilder accessing secured link https - json

I am using this code for GETting a JSON object from the URL using Groovy: the URL that I use is a HTTPS URL so when I test the code I get a 403 error, after Google it I understand that I need to use a HttpBuilder SSL but I don't understand how can I do it.
the code is :
def getJson(Integer id) {
def adress = new HTTPBuilder("https://api.XXXY.com")
def path="/vls/v1/etudiants/${id}?b=my&apiKey=99990"
//Get request
adresseServeur.request(Method.GET, JSON) {
uri.path = path
headers.Accept = 'application/json'
// success response handler
response.success = { resp, json ->
retourJson = json
}
// failure response handler
response.failure = { resp ->
println "Unexpected error: ${resp.statusLine.statusCode} : ${resp.statusLine.reasonPhrase}"

Related

Get values from a JSON response in Groovy

I have a groovy script, it does an easy API call, and I am getting as response a JSON body.
How can I get, from the JSON body, a single value, and use it as a variable?
newRelease.request(GET) { req ->
requestContentType = ContentType.JSON
headers.'X-Octopus-ApiKey' = 'API-xxx'
response.success = { resp, JSON ->
return JSON
}
response.failure = { resp ->
return "Request failed with status ${resp.status}"
}
}
and this is the response
[DeploymentProcessId:deploymentprocess-Projects-370, LastReleaseVersion:null, NextVersionIncrement:0.0.41, VersioningPackageStepName:null, Packages:[], Links:[Self:/api/Spaces-1/deploymentprocesses/deploymentprocess-Projects-370/template]]
So what I am trying to extract is the NextVersionIncrement.
Any idea?

Getting raw json string or customer jackson mapper from httpbuilder-ng get request

I'm updating groovy scripts from httpbuilder to httpbuilder-ng. These scripts interact with various webservices to get messages. I'm looking to parse the responses preferably using Jackson into objects. However, I can't seem to get the raw json response like I could in httpbuilder as httpbuilder-ng auto parses into a lazymap in all cases.
The old implementation using httpbuilder allowed you to use the body.text method to get the raw json string without it being parsed into a lazymap. This could then be used with ObjectMapper in Jackson to create my POJO's. However, httpbuilder-ng doesn't seem to support this.
I have already tried the method here for getting the raw json, but the body.text method does not seem to work in version 1.03 that I'm using http://coffeaelectronica.com/blog/2016/httpbuilder-ng-demo.html.
I have also tried to add my own custom encoders to override Groovy's default creation of JSON objects without any success. It is supposedly possible as detailed in the wiki https://http-builder-ng.github.io/http-builder-ng/asciidoc/html5/. If anyone has a code snippet of how to do this it would be appreciated!
Old httpbuilder code:
def http = new HTTPBuilder("http://${proxy}.domain.ie")
http.request(GET, TEXT) {
uri.path = "/blah/plugins/blah/queues"
headers.Accept = 'application/json'
headers.'Cookie' = "token=${token}"
response.success = { resp, json ->
assert resp.status < 300
LOGGER.info("GET queues request succeeded, HTTP " + resp.status)
ObjectMapper objectMapper = new ObjectMapper()
queues = objectMapper.readValue(json, Queue[].class)
}
response.failure = { resp ->
assert resp.status >= 300
LOGGER.info("GET queues request failed, HTTP " + resp.status)
return null
}
}
new http-builder-ng code:
def http = configure {
request.uri = "http://${proxy}.domain.ie"
request.headers["Accept"] = "application/json"
request.headers["Cookie"] = "token=${token}"
request.contentType = TEXT
}
return http.get {
request.uri.path = "/blah/plugins/blah/queues"
response.success { FromServer fs, Object body ->
return body.text // doesn't work
}
response.failure {
return null
}
}
Update
Found the solution. It was to add a custom parser and a closure using the FromServer.inputstream.text method.
def text = httpBuilder.get {
request.uri.path = '/blah/plugins/blah/queues'
response.parser('application/json') { ChainedHttpConfig cfg, FromServer fs ->
String text = fs.inputStream.text
}
}

Grails: Error when fetching and parsing JSON

I have a Grails service that sends a request to the JIRA REST API and returns JSON - When I try to use JsonSlurper to parse the JSON, I get the following error:
ERROR errors.GrailsExceptionResolver - JsonException occurred when processing request: [GET] /osmDash/jira/storyComplete
Lexing failed on line: 1, column: 1, while reading 'j', no possible valid JSON value or punctuation could be recognized.
Here is the code in the controller:
def jsonFile = jiraService.fetchJQL('issuetype=Story AND status in (Resolved,Closed,Done) AND resolved>=-30d') as JSON
def jiraSlurper = new JsonSlurper()
def jiraResult = jiraSlurper.parseText('jsonFile').total
And this is what the JSON looks like when I render it in the page:
{"total":1356,"issues":[],"startAt":0,"maxResults":0}
I was looking at groovy.json.JsonSlurper parse JSON, which seems simliar, but I couldn't get this method to work. I'm looking specifically to assign the "total" value to a variable.
This is the service that is returning the JSON:
def fetchJQL(String jql, Integer maxResults = 0, def fields = null) {
jira.request(POST, JSON) { req ->
uri.path = '/rest/api/2/search'
headers.'Authorization' = authHash
body = [jql: jql, maxResults: maxResults, fields: fields]
response.success = { resp, json ->
return json
}
response.failure = { resp ->
println resp.statusLine.statusCode
println resp.statusLine
}
}

Another issue when trying to POST JSON to REST URL via HttpBuilder

I read this and several other postings on SO and elsewhere about how to send a Post call via HttpBuilder with JSON as the data content. My problem is that NONE OF THOSE SOLUTIONS are working!
My problem is only slightly different. I have existing JSON data in a file. When I attempt to send this to the REST interface with curl:
curl -X POST -u "username:password" -d #/path/to/myFile.json http://localhost:8080/path/here --header "Content-Type:application/json"
all works perfectly well. Here is where I am at (some extra code IS in there, read on):
def myFile = new File('/path/to/myFile.json')
if (!myFile.exists()) println "ERROR! Do not have JSON file!"
def convertedText = myFile.text.replaceAll('\\{', '[')
convertedText = convertedText.replaceAll('\\}', ']')
def jsonBldr = new JsonBuilder()
jsonBldr myFile.text
println jsonBldr.toString()
def myClient = new groovyx.net.http.HTTPBuilder('http://username:password#localhost:8080/my/path')
myClient.setHeaders(Accept: 'application/json')
results = myClient.request(POST, JSON) { req ->
body = [ jsonBldr.toString() ]
requestContentType = JSON
response.success = { resp, reader ->
println "SUCCESS! ${resp.statusLine}"
}
response.failure = { resp ->
println "FAILURE! ${resp.properties}"
}
}
This results in the 'failure' closure with this data:
statusLine:HTTP/1.1 400 Exception evaluating property 'id' for java.util.ArrayList, Reason: groovy.lang.MissingPropertyException: No such property: id for class: java.lang.String
FWIW, there is no "id" in my JSON anywhere. If I change the "body" line from "[ jsonBldr.toString() ]" to "[ convertedText ]" - which is why that code is up there, I get the same error. If I take out the brackets on the body, I get an error stating that the body is not data for an array (as its a Map).
Can anyone (far groovier than I) tell me what the %%$## I am doing wrong???
You need JsonSlurper instead of JsonBuilder. After which the implementation would look like:
def myFile = new File('/path/to/myFile.json')
if (!myFile.exists()) println "ERROR! Do not have JSON file!"
def bodyMap = new JsonSlurper().parseText(myFile.text)
def myClient = new groovyx.net.http.HTTPBuilder('http://username:password#localhost:8080/my/path')
modelClient.setHeaders(Accept: 'application/json')
results = myClient.request(POST, JSON) { req ->
requestContentType = JSON
body = bodyMap
response.success = { resp, reader ->
println "SUCCESS! ${resp.statusLine}"
}
response.failure = { resp ->
println "FAILURE! ${resp.properties}"
}
}
However, I am not clear what is difference between myFile and modelFile in your code.

Posting JSON data with Groovy's HTTPBuilder

I've found this doc on how to post JSON data using HttpBuilder. I'm new to this, but it is very straightforward example and easy to follow. Here is the code, assuming I had imported all required dependencies.
def http = new HTTPBuilder( 'http://example.com/handler.php' )
http.request( POST, JSON ) { req ->
body = [name:'bob', title:'construction worker']
response.success = { resp, json ->
// response handling here
}
}
Now my problem is, I'm getting an exception of
java.lang.NullPointerException
at groovyx.net.http.HTTPBuilder$RequestConfigDelegate.setBody(HTTPBuilder.java:1131)
Did I miss something? I'll greatly appreciate any help you can do.
I took a look at HttpBuilder.java:1131, and I'm guessing that the content type encoder that it retrieves in that method is null.
Most of the POST examples here set the requestContentType property in the builder, which is what it looks like the code is using to get that encoder. Try setting it like this:
import groovyx.net.http.ContentType
http.request(POST) {
uri.path = 'http://example.com/handler.php'
body = [name: 'bob', title: 'construction worker']
requestContentType = ContentType.JSON
response.success = { resp ->
println "Success! ${resp.status}"
}
response.failure = { resp ->
println "Request failed with status ${resp.status}"
}
}
I had the same problem a while ago and found a blog that noted the 'requestContentType' should be set before 'body'. Since then, I've added the comment 'Set ConentType before body or risk null pointer' in each of my httpBuilder methods.
Here's the change I would suggest for your code:
import groovyx.net.http.ContentType
http.request(POST) {
uri.path = 'http://example.com/handler.php'
// Note: Set ConentType before body or risk null pointer.
requestContentType = ContentType.JSON
body = [name: 'bob', title: 'construction worker']
response.success = { resp ->
println "Success! ${resp.status}"
}
response.failure = { resp ->
println "Request failed with status ${resp.status}"
}
}
Cheers!
If you need to execute a POST with contentType JSON and pass a complex json data, try to convert your body manually:
def attributes = [a:[b:[c:[]]], d:[]] //Complex structure
def http = new HTTPBuilder("your-url")
http.auth.basic('user', 'pass') // Optional
http.request (POST, ContentType.JSON) { req ->
uri.path = path
body = (attributes as JSON).toString()
response.success = { resp, json -> }
response.failure = { resp, json -> }
}
I found an answer in this post: POST with HTTPBuilder -> NullPointerException?
It's not the accepted answer, but it worked for me. You may need to set the content type before you specify the 'body' attribute. It seems silly to me, but there it is. You could also use the 'send contentType, [attrs]' syntax, but I found it more difficult to unit test. Hope this helps (late as it is)!
I gave up on HTTPBuilder in my Grails application (for POST at least) and used the sendHttps method offered here.
(Bear in mind that if you are using straight Groovy outside of a Grails app, the techniques for de/encoding the JSON will be different to those below)
Just replace the content-type with application/json in the following lines of sendHttps()
httpPost.setHeader("Content-Type", "text/xml")
...
reqEntity.setContentType("text/xml")
You will also be responsible for marshalling your JSON data
import grails.converters.*
def uploadContact(Contact contact){
def packet = [
person : [
first_name: contact.firstName,
last_name: contact.lastName,
email: contact.email,
company_name: contact.company
]
] as JSON //encode as JSON
def response = sendHttps(SOME_URL, packet.toString())
def json = JSON.parse(response) //decode response
// do something with json
}