SoapUI POST to REST with attached file in Groovy - rest

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 :)

Related

Item does not have a file (error 500) when uploading a PNG file to a portal using add item method

I am trying to setup a POST request method using the "Add Item" operation within a REST API for my portal so that the PNG images can be add and later updated. Currently my script uploads the item to the portal but when i try to download the file or share it then it opens a page saying "Item does not have a file . Error 500" I assume its something to do with how i am building the POST request. How should i send the file over the POST request so that i can later download and update the file . Here is my current code:
def add_item(username,files,type,title):
"""
Add an item to the portal
Input:
- file: path of the the file to be uploaded
- username: username of user uploads the item
Return:
- Flag with a list of messages
"""
# set request header authorization type
header = {
'Authorization': f'Bearer {token}'
}
# build url
u_rl = f"{portal}/sharing/rest/content/users/{username}/addItem"
# search for id
req = requests.post(url=u_rl, headers=header,files=files,data={ "type":type,"title":title,"f": "json"})
response = json.loads(req.text)
if 'error' in response.keys():
error = response["error"]
raise Exception(
f"Error message: {error['message']}", f"More details: {','.join(error['details'])}")
return response["success"] if 'success' in response.keys() else False
if __name__ == "__main__":
user = input("input your USERNAME: ")
password = getpass.getpass("input your PASSWORD: ")
portal = "https://cvc.portal"
token = generate_token(user, password, portal=portal)
files = {'upload_file': open(r'C:\Users\test.png','rb')}
type='Image',
title='An image'
add_item(user,files,type,title

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.`"

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

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.

Unable to upload file via REST request in GRAILS

I am trying to upload a file via REST using GRAILS
curl -X POST -H "Cache-Control: no-cache" -H "Postman-Token: d5d7aef8-3964-311b-8b64-4a7a82c52323" -H "Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW" -F "file1=myfile.jpg" -F "fname=swateek" -F "lname=jena" 'http://localhost:8081/sampleFileREST/document/upload'
Here's how my controller looks like:
class DocumentController extends RestfulController<Document> {
static responseFormats = ['json', 'xml']
def upload() {
def fileLocation="<xml>empty</xml>"
def file = request.getParameter('file1')
def f1 = request.getParameter('fname')
def f2 = "<abc>"+request.getParameter('lname')+"</abc>"
def params = "gf"
if(file.empty) {
fileLocation = "<xml>"+"File cannot be empty"+"</xml><allprm>"+params+"</allprm>"
} else {
def documentInstance = new Document()
documentInstance.filename = file.originalFilename
documentInstance.fullPath = grailsApplication.config.uploadFolder + documentInstance.filename
file.transferTo(new File(documentInstance.fullPath))
documentInstance.save()
fileLocation = "<xml>"+documentInstance.fullPath+"</xml>"
}
/* return "File uploaded to: "+documentInstance.fullPath */
render(text: fileLocation, contentType: "text/xml", encoding: "UTF-8")
}
}
I am able to access the parameters of the request, anything except the file I am sending in the request.
Unable to figure out what's wrong here.
UPDATE
I had used .getParameter() to fetch a file. That's incorrect, the correct way is as below:
request.getFile('<filename>') // without the <>
This might raise an error in IntelliJ as "Symbol Not Found" or "Cannot Resolve Method", please follow the procedure in the answer below.
Damn the IDE that I was using, IntelliJ.
Also, this piece of code while getting the file:
def file = request.getParameter('file1')
should be replaced as
def file = request.getFile('file1')
Now previously, when I was using the request.getFile() method I was getting an "Symbol Not Found" error and it was failing to execute the request.
Solution:
Open IntelliJ
Click on "File"
Find the option "Invalidate Caches/Restart" and wait for IntelliJ to come back again.
If this doesn't work, the other way is mentioned in this answer:
IntelliJ IDEA JDK configuration on Mac OS