Timeout exception while reading data from HttpURLConnection in Google App Engine - java

I am running an application on Google App Engine which calls a Http URL of my
web application(running on Glassfish) to read data using inputstream. Here is
my code snippet.
OutputStream os = response.getOutputStream();
URL url = new URL(Http URL);
conn = (HttpURLConnection)url.openConnection();
conn.setConnectTimeout(0);
conn.setReadTimeout(0);
conn.setRequestMethod("GET");
System.out.println("response code=" + conn.getResponseCode());
byte b[] = new byte[2048];
InputStream is = url.openStream();
int len;
while ((len=is.read(b))!=-1){
os.write(b, 0, len);
System.out.println("len=" + len);
}
But I am getting "Timeout while fetching URL:" exception.
I have tried URLFetchService too, but exception remains same
URLFetchService urlFetchService = URLFetchServiceFactory.getURLFetchService();
URL url = new URL(Http URL);
Future future = urlFetchService.fetchAsync(url);
HTTPResponse response1 = (HTTPResponse)future.get();
byte[] content = response1.getContent();
int responseCode = response1.getResponseCode();
List<HTTPHeader> headers = response1.getHeaders();
System.out.println("responseCode=" + responseCode);
Please advise how to proceed. Thanks in advance for your help.

Resolved this exception. Http URL of my web application(running on Glassfish) was an internal IP address. On attempting to read data from Google, it should be a publicly accessible IP address.

Related

Access Azure web app web service through AAD using MSI

I have an Azure webapp (App Service) running with Tomcat. I'd deployed 2 war applications. WAR-1 provides web service call which return a json files using Springboot. WAR-2 is a web application which call this web services in WAR-1. This webapp has system assigned managed identity (or MSI). In addition, this webapp has authentication on with AAD, using Express configuration.
I can access static pages in WAR-2, after authentication through AAD. Now I need to fetch data from WAR-1. I have a servlet which contains code like this:
String subscriptionId = "xxxx";
String testURL = "https://yyy.azurewebsites.net/war1/person/100";
String resourceId = "https://management.azure.com/";
AppServiceMSICredentials credentials = new AppServiceMSICredentials(AzureEnvironment.AZURE);
Azure azure = Azure.configure()
.withLogLevel(LogLevel.BODY_AND_HEADERS)
.authenticate(credentials)
.withSubscription(subscriptionId);
String token = credentials.getToken(resourceId);
HttpURLConnection conn = (HttpURLConnection) new URL(testURL).openConnection();
conn.setDoOutput(true);
conn.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
conn.setRequestMethod("GET");
conn.setRequestProperty("Authorization", "Bearer " + token);
int responseCode = conn.getResponseCode();
OutputStream os = conn.getOutputStream();
....
I do able to get a token, but the response code is 500 when I make the GET call.
So my question is ... is this the correct way to do this call ? I did found an articlehttps://dotnetdevlife.wordpress.com/2018/10/22/call-azure-ad-protected-website-using-managed-service-identity-msi/ similar to this situation but it uses .Net. I cannot find any Java equivalent of this.
I tested at my side, and here are my steps:
1. Two apps in one Azure web app.
App1: https://jackdemoapp1.azurewebsites.net/app1/
App2: https://jackdemoapp1.azurewebsites.net/app2/
2. Configure Authentication/Authorization on Azure portal.
And you can get the client ID by clicking into the details, note it down and we will use it in app2:
3. Configure managed identity on Azure portal
To simplify the test, the app1 will just return a "Hello" string.
4. Code in app2
#ResponseBody
#RequestMapping("/")
public String index() {
JSONObject json = new JSONObject();
try {
AppServiceMSICredentials credential = new AppServiceMSICredentials(AzureEnvironment.AZURE);
// As we want to get token for accessing the aad-protected app, change the
// resource to the client ID you get in step 2
String token = credential.getToken("ac07d701-6f7d-462e-8b67-5dffa1df955f");
json.put("token", token);
// The URL for app1 API
String app1 = "https://jackdemoapp1.azurewebsites.net/app1/";
HttpURLConnection conn = (HttpURLConnection) new URL(app1).openConnection();
conn.setRequestMethod("GET");
conn.setRequestProperty("Authorization", "Bearer " + token);
conn.setDoOutput(true);
conn.setDoInput(true);
// Open the connection
conn.connect();
int code = conn.getResponseCode();
if (code >= 200 && code <= 300) {
try (InputStream inputStream = conn.getInputStream();
InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
BufferedReader bufferedReader = new BufferedReader(inputStreamReader)) {
StringBuilder stringBuilder = new StringBuilder();
String line = "";
while ((line = bufferedReader.readLine()) != null) {
stringBuilder.append(line);
}
String response = stringBuilder.toString();
json.put("response", response);
}
} else {
json.put("Error", "Response Code" + conn.getResponseCode());
}
conn.disconnect();
} catch (Exception e) {
json.put("Exception", e.getStackTrace());
}
return json.toString();
}
Result

