HttpURLConnection not able to read 302 Response code - java

I am trying to download a file through code and it is working if the file is found. But if the Link returns a 302 code, I am getting a connection timeout through code. It is working fine in browser.
Can someone help me out where I am going wrong?
My code is given below:
private static void downloadFile(String fileUrl, String fileName) {
HttpURLConnection connection = null;
try {
URL url = new URL(fileUrl);
connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.setConnectTimeout(60000);
connection.setReadTimeout(60000);
connection.connect();
int code = connection.getResponseCode();
String message = connection.getResponseMessage();
System.out.println(code + "-" + message);
if (code == HttpURLConnection.HTTP_OK) {
try (BufferedInputStream in = new BufferedInputStream(connection.getInputStream());
FileOutputStream fileOutputStream = new FileOutputStream(fileName)) {
byte dataBuffer[] = new byte[1024];
int bytesRead;
while ((bytesRead = in.read(dataBuffer, 0, 1024)) != -1) {
fileOutputStream.write(dataBuffer, 0, bytesRead);
}
} catch (Exception ex) {
ex.printStackTrace();
}
} else {
throw new Exception("Invalid Response Code: " + code + ", Response Message: " + message);
}
} catch (Exception ex) {
ex.printStackTrace();
} finally {
if (connection != null) {
connection.disconnect();
}
}
}
Working URL(200): https://archives.nseindia.com/content/historical/DERIVATIVES/2022/SEP/fo16SEP2022bhav.csv.zip
Timeout URL(302): https://archives.nseindia.com/content/historical/DERIVATIVES/2022/SEP/fo17SEP2022bhav.csv.zip

A setting
connection.setInstanceFollowRedirects(true); // follow response codes 3xx
connection = (HttpURLConnection) new URL(fileUrl).openConnection();
connection.setInstanceFollowRedirects(true); // follow response codes 3xx
connection.setRequestMethod("GET");
connection.setConnectTimeout(60000);
connection.setReadTimeout(60000);
connection.connect();

Related

Java make POST request to express js server and download PDF file

I have express js server as API. I need to send POST request to that server and my website needs to download PDF file to the client computer.
Here is my express server code:
const pdf = await generatePDF(data.originURL, data.url, data.pageOrientation); //pdf generation
// send pdf to client
res.writeHead(200, {
'Content-Type': 'application/pdf',
'Content-Disposition': 'attachment; filename=file.pdf',
'Content-Length': pdf.length
});
res.end(pdf);
In my website I have commandButton which call the action for POST request;
What I'm a doing wrong, I'm not getting any downloaded file in my website?
Method for making POST request:
public void makeRequest() {
HttpURLConnection connection = null;
try {
String imageExportServer = "url....";
URL url = new URL(imageExportServer);
connection = (HttpURLConnection)url.openConnection();
Stopwatch stopwatch = Stopwatch.createStarted();
try {
connection.setDoOutput(true);
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "application/json");
try (OutputStream stream = connection.getOutputStream()) {
JsonObject configJson = new JsonObject();
configJson.addProperty("originURL", "url");
configJson.addProperty("url", "url...");
configJson.addProperty("pageOrientation", "someText");
stream.write(Builder().create().toJson(configJson).getBytes());
}
int responseCode = connection.getResponseCode();
if (responseCode != 200) {
//log.warn("Error response: ", responseCode);
}
String fileName = "";
String disposition = connection.getHeaderField("Content-Disposition");
String contentType = connection.getContentType();
int contentLength = connection.getContentLength();
System.out.println("Content-Type = " + contentType);
System.out.println("Content-Disposition = " + disposition);
System.out.println("Content-Length = " + contentLength);
System.out.println("fileName = " + fileName);
// opens input stream from the HTTP connection
InputStream inputStream = connection.getInputStream();
// opens an output stream to save into file
FileOutputStream outputStream = new FileOutputStream("neki.pdf");
int bytesRead = -1;
byte[] buffer = new byte[contentLength];
while ((bytesRead = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
}
outputStream.close();
inputStream.close();
FileOutputStream fos = new FileOutputStream("neki.pdf");
fos.write(buffer);
fos.close();
System.out.println("File downloaded");
}
} catch (IOException e) {
//log.warn(e.getMessage(), e);
} finally {
//log.info("Exporting chart of type '%s' took %sms.", "tyoe", stopwatch.elapsed(TimeUnit.MILLISECONDS));
}
} catch (IOException e) {
//log.warn(e.getMessage(), e);
} finally {
if (connection != null) {
try {
connection.disconnect();
} catch (Exception e) {
//log.warn(e.getMessage(), e);
}
}
}
}

How to solve W/OkHttpClient: A connection was leaked?

