Karate ApacheHttpClient Response is failing with error com.intuit.karate - Runtimejava.io.IOException: Attempted read from closed stream - rest

Reference: java.io.IOException: Attempted read from closed stream
Reference: https://github.com/karatelabs/karate/blob/master/karate-core/src/main/java/com/intuit/karate/http/ApacheHttpClient.java
KarateCore - class file: ApacheHttpClient.java is unable to process the Response its failing at the code line
CloseableHttpClient client = clientBuilder.build();
CloseableHttpResponse httpResponse;
byte [] bytes;
try {
httpResponse = client.execute(requestBuilder.build());
HttpEntity responseEntity = httpResponse.getEntity();
if (responseEntity == null || responseEntity.getContent() == null) {
bytes = Constants.ZERO_BYTES;
} else {
**InputStream is = responseEntity.getContent();**
bytes = FileUtils.toBytes(is);
}
request.setEndTimeMillis(System.currentTimeMillis());
} catch (Exception e) {
if (e instanceof ClientProtocolException && e.getCause() != null) { // better error message
throw new RuntimeException(e.getCause());
} else {
throw new RuntimeException(e);
}
}
The Code is failing at line InputStream is = responseEntity.getContent(); when trying to read from a closed stream. The exception message displayed
Error com.intuit.karate - Runtimejava.io.IOException: Attempted read from closed stream.
May be the InputStream need to updated.
I am able read the Http Response content using below code
BufferedReader br = new BufferedReader(
new InputStreamReader((httpResponse.getEntity().getContent())));
String output;
while ((output = br.readLine()) != null){
output = br,readLine();
System.out.println(output);
}
Also the able to read the response using EntityUtils as a string content
String content = EntityUtils.toString(responseEntity);
System.out.println(content);
Not sure if i am missing something in the feature:scenario file response or the ApacheHttpClient.java file need to updated to read InputStream and then convert to bytes.
Feature: Hello
Scenario: Rest API Post
Given url 'some url path'
And header Content-Type = 'application/json'
And request { username: 'abc', password: 'pwd' }
When method POST
Then status 200
And print 'Response is:', response
The expected Response is a JSON format as:
{
"accessToken": "akjdoioikf",
"expires":"2020-01-29T01:09:48Z"
}
Any suggestions, appreciated!

Related

DataFlowTemplate response does not return body

Considering the test07 stream is already created the following code snippet won't get response body in the exception stack trace.
try {
URI dataFlowUri = URI.create("http://localhost:9393");
DataFlowOperations dataFlowOperations = new DataFlowTemplate(dataFlowUri);
StreamDefinition streamDefinition = Stream.builder(dataFlowOperations)
.name("test07")
.definition("time|log")
.create();
}
catch (Exception ex){
ex.printStackTrace();
}
org.springframework.web.client.HttpClientErrorException$Conflict: 409 : [no body]
at org.springframework.web.client.HttpClientErrorException.create(HttpClientErrorException.java:125)
at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:184)
at org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:125)
at org.springframework.cloud.dataflow.rest.client.VndErrorResponseErrorHandler.handleError(VndErrorResponseErrorHandler.java:62)
at org.springframework.web.client.ResponseErrorHandler.handleError(ResponseErrorHandler.java:63)
at org.springframework.web.client.RestTemplate.handleResponse(RestTemplate.java:782)
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:740)
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:674)
at org.springframework.web.client.RestTemplate.postForObject(RestTemplate.java:418)
at org.springframework.cloud.dataflow.rest.client.StreamTemplate.createStream(StreamTemplate.java:121)
at org.springframework.cloud.dataflow.rest.client.dsl.StreamDefinition.(StreamDefinition.java:60)
at org.springframework.cloud.dataflow.rest.client.dsl.Stream$StreamDefinitionBuilder.create(Stream.java:400)
on other hand when Post request this directly
http://localhost:9393/streams/definitions?name=test07&definition=time%20%7C%20log&description=test07
the response as follow with status code 409
[
{
"logref": "DuplicateStreamDefinitionException",
"message": "Cannot create stream test07 because another one has already been created with the same name"
}
]
I want to get response body when exception occur
so anyone can help if I'm missing something here?
I had to override the default rest template to get the response body as desired.
ClientHttpRequestFactory factory = new BufferingClientHttpRequestFactory(new SimpleClientHttpRequestFactory());
RestTemplate restTemplate = new RestTemplate(factory);
URI dataFlowUri = URI.create("http://localhost:9393");
DataFlowOperations dataFlowOperations = new DataFlowTemplate(dataFlowUri, restTemplate);
StreamDefinition streamDefinition = Stream.builder(dataFlowOperations)
.name("test07")
.definition("time|log")
.create();
thanks

