Having trouble recreating a cURL command in a Spring RestTemplate Using Headers - spring

Here's the curl command I'm trying to recreate :
curl https://bannana-pajamas.com/services/data/v20.0/query/?q=BananaQuery -H 'Authorization: Bearer Banana_Token'
This curl command works just fine in my terminal and returns a json file.
Here's my attempt at recreating it in a Spring Rest Template:
//Create a rest template
RestTemplate rest = new RestTemplate();
System.out.println("This here is the token "+Banana_Token);
//Create the headers
HttpHeaders headers = new HttpHeaders();
headers.set("Authorization","Bearer "+Banana_Token);
HttpEntity<String> entity = new HttpEntity<>(headers);
//Create the url
String url = "https://bannana-pajamas.com/services/data/v20.0/query/?q=BananaQuery";
String response;
try{
response = rest.exchange(url, HttpMethod.GET, entity, String.class).toString();
}catch(Exception error){
System.out.println("This still ain't working bro. Imma make this null till you get stuff right");
response = null;
}
return response;
When I run this, I get the following error:
org.springframework.web.client.HttpClientErrorException: 400 Bad Request
I've tried several of the similar answers on this site, but I keep getting that error. I probably missing something very minor.
Anybody have any ideas?
Thanks!

Related

Writing Wrapper for FileUpload in Spring boot : File not Present

Use Case
I need to write a wrapper for a FileUpload API, which takes Files from UI, and upload those to remote API. What I have chalked out so far:
Made a Controller which takes File and Content body as Request part, then I try to upload them to remote API, code snippets follow:
Controller Endpoint
ResponseEntity uploadFiles(#RequestPart("files") MultipartFile[] files, #RequestPart("someData") Metadata fileMetadata)
File Upload Code
byte[][] fileArray = Arrays.stream(files).map(multipartFile -> {
try {
return multipartFile.getBytes();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}).toArray(byte[][]::new);
//add file
LinkedMultiValueMap<String, Object> params = new LinkedMultiValueMap<>();
configuration.getDocumentCategory());
params.add(DocStorageConstants.FILE, fileArray);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
HttpEntity<LinkedMultiValueMap<String, Object>> requestEntity = new HttpEntity<>(params, headers);
ResponseEntity<FileUploadResponse> responseEntity = restTemplate.postForEntity(configuration.getUploadEndpoint(), requestEntity, FileUploadResponse.class);
The remote API returns response as if Files never reached this API, what I need to do to avoid this? I might try writing file to a temporary file and then upload that file to remote endpoint, not sure if that is a clean approach. Thanks in advance for any suggestions!
[Update]: The cURL that I am trying to form is below:
curl --location --request POST 'http://<host>:<port>/file-endpoint' \
--header 'X-Api-Client:<api-key>' \
--header 'x-service-id: <service-id>' \
--form 'file=#"/aggregate.csv"' \
--form 'uploadRequest="{\"bn\":\"NFA\",\"dc\":\"generalDocs\",
\"tags\":[\"test\", \"test2\"]
}"'
Following snippet worked
Arrays.stream(files).forEach(multipartFile -> params.add(DocStorageConstants.FILE, multipartFile.getResource()));

How to turn this POST cURL request into a java code