I'm trying to create a connection to some remote server, and get the following warning in my LogCat: "W/OkHttpClient: A connection to "some url" was leaked. Did you forget to close a response body?"
Now I don't understand why is it happening.
I use Apache IO commons to count number of bytes sent and received, and it's the only use if mine with OkHTTP.
Can you please look at my code snippet and tell me what's wrong with it?
This is the code where I try to create a connection:
public static JSONObject getConfiguration(Context context) throws HttpRequestException {
long bytes = 0;
long netUsage = HttpUtils.getCurrentNetworkUsage(context);
int statusCode = 0, count = 0;
NetworkRequest.Status netStatus = NetworkRequest.Status.FAILED;
JSONObject commonInformation;
HttpURLConnection connection = null;
CountingInputStream cis = null;
InputStreamReader isr = null;
BufferedReader br = null;
InputStream is = null;
CountingOutputStream cos = null;
// result
JSONObject receivedConfig = null;
try {
commonInformation = ConfigurationProcessor.getCommonInformation(context);
if (commonInformation == null) {
return null;
}
URL url = new URL(BuildConfig.SERVER_CONFIG_URL);
if (BuildConfig.DEBUG) {
LogUtils.d(TAG, "url = " + url.getPath());
}
connection = url.getProtocol().equals("https")? getHttpsConnection(url) : getHttpConnection(url);
connection.setDoOutput(true);
connection.setDoInput(true);
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
connection.setRequestProperty("Content-Encoding", "gzip");
byte[] gzipped = HttpUtils.gzip(commonInformation.toString());
cos = new CountingOutputStream(connection.getOutputStream());
cos.write(gzipped);
cos.flush();
statusCode = connection.getResponseCode();
switch (statusCode) {
case 200: {
// get the response
is = connection.getInputStream();
cis = new CountingInputStream(is);
isr = new InputStreamReader(cis);
br = new BufferedReader(isr);
StringBuilder builder = new StringBuilder();
String output;
while ((output = br.readLine()) != null) {
builder.append(output);
}
receivedConfig = new JSONObject(builder.toString());
netStatus = NetworkRequest.Status.SUCCEEDED;
break;
}
case 502: {
throw new HttpRequestException("Received 502 error (Bad Gateway)", NetworkRequest.Type.GET_REMOTE_CONFIGURATION);
}
}
// analytics about the request
if (BuildConfig.DEBUG) {
LogUtils.d(TAG, "generating analytics about the http request");
}
count = receivedConfig == null ? 0 : 1;
if (cis != null) {
bytes = cis.getByteCount();
}
if (cos != null) {
bytes += cos.getByteCount();
}
} catch (Exception | OutOfMemoryError ex) {
LogUtils.e(TAG, ex.getMessage());
ex.printStackTrace();
} finally {
closeStream(is);
closeStream(br);
closeStream(isr);
closeStream(cis);
closeStream(cos);
if (connection != null) connection.disconnect();
createNetworkRequest(context, statusCode, netUsage, netStatus, count, bytes, NetworkRequest.Type.GET_REMOTE_CONFIGURATION, BuildConfig.SERVER_CONFIG_URL);
}
if (BuildConfig.DEBUG) {
LogUtils.d(TAG, "Received configuration data");
}
return receivedConfig;
}

Java HttpURLConnection invoke remote server and returned 500 status

