Groovy script for Jenkins: execute HTTP request without 3rd party libraries - rest

I need to create a Groovy post build script in Jenkins and I need to make a request without using any 3rd party libraries as those can't be referenced from Jenkins.
I tried something like this:
def connection = new URL( "https://query.yahooapis.com/v1/public/yql?q=" +
URLEncoder.encode(
"select wind from weather.forecast where woeid in " + "(select woeid from geo.places(1) where text='chicago, il')",
'UTF-8' ) )
.openConnection() as HttpURLConnection
// set some headers
connection.setRequestProperty( 'User-Agent', 'groovy-2.4.4' )
connection.setRequestProperty( 'Accept', 'application/json' )
// get the response code - automatically sends the request
println connection.responseCode + ": " + connection.inputStream.text
but I also need to pass a JSON in the POST request and I'm not sure how I can do that. Any suggestion appreciated.

Executing POST request is pretty similar to a GET one, for example:
import groovy.json.JsonSlurper
// POST example
try {
def body = '{"id": 120}'
def http = new URL("http://localhost:8080/your/target/url").openConnection() as HttpURLConnection
http.setRequestMethod('POST')
http.setDoOutput(true)
http.setRequestProperty("Accept", 'application/json')
http.setRequestProperty("Content-Type", 'application/json')
http.outputStream.write(body.getBytes("UTF-8"))
http.connect()
def response = [:]
if (http.responseCode == 200) {
response = new JsonSlurper().parseText(http.inputStream.getText('UTF-8'))
} else {
response = new JsonSlurper().parseText(http.errorStream.getText('UTF-8'))
}
println "response: ${response}"
} catch (Exception e) {
// handle exception, e.g. Host unreachable, timeout etc.
}
There are two main differences comparing to GET request example:
You have to set HTTP method to POST
http.setRequestMethod('POST')
You write your POST body to outputStream:
http.outputStream.write(body.getBytes("UTF-8"))
where body might be a JSON represented as string:
def body = '{"id": 120}'
Eventually it's good practice to check what HTTP status code returned: in case of e.g. HTTP 200 OK you will get your response from inputStream while in case of any error like 404, 500 etc. you will get your error response body from errorStream.

Related

How to check for proper format in my API response

Currently running tests for my REST API which:
takes an endpoint from the user
using that endpoint, grabs info from a server
sends it to another server to be translated
then proceeds to jsonify the data.
I've written a series of automated tests running and I cannot get one to pass - the test that actually identifies the content of the response. I've tried including several variations of what the test is expecting but I feel it's the actual implementation that's the issue. Here's the expected API response from the client request:
{ "name": "random_character", "description": "Translated description of requested character is output here" }
Here is the testing class inside my test_main.py:
class Test_functions(unittest.TestCase):
# checking if response of 200 is returned
def test_healthcheck_PokeAPI(self):
manualtest = app.test_client(self)
response = manualtest.get("/pokemon/")
status_code = response.status_code
self.assertEqual(status_code, 200)
# the status code should be a redirect i.e. 308; so I made a separate test for this
def test_healthcheck_ShakesprAPI(self):
manualtest = app.test_client(self)
response = manualtest.get("/pokemon/charizard")
self.assertEqual(response.status_code, 308)
def test_response_content(self):
manualtest = app.test_client(self)
response = manualtest.get("/pokemon/charizard")
self.assertEqual(response.content_type,
'application/json') <<<< this test is failing
def test_trans_shakespeare_response(self):
manualtest = app.test_client(self)
response = manualtest.get("/pokemon/charizard")
self.assertFalse(b"doth" in response.data)
Traceback:
AssertionError: 'text/html; charset=utf-8' != 'application/json' - text/html; charset=utf-8 + application/json
Any help would be greatly appreciated

RestClient.post response generating "error groovyx.net.http.ResponseParseException : OK"