File download from url using HttpURLConnection |HTTP 400 if file name contain space

I'm trying to download the files from url(soap request) using http connection, and below is my code, while executing i'm getting http = 400, because of file Name contain space (ac abc.pdf)
String downloadFileName = "ac abc.pdf";
String saveDir = "D:/download";
String baseUrl = "abc.com/AttachmentDownload?Filename=";
URL url = new URL(baseUrl + downloadFileName);
HttpURLConnection connection = (HttpURLConnection) url
.openConnection();
connection.setReadTimeout(60 * 1000);
connection.setConnectTimeout(60 * 1000);
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "application/octet-stream");
connection.setRequestProperty("SOAPAction", url.toString());
String userCredentials = "user:pass";
connection.setRequestProperty("Authorization", userCredentials);
connection.setDoInput(true);
connection.setDoOutput(true);
int responseCode = connection.getResponseCode();
if (responseCode == HttpURLConnection.HTTP_OK) {
try (InputStream inputStream = connection.getInputStream()) {
String saveFilePath = saveDir + downloadFileName;
try (FileOutputStream outputStream = new FileOutputStream(saveFilePath)) {
int bytesRead = -1;
byte[] buffer = new byte[BUFFER_SIZE];
while ((bytesRead = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
}
}
}
while executing the above code getting the below output
responsecode400
response messageBad Request
No file to download. Server replied HTTP code: 400
let me know how can we format the url with the above situation
Spaces and some other symbols are not well tollerated in URL. You need to escape or encode them change your code
URL url = new URL(baseUrl + downloadFileName);
To:
URL url = new URL(baseUrl + URLEncoder.encode(downloadFileName, StandardCharsets.UTF_8.name());
That should resolve your problem. Besides there are Open Source libraries that resolve your issue for you. See Apache commons which is a popular solution. Another solution is MgntUtils library (version 1.5.0.2). It contains class HttpClient that allows you to do things very simple:
httpClient.sendHttpRequestForBinaryResponse(baseUrl + URLEncoder.encode(downloadFileName, StandardCharsets.UTF_8.name()", HttpClient.HttpMethod.POST);
This will return ByteBuffer that contains the response as raw bytes. The same class has method sendHttpRequest to get Textual response. Both methods throw IOException in case of failure. Here is the link to an article that explains where to get MgntUtils library as well as what utilities it has. In the article the HttpClient class is not mentioned (It is a new feature), but the library comes with well written javadoc. So look for javadoc for HttpClient class in that library.

saving file as .pdf as recieved in http response error

For my project i need to download a pdf file from google drive using java
I get my httpresponse code 200 and by using following method i store it in abc.pdf file
String url = "https://docs.google.com/uc?id="+fileid+"&export=download";
URL obj = new URL(url);
HttpURLConnection conn = (HttpURLConnection) obj.openConnection();
// optional default is GET
conn.setRequestMethod("GET");
//add request header
conn.setRequestProperty("User-Agent", USER_AGENT);
int responseCode = conn.getResponseCode();
System.out.println("\nSending 'GET' request to URL : " + url);
System.out.println("Response Code : " + responseCode);
BufferedReader in = new BufferedReader(
new InputStreamReader(conn.getInputStream()));
String inputLine;
OutputStream f0 = new FileOutputStream("C:\\Users\\Darshil\\Desktop\\abc.pdf",true);
while ((inputLine = in.readLine()) != null) {
//System.out.println(inputLine);
byte b[]=inputLine.getBytes();
//System.out.println(b);
f0.write(b);
}
in.close();
f0.close();
But when i try to open abc.pdf in my adobe reader x i get following error:
There was an error opening this document.The file is damaged and could not be repaired
You seem to be directly accessing the Google drive using Raw HTTP requests.
You may be better of using the Google Drive SDK. This link contains good examples to address the use cases you state in your question.
However if you do want to stick to your technique then you should not be using a BufferedReader.readLine(). This is because the PDF file is a binary finally that would depend upon the correct byte sequences to be preserved in order to be read correctly by the PDF reader software. Hopefully the below technique should help you:
//read in chunks of 2KB
byte[] buffer = new byte[2048];
int bytesRead = 0;
try(InputStream is = conn.getInputStream())
{
try(DataOutputStream os = new DataOutputStream(new FileOutputStream("file.pdf"))
{
while((bytesRead = is.read(buffer)) != -1)
{
os.write(buffer, 0, bytesRead);
}
}
}
catch(Exception ex)
{
//handle exception
}
Note that I am using the try-with-resources statement in Java 7
Hope this helps.

Simulate URL entering on java

So I have a problem where if I type this link on the browser and hit enter, an activation happens. I just want to do the same through Java. I don't need any kind of response from the URL. It should just do the same as entering the URL on a browser. Currently my code doesn't throw an error, but I don't think its working because the activation is not happening. My code:
public static void enableMachine(String dns){
try {
String req= "http://"+dns+"/username?username=sputtasw";
URL url = new URL(req);
URLConnection connection = url.openConnection();
connection.connect();
/*BufferedReader br = new BufferedReader(new InputStreamReader(url.openStream()));
String strTemp = "";
while (null != (strTemp = br.readLine())) {
System.out.println(strTemp);
}*/
} catch (Exception ex) {
ex.printStackTrace();
}
}
What's the problem?
If you want to do that with an URLConnection, it isn't sufficient to just open the connection with connect, you also have to send e.g. an HTTP request etc.
That said, i think it would be easier, if you use an HTTP client like the one from Apache HttpComponents (http://hc.apache.org/). Just do a GET request with the HTTP client, this would be the same as visiting the page with a browser (those clients usually also supports redirection etc.).
You may use HttpUrlConnectionClass to do the job:
URL url = new URL("http://my.url.com");
HttpURLConnection httpCon = (HttpURLConnection) url.openConnection();
httpCon.setRequestProperty("Content-Type", "application/json");
httpCon.setDoOutput(true);
httpCon.setRequestMethod("POST");
String params = "foo=42&bar=buzz";
DataOutputStream wr = new DataOutputStream(httpCon.getOutputStream());
wr.writeBytes(params);
wr.flush();
wr.close();
httpCon.connect();
int responseCode = httpCon.getResponseCode();
You may as well use "GET" request method and just append parameters to the url.

Download a file from a page (cookies needed) using post request

I have tested the first step (the login page) and it works. I put all parameters (user, pass, etc) and I can print the result (page with my data). The problem is when I try to download a file from that web. I need the cookies from the first step. In the file that I download I have the message: "Expired session". This is my code:
URL login = new URL("...");
URL download_page = new URL("...");
URL document_link new URL("...");
//String for request
String data_post = "username=name&password=1234&other_data=...";
//Login page
HttpURLConnection conn = (HttpURLConnection)login.openConnection();
conn.setDoOutput(true);
OutputStreamWriter wr = new OutputStreamWriter(conn.getOutputStream());
wr.write(data_post);
wr.close();
conn.connect();
//Download page
HttpURLConnection connDownload = (HttpURLConnection)download_page.openConnection();
connDownload.connect();
//Link to the file
HttpURLConnection connFile = (HttpURLConnection)document_link.openConnection();
connFile.connect();
BufferedInputStream in = new BufferedInputStream(connFile.getInputStream());
File saveFile = new File("myfile.txt");
OutputStream out = new BufferedOutputStream(new FileOutputStream(saveFile));
byte[] buf = new byte[256];
int n = 0;
while ((n=in.read(buf))>=0) {
out.write(buf, 0, n);
}
out.flush();
out.close();
Thanks in advance.
Have you tried to check the headers for a cookie on the first page before closing the connection? I'd try something like:
String cookies = conn.getHeaderField("Set-Cookie");
Then set the cookie subsequently in the following connections, before executing connect(), using:
connDownload.setRequestProperty("Cookie", cookies);
... See if that works ...

Categories

Resources