I want to invoke remote server using HttpURLConnection, here is my function:
public String invokeAwvsServer(String api, String param, String method){
System.out.println(api+param);
BufferedReader reader = null;
HttpURLConnection connection = null;
OutputStreamWriter out = null;
try {
URL url = new URL(api);
connection = (HttpURLConnection) url.openConnection();
connection.setDoOutput(true);
connection.setDoInput(true);
connection.setUseCaches(false);
connection.setInstanceFollowRedirects(true);
connection.setRequestMethod(method);
connection.setRequestProperty("Content-Type", "application/json");
connection.setRequestProperty("X-Auth", apiKey);
connection.connect();
if(method.equalsIgnoreCase("POST")){
out = new OutputStreamWriter(connection.getOutputStream(), "UTF-8");
out.append(param);
out.flush();
}
reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), "UTF-8"));
String line;
StringBuffer res = new StringBuffer();
while ((line = reader.readLine()) != null) {
res.append(line);
}
return res.toString();
} catch (IOException e) {
e.printStackTrace();
} finally {
if(reader != null){
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(connection != null){
connection.disconnect();
}
if(out != null){
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return "error";
}
I use this function in its own class and works well, but if I call it in other class ,the remote server return 500 status code and JVM throws exception like:
java.io.IOException: Server returned HTTP response code: 500 for URL:...
What`s the reason?Thanks a lot:)

Does closing of input/output stream gotten from getInput/OutputStream() affects recreation of underlying Socket?

I've already looked through resources which describe specifics of work with HttpURLConnection as in Java so in Android (where there is not default implementation of working with connection pool) and my question is: if I close a stream gotten from HttpURLConnection, will the system create a new one Socket at a next time when I establish a HttpURLConnection with the same URL or it will try to use an exist one? Considering the following code:
private byte[] downloadText(URL url, String data) {
OutputStream out = null;
InputStream in = null;
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
try {
conn.setRequestMethod("POST");
conn.setReadTimeout(20 * 1000);
conn.setConnectTimeout(15 * 000);
conn.setDoInput(true);
conn.setDoOutput(true);
conn.setRequestProperty("Content-Type", "application/json;charset=utf-8");
byte[] payload = data.getBytes("utf-8");
conn.setFixedLengthStreamingMode(payload.length);
conn.connect();
out = new BufferedOutputStream(conn.getOutputStream());
out.write(payload);
out.flush();
final int responseCode = conn.getResponseCode();
final String responseMessage = conn.getResponseMessage();
is = conn.getInputStream();
if((responseCode / 100) == 2 || responseMessage.equals("OK")) {
return readFromStream(is);
}
} catch (IOException e) {
Log.e(TAG, "Error occurred while trying to connect to the server" + e.toString());
} finally {
try {
if(out != null) {
out.close();
}
if(is != null) {
is.close();
}
} catch(IOException e) {
Log.e(TAG, "Error occurred while trying to close data streams" + e.toString());
}
}
}
Your question doesn't make sense. If there isn't a connection pool, there is no 'existing socket' to reuse.

URLConnection is not allowing me to access data on Http errors (404,500,etc)

I am making a crawler, and need to get the data from the stream regardless if it is a 200 or not. CURL is doing it, as well as any standard browser.
The following will not actually get the content of the request, even though there is some, an exception is thrown with the http error status code. I want the output regardless, is there a way? I prefer to use this library as it will actually do persistent connections, which is perfect for the type of crawling I am doing.
package test;
import java.net.*;
import java.io.*;
public class Test {
public static void main(String[] args) {
try {
URL url = new URL("http://github.com/XXXXXXXXXXXXXX");
URLConnection connection = url.openConnection();
DataInputStream inStream = new DataInputStream(connection.getInputStream());
String inputLine;
while ((inputLine = inStream.readLine()) != null) {
System.out.println(inputLine);
}
inStream.close();
} catch (MalformedURLException me) {
System.err.println("MalformedURLException: " + me);
} catch (IOException ioe) {
System.err.println("IOException: " + ioe);
}
}
}
Worked, thanks: Here is what I came up with - just as a rough proof of concept:
import java.net.*;
import java.io.*;
public class Test {
public static void main(String[] args) {
//InputStream error = ((HttpURLConnection) connection).getErrorStream();
URL url = null;
URLConnection connection = null;
String inputLine = "";
try {
url = new URL("http://verelo.com/asdfrwdfgdg");
connection = url.openConnection();
DataInputStream inStream = new DataInputStream(connection.getInputStream());
while ((inputLine = inStream.readLine()) != null) {
System.out.println(inputLine);
}
inStream.close();
} catch (MalformedURLException me) {
System.err.println("MalformedURLException: " + me);
} catch (IOException ioe) {
System.err.println("IOException: " + ioe);
InputStream error = ((HttpURLConnection) connection).getErrorStream();
try {
int data = error.read();
while (data != -1) {
//do something with data...
//System.out.println(data);
inputLine = inputLine + (char)data;
data = error.read();
//inputLine = inputLine + (char)data;
}
error.close();
} catch (Exception ex) {
try {
if (error != null) {
error.close();
}
} catch (Exception e) {
}
}
}
System.out.println(inputLine);
}
}
Simple:
URLConnection connection = url.openConnection();
InputStream is = connection.getInputStream();
if (connection instanceof HttpURLConnection) {
HttpURLConnection httpConn = (HttpURLConnection) connection;
int statusCode = httpConn.getResponseCode();
if (statusCode != 200 /* or statusCode >= 200 && statusCode < 300 */) {
is = httpConn.getErrorStream();
}
}
You can refer to Javadoc for explanation. The best way I would handle this is as follows:
URLConnection connection = url.openConnection();
InputStream is = null;
try {
is = connection.getInputStream();
} catch (IOException ioe) {
if (connection instanceof HttpURLConnection) {
HttpURLConnection httpConn = (HttpURLConnection) connection;
int statusCode = httpConn.getResponseCode();
if (statusCode != 200) {
is = httpConn.getErrorStream();
}
}
}
You need to do the following after calling openConnection.
Cast the URLConnection to HttpURLConnection
Call getResponseCode
If the response is a success, use getInputStream, otherwise use getErrorStream
(The test for success should be 200 <= code < 300 because there are valid HTTP success codes apart from than 200.)
I am making a crawler, and need to get the data from the stream regardless if it is a 200 or not.
Just be aware that it if the code is a 4xx or 5xx, then the "data" is likely to be an error page of some kind.
The final point that should be made is that you should always respect the "robots.txt" file ... and read the Terms of Service before crawling / scraping the content of a site whose owners might care. Simply blatting off GET requests is likely to annoy site owners ... unless you've already come to some sort of "arrangement" with them.

Categories