I' am using groovy to consume a POST Rest api : here is my code :
import groovyx.net.http.RESTClient
#Grab (group = 'org.codehaus.groovy.modules.http-builder', module = 'http-builder', version = '0.7.1')
def url = "https://poc-ser.tst.be/"
def client = new RESTClient(url)
client.ignoreSSLIssues()
client.auth.basic(login,pswd)
client.post(
path: "osidoc/api/rest/production/documents?id=46",
contentType:'application/json',
headers: [Accept: 'application/json' , Authorization: 'Authorization']
)
But I always get error " error groovyx.net.http.ResponseParseException: OK caused by: groovy.json.JsonException: Unable to determine the current character, " Knowing that the response should be "application/msword" type (i.e : the response should be a word doc)
EDIT
I tried to change the Accept to "application/octet-stream' but it showed me an other error "406Invalid Accept header. Only XML and JSON are supported.`"

SoapUI POST to REST with attached file in Groovy

I'm trying to POST to a Sharepoint REST service an attached file with SoapUI Pro. I've tried the examples at: https://support.smartbear.com/readyapi/docs/requests/attachment/rest.html
But with no luck.
It should work with POST with byte-array as body. But how do I do that in SoapUI and Groovy?
In the tool Insomnia it works with "Binary File".
I add these headers:
Accept: application/json;odata=verbose
Content-Type: application/octet-stream
Media type = multipart/mixed and Post QueryString
But the file won't be uploaded to SharePoint.
PowerShell code that works:
$headers = #{
'X-RequestDigest' = 'xxxxxxxxxxxxxxxxxxxxxxx'
'Accept' = 'application/json;odata=verbose'
}
$document = [System.IO.File]::ReadAllBytes('C:\temp\myFile.docx')
Invoke-RestMethod -Method Post -UseDefaultCredentials -Uri "https://xxxx.xxx/add(url='myFile.docx',%20overwrite=true)" -Headers $headers -Body $document
I tried to go through this as well a while ago but I found it easier to use HTTP to do this.
You may try to see if it fits your requirements
My groovy script for attachment :
// upload source file before import
// get uploading request
def source_file = context.expand( '${#TestCase#source_file_path}' )
log.info "upload $source_file"
def aPIToolsTestSuite = context.expand( '${#Project#APIToolsTestSuite}' ) // the test suite that contains the test case with the HTTP request
tc_name = "import - upload resource files"
request = testRunner.testCase.testSuite.project.testSuites[aPIToolsTestSuite].testCases[tc_name].getTestStepByName("Request 1").testRequest
// clear request from any existing attachment
for (a in request.attachments)
{
request.removeAttachment(a)
}
// attach file to upload
def file = new File(source_file)
if (file == null)
{
log.error "bad file name : $source_file"
}
else
{
// attach file and set properties
try{
def attachment = request.attachFile (file, true)
attachment.contentType = "application/octet-stream"
attachment.setPart("upload file '$source_file'")
}
catch (Exception e){
log.error "file ${file.name} : exception $e"
}
}
// now upload file - launch the request
def jsonSlurper = new groovy.json.JsonSlurper()
def TC;
def async = false
TC = testRunner.testCase.testSuite.project.getTestSuiteByName(aPIToolsTestSuite).getTestCaseByName(tc_name)
result = TC.run (context.getProperties(), async)
if (String.valueOf( result.status ) != "PASS")
{
msg = "unexpected failure during $tc_name when uploading $source_file"
testRunner.fail(msg)
log.error msg
}
else
{
// this part is for further processing
// file uploaded, go through the import and properties backup process
resource_to_import = TC.getPropertyValue("testResponse").split('\"')[1]
// file uploaded, go through the import and properties backup process
testRunner.testCase.setPropertyValue("resource_id", resource_to_import)
}
And the HTTP request contained in the test case APIToolsTestSuite/import - upload resource files
first step : get endpoint
def env = testRunner.testCase.testSuite.project.activeEnvironment
rest = env.getRestServiceAt(0)
config = rest.getEndpoint().config
endpoint = new XmlSlurper().parseText(config.toString())
testRunner.testCase.setPropertyValue("endpoint", endpoint.toString())
second step, HTTP request:
POST
with Request tab parameters :
name : metadata
value : {"storageType":"FILESYSTEM","itemName":"my_source_file"}
type : QUERY
media type : multipart/form-data
Post QueryString
Headers : application/json
Good luck :)

How to make proper https request using Finagle to Telegram API

Currently i working at simple bot that will have a telegram interface. The problem is, that finagle have means to make http request, but i have no clue how to make https request.
I tried to make https request with scala-library finagle to telegram bot API:
val service: Service[http.Request, http.Response] = Http.client.withTlsWithoutValidation.newService("api.telegram.org:443")
val request = http.Request(http.Method.Get,bottoken + "/getMe")
request.host = "api.telegram.org"
val t = Await.result(service(request) onSuccess(a => a) onFailure( exc => println("Auth check failed : " + exc.toString )))
if (t.status == Status.Ok) {
println("Auth check success")
} else {
println("Auth check failed : " + t.toString + "\r\n" + t.contentString)
}
Every time i run this code it yields 400 Bad Request http response.
Http.client.withTls("api.telegram.org")
yields the same result.
What am i doing wrong?
You have to add in the Request the http protocol.
val request = http.Request(http.Method.Get, "http://yourholeHost/getMe")

HTTP4S client. How to get the exact request and response body

I am writing a small http4s client
val client = SimpleHttp1Client()
val uri = Uri.fromString(requestUrl).valueOr(throw _)
val task = POST(uri, UrlForm("username" -> userName, "password" -> password)).map{request => println("request: " + request.body)}
try {
val response = client.expect[String](task).unsafePerformSync
println("token: " + response)
response
} catch {
case e: Exception => println(e.getMessage);"BadToken"
}
The output is like
[info] Running com.researchnow.nova.shield.NovaShieldSetup
[info] Emit(Vector(ByteVector(44 bytes, 0x757365726e616d653d616268737269766173746176612670617373776f72643d41726)))
[info] Failed: unexpected HTTP status: 400 Bad Request
[info] token: BadToken
How to convert the binary request body to String? I want to see the body and headers in clear text.
I had a conversation with the http4s team on gitter and found the response. since gitter talk is not returned by google I am putting the answer here
val loggedReq = req.copy(body = request.body.observe(scalaz.stream.io.stdOutBytes))
println(loggedReq)
this prints all the headers. If we do something with the loggedReq then we get the entire body which is posted
loggedReq.as[String].run