I have the following cURL request that I want to turn into java code to execute it with spring.
I use it to upload a file, the cURL request works correctly.
curl "https://mywebsite.service-now.com/api/now/attachment/file?table_name=incident&table_sys_id=fa4922f6db3ea30085a0f7871d961999&file_name=test.zip" --request POST --header "Accept:application/json" --header "Authorization:Basic cmVhbHRlc3QyOmJwb3N0QDEyMw==" --header "Content-Type: application/zip" -F "uploadFile=#test.zip"
I will use the following API:
https://docs.servicenow.com/bundle/geneva-servicenow-platform/page/integrate/inbound_rest/reference/r_AttachmentAPI-POST.html
I made a little research and found out that I have to use restTemplate to use 3rd party API.
I also wrote this:
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.TEXT_PLAIN);
headers.add("Authorization", "Basic " + encodePassword());
return headers;
(I made the encodePassword method, that is correct. )
I tried a lot of other stuff but it doesn't work
You have to set the content-type header value to MediaType.MULTIPART_FORM_DATA. When this header is set, RestTemplate automatically marshals the file data along with some metadata.
//Headers
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
//parameter values
// the getTestFile( ) method generates a file on the fly and returns a FileSystemResource
MultiValueMap<String, Object> map= new LinkedMultiValueMap<>();
map.add("file", getTestFile();
...
//create request
HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<MultiValueMap<String, String>>(map, headers);
ResponseEntity<String> response = restTemplate.postForEntity( url, request , String.class );

Invalid mimetype exception in Spring boot rest call

I am new to both Spring boot and rest calls.
I am trying to consume a rest service and I do not have any information about that rest API except URL. When I hit that URL from a browser I am getting a response as {key:value}. So, I assumed that it is a JSON response.
I am consuming it in spring boot as follows
restTemplate.getForObject(url, String.class) .
This is giving Invalid mime type "content-type: text/plain; charset=ISO-8859-1": Invalid token character ':' in token "content-type: text"
I assume that this error is because response content type is set to text/plain but it is returning JSON format.
EDIT:
Tried this way but did not work.
HttpHeaders headers = new HttpHeaders();
headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
HttpEntity<String> entity = new HttpEntity<String>("parameters",headers);
ResponseEntity<String> result = restTemplate.exchange(url,HttpMethod.GET,
entity, String.class);
How to handle and solve it?
You might want to read about the request headers your REST API needs. Content-Type header specifies the media type of the request you're sending to the server. Because you're just getting data from the server you should set the Accept header to the kind of response you want i.e., Accept: application/json.
Unfortunately, you can't set headers using getForObject(). You could try this:
URL url = new URL("Enter the URL of the REST endpoint");
con = (HttpURLConnection) url.openConnection();
con.setRequestMethod("GET");
con.setRequestProperty("Accept", "application/json");
if (con.getResponseCode() == HttpURLConnection.HTTP_OK) {
BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
StringBuffer content = new StringBuffer();
String inputLine;
while ((inputLine = in.readLine()) != null) {
content.append(inputLine);
}
in.close();
}

RestTemplate Equivalent of cURL PUT

I can access an API with that cURL command:
curl -X PUT -H 'Content-type:application/json' --data-binary '["remaro"]' "http://localhost:4352/mypath"
I want to make it over Spring RestTemplate. My data is stored as String. I tried that but my server returns 400 bad request:
HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<String> entity = new HttpEntity<>("\"" + dataVariable + "\"", headers);
restTemplate.put(http://localhost:4352/mypath, entity);
I've also send my variable as:
String dataVariable = "\"remaro\"";
but didn't work. I still get 400 error.
Use RestTemplate.exchange
Look at my example and change accordingly
String url = BASE_URI + "/update/{clusterId}";
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
ClusterDTO cluster = new ClusterDTO();
cluster.setClusterId(1L);
cluster.setClusterName("ClusterAV");
..........
HttpEntity<ClusterDTO> entity = new HttpEntity<ClusterDTO>(cluster,headers);
ResponseEntity<ClusterDTO> responseEntity = restTemplate.exchange(url, HttpMethod.PUT, entity, ClusterDTO.class,1L);
I've just send it as:
"[\"" + dataVariable + "\"]"
and worked.

ALM 12 REST using SpringFramework RestTemplate: "401 QCSession cookie missing"

In ALM 12 we have to explicity call "qcbin/rest/site-session" to get session.
When I GET call "/qcbin/rest/site-session" I receive the following:
"Set-Cookie=[BIGipServerALMAST330P-QC=rd100o00000000000000000000ffff0fe0dd74o8080; path=/, ]""
I extract the cookie as described here:
HP ALM 12 REST not returning QCSession cookie.
Instead of this RestConnector, our project is using RestTemplate from SpringFramework, so I did:
private HashMap getQCSession() throws Exception {
URL url = new URL("https://almxxxx.saas.hp.com/qcbin/rest/site-session?login-form-required=y");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Type", "application/xml");
conn.setRequestProperty("Accept", "application/xml");
conn.connect();
HashMap cookies = updateCookies(conn);
return cookies;
}
public HashMap updateCookies(HttpURLConnection conn) {
String cookie2 = conn.getHeaderField("Set-Cookie");
int equalIndex = cookie2.indexOf('=');
int semicolonIndex = cookie2.indexOf(';');
String cookieKey = cookie2.substring(0, equalIndex);
String cookieValue = cookie2.substring(equalIndex + 1, semicolonIndex);
HashMap cookies = new HashMap();
cookies.put(cookieKey, cookieValue);
System.out.println(cookies.toString());
return cookies;
}
To send the cookie in the GET call using the RestTemplate I followed the instructions from http://springinpractice.com/2012/04/08/sending-cookies-with-resttemplate/, so I did:
public <U extends Object> ResponseEntity<U> getFromURL(URI url, Class<U> responseBodyClass) throws Exception {
logger.info("GET na URL: {} esperando classe: {} no response", url, responseBodyClass);
HashMap cookie = this.getQCSession();
HttpHeaders requestHeaders = new HttpHeaders();
requestHeaders.add("Cookie", this.getQCSession().toString());
this.httpEntity = new HttpEntity(null, requestHeaders);
return super.exchange(url, HttpMethod.GET, this.httpEntity, responseBodyClass);
}
The requestHeaders content added to the HttpEntity (SpringFramework) is:
{Cookie=[{BIGipServerALMAST330P-QC=rd100o00000000000000000000ffff0fe0dd74o8080}]}
However I'm still getting "401 QCSession cookie missing".
I already tried to send in the GET call the JSESSIONID, with no success as well.
I appreciate any help.
Any clue?
I ran into this. As of ALM12 you need to create a session also.
I POST some XML or JSON to here "/authentication-point/alm-authenticate" to authenticate
Then collect the Set-Cookie header
I then POST to "/rest/site-session" with the cookie from the previous response.
I collect the session cookies from that response to use in my subsequent requests.
Hope that helps
I don't know, if it can help you but you are sending it with query param for UI authentication.
"POST .../rest/site-session?login-form-required=y"
I would suggest to POST it without query param
"POST .../rest/site-session"
Also the order of actions you should do before asking for QCSession token is:
1.Check whether you are authenticated
"GET .../rest/is-authenticated"
2.If not you'll get reference where to authenticate: WWW-Authenticate: LWSSO realm=".../authentication-point"
3.Send basic auth header to authentication point with added alm-authenticate at the end. Which returns you LWSSO_COOKIE_KEY.
"POST .../authentication-point/alm-authenticate"
Authentication: Basic BASE64{username:password}
4.Then you'll need to POST that LWSSO_COOKIE_KEY to site-session and ALM will return you QCSession key.
"POST .../rest/site-session"
"Cookie: LWSSO_COOKIE_KEY={cookie}; Path=/"
Hopefully I was able to help you.
If you still have problems, feel free to contact me.

Resources