Resteasy client not working from office, but working from home

I am using RestEasy client api, to make call to some internal api, but when I run the code from my home I am able to get the response without any timeout exception. But when I run from office getting timeout execution, am I missing any configurations?
I/O exception (java.net.ConnectException) caught when processing request: Operation timed out
Below the code am using:
ClientRequest request = new ClientRequest(
"https://example.com/v2");
request.queryParameter("name", "jhon");
request.accept("application/json");
ClientResponse<String> response = request.get(String.class);
if(response.getStatus() == 404){
System.out.println(response.getEntity());
System.out.println(response.getStatus());
}
BufferedReader br = new BufferedReader(new InputStreamReader(
new ByteArrayInputStream(response.getEntity().getBytes())));
String output;
System.out.println("Output from Server .... \n");
while ((output = br.readLine()) != null) {
System.out.println(output);
JSONObject d = new JSONObject(output);
JSONObject sd = d.getJSONObject("Error");
System.out.println(sd.get("Detail"));
}

Wicket WebResponse Attachment Header with UTF-8 charackers?

In wicket project I use request handler for file downloading. Everything is works good until I have file with non standard encoding like utf-8.
I use this code for generate response
#Override
public void respond(IRequestCycle requestCycle)
{
WebResponse response = (WebResponse) requestCycle.getResponse();
response.setAttachmentHeader(briefcaseDocument.getName());
response.setContentType(briefcaseDocument.getMimeType());
response.setContentLength(briefcaseDocument.getSize());
InputStream inputStream = null;
OutputStream outputStream = null;
try
{
inputStream = briefcaseDocument.getInputStream();
outputStream = response.getOutputStream();
IOUtils.copyLarge(inputStream, outputStream);
}
catch (Exception e)
{
throw new RuntimeException("unable to push file content", e);
}
finally
{
IOUtils.closeQuietly(inputStream);
IOUtils.closeQuietly(outputStream);
}
}
but if document has special characketrs I get empty file name. For example:
ćććć is:
Content-Disposition attachment; filename=" ";
ćwiek is:
Content-Disposition attachment; filename=" wiek";
I read this stack topic and change code like this:
String fileName = briefcaseDocument.getName();
String encoded = URLEncoder
.encode(briefcaseDocument.getName(), "UTF-8");
response.setHeader("Content-Disposition","attachment" +
((!Strings.isEmpty(fileName)) ? ("; filename=\"" + fileName + "\"; filename*=UTF-8''"+encoded) : "" ));
and then I get as result:
Content-Disposition attachment; filename=" "; filename*=UTF-8''%C4%87%C5%BC
and file name present good, but I don't feel good with this solution ;) How to make wicket set file name properly?
According to http://greenbytes.de/tech/tc2231/ this is the proper way.
Since 7.0.0-M1 (https://issues.apache.org/jira/browse/WICKET-4934) Wicket does this automatically for you.

Can't upload file to Google Drive from service account

I am trying to upload a file to google drive using google service account.
Driver Service
public static Drive getDriveService(String secretKeyFile) throws GeneralSecurityException,
IOException, URISyntaxException {
HttpTransport httpTransport = new NetHttpTransport();
JacksonFactory jsonFactory = new JacksonFactory();
GoogleCredential credential = new GoogleCredential.Builder()
.setTransport(httpTransport)
.setJsonFactory(jsonFactory)
.setServiceAccountId(SERVICE_ACCOUNT_EMAIL)
.setServiceAccountScopes(DriveScopes.DRIVE)
.setServiceAccountPrivateKeyFromP12File(
new java.io.File(secretKeyFile))
.build();
Drive service = new Drive.Builder(httpTransport, jsonFactory, null)
.setHttpRequestInitializer(credential).setApplicationName("appl name").build();
return service;
}
Insert File
private static File insertFile(Drive service, String title, String description,String mimeType, String filename) {
File body = new File();
body.setTitle(title);
body.setDescription(description);
body.setMimeType(mimeType);
java.io.File fileContent = new java.io.File(filename);
FileContent mediaContent = new FileContent(mimeType, fileContent);
try {
File file = service.files().insert(body, mediaContent).execute();
return file;
} catch (IOException e) {
System.out.println("An error occured: " + e);
return null;
}
}
Main Method
Drive service=null;
try {
String secretFile= "somedigit-privatekey.p12";
service = getDriveService(secretFile);
} catch (URISyntaxException ex) {
ex.printStackTrace();
}
File insertFile = insertFile(service, "test title", "File description", "text/plain", "c:\\test.txt");
List list = service.files().list();
System.out.println("Files Id : "+insertFile.getId());
System.out.println("Count Files : "+list.size());
Now, my questions is :
How and where can i check that file was uploaded?
Why it returns the file ID but list.size() is zero.
It returns the download link also but when i paste that link in
browser it doesn't download any file.
You are creating a listing request but not executing it. Use execute method to make the request:
service.files().list().execute();
If you paste the download link into the browser, it will respond with 401, because your download request should also contain a valid Authorization header. Use the following snippet to download the file programmatically.
HttpResponse resp = service.getRequestFactory().buildGetRequest(new GenericUrl(file.getDownloadUrl())).execute();
InputStream stream = resp.getContent();
stream is an input stream for the file content.
Or add an Authorization: Bearer <access token> to the request you're making elsewhere.

Binary File Download using socket connection in Java ME

I am trying to download a pdf file on my mobile (using Java ME) using SocketConnection Api. The idea is to send the server a HTTP GET request, and it replies back with the data for pdf file. However, the problem I am facing is that the server initially replies back with string data (the HTTP Headers), and then the binary data. I just want to store the binary data (the pdf file).
I have written this code so far, and it works perfectly fine as far as the server replies back with string data. However, when it replies back with binary data, this code still tries to store everything as string, correctly storing the initially returned HTTP Headers (not required) and then garbled bits corresponding to the binary data of my PDF file.
public void FileDownload() {
try {
sc = (SocketConnection) Connector.open("socket://" + hostname + ":" + port);
OutputStream os = sc.openOutputStream();
os.write(("GET " + link_to_file_to_be_downloaded + " HTTP/1.0\r\n").getBytes("UTF-8"));
os.write(("HOST: " + hostname + "\r\n").getBytes("UTF-8"));
os.write(("\r\n").getBytes("UTF-8"));
os.flush();
os.close();
String url = "file:///E:/Data/" + "binary_data.pdf";
FileConnection fconn = (FileConnection) Connector.open(url, Connector.READ_WRITE);
if (!fconn.exists()) {
fconn.create();
}
OutputStream ops = fconn.openOutputStream();
byte data = 0;
in = sc.openInputStream();
data = (byte) in.read();
while (data != -1) {
ops.write(data);
data = (byte) in.read();
}
ops.flush();
ops.close();
fconn.close();
} catch (IOException ex) {
parent_class.main_form.append("Exception occured while "
+ "downloading file: " + ex.toString() + "\n");
} finally {
if (in != null) {
try {
in.close();
} catch (IOException ex) {
parent_class.main_form.append("Exception occured while "
+ "downloading file: " + ex.toString() + "\n");
}
}
}
}
This is what gets stored in the file "binary_data.pdf" using this code -
HTTP/1.1 200 OK
Date: Sun, 25 Mar 2012 07:03:10 GMT
Server: Apache/2.2.14 (Ubuntu)
Last-Modified: Tue, 20 Mar 2012 22:00:45 GMT
ETag: "420050-12bad-4bbb3ce85fd21"
Accept-Ranges: bytes
Content-Length: 76717
Content-Type: application/pdf
Via: 1.0 www.XXX.XXX.org
Connection: close
%PDF-1.4
%????
3 0 obj <<
/Length 4077
/Filter /FlateDecode
>>
stream
x??ZYs?6~????9U.?#??Udg?M*qYJ???T-4?fq? #Z????<FT?}
lt7??n???_???4?s???????"
3????<???^?V?z??M?z??m?^????V???o??S'm6?????.??/Sx??Y?av?MB?*b^?f??/?IO??B??q??/?(??aT?a?##??,?%???Z8? ?]??-?\?]??????nw?2?;?????Z?;?[}??????&J=ml??-??V?|??:??"?(?Gf??D??~?QW?U?Z???cP?b???QX
(This operation might be simpler using the high level HttpConnection api, but I wish to understand how everything works at the most basic level, and hence I am using the SocketConnection api instead.)
In short, what I wish my app to do is simply interpret the data replied by the server correctly, either as string or binary, and then accordingly store the binary file (possibly discarding the string HTTP headers).
I found the solution. Below is the working code.
I am first storing the header response as a string. Headers are terminated by \r\n\r\n, (so, read in bytes upto these characters). Later am storing the (possibly) binary data in a file separately.
public String FileDownloadNonPersistently() {
String server_reply = new String();
try {
sc = (SocketConnection) Connector.open("socket://" + hostname + ":" + port);
os = sc.openOutputStream();
os.write(("GET " + link_to_file_to_be_downloaded +
" HTTP/1.0\r\n").getBytes("UTF-8"));
os.write(("HOST: " + hostname + "\r\n").getBytes("UTF-8"));
os.write(("\r\n").getBytes("UTF-8"));
os.flush();
os.close();
in = sc.openInputStream();
// 1. Read the response header from server separately beforehand.
byte data;
String temp_char = "";
while (!"\r\n\r\n".equals(temp_char)) {
data = (byte) in.read();
server_reply += String.valueOf((char) data);
if (((char) data) == '\r' || ((char) data) == '\n') {
temp_char += String.valueOf((char) data);
} else {
temp_char = "";
}
}
// 2. Recieving the actual data, be it text or binary
current = 0;
mybytearray = new byte[filesize];
bytesRead = in.read(mybytearray,0,mybytearray.length);
current = bytesRead;
do {
bytesRead = in.read(mybytearray, current,
(mybytearray.length-current));
if(bytesRead >= 0) current += bytesRead;
} while(bytesRead > -1);
// Store recieved data to file, if set true from options
if (tcp_save_downloaded_file == true) {
// decide an appropriate file name acc. to download link
String url = "file:///E:/Data/" + "tcp_downloaded_file.pdf";
FileConnection fconn = (FileConnection)
Connector.open(url, Connector.READ_WRITE);
if (!fconn.exists()) { // XXX. what if file already present? overwrite or append mode?
fconn.create();
}
OutputStream ops = fconn.openOutputStream();
ops.write(mybytearray, 0 , current);
ops.flush();
ops.close();
}
} catch (Exception ex) {
parent_class.main_form.append("Exception occured while "
+ "downloading file: " + ex.toString() + "\n\n");
} finally {
if (in != null) {
try {
in.close();
} catch (IOException ex) {
parent_class.main_form.append("Exception occured while "
+ "closing inputstream "
+ "after downloading file: " + ex.toString() + "\n\n");
}
}
// XXX. see if you need to close the OutputStreams and
// SocketConnection as well.
return server_reply;
}
}
The first 10 lines are the HTTP message headers. For more information on them please go to https://www.rfc-editor.org/rfc/rfc2616#page-31.
The blank line identifies where the body starts.
You can start saving the pdf content from line 12 onwards, but you should do it using a different read method.
Instead of
data = (byte) in.read();
while (data != -1) {
ops.write(data);
data = (byte) in.read();
}
please try
byte buff[] = new byte[1024];
int len = in.read(buff);
while (len > 0) {
ops.write(buff, 0, len);
len = in.read(buff);
}