HttpsURLConnection status code 302 when establishing a connection - java

I am trying an example on httpsURLConnection,I get the following exception
Status code: 302
ejava.lang.IllegalStateException: connection not yet open
Following is the code snippet :
private static String url_s = "https://java.sun.com:443" ;
URL url = new URL(url_s) ;
HttpsURLConnection conn = (HttpsURLConnection) url.openConnection() ;
conn.setDoInput(true);
conn.setRequestMethod("GET") ;
conn.connect() ;

You need to read up a bit about HTTP protocol first if you really wanna try your hands at direct client calling.
302 is temporary redirect header which is sent back from the server. The response has another header named 'Location' whose value is a URL to which the server wants you to hit next. Browsers handle this automatically so you dont see a wait thing.
But if you want to do it yourself be sure ot handle all 301, 302 situations like these.
Best Of Luck.

Related

Redmine / Java native: Update query by script. Clone Fiddler request

I'm doing a script to update several queries that we use in our project everytime we deploy a sprint.
I'm trying to replicate the same request that I'm testing on Fiddler, that it is working, in the following way:
System.setProperty("sun.net.http.allowRestrictedHeaders", "true");
String host = 'redmine.our-domain.com';
String url = 'http://redmine.our-domain.com/queries/4088';
String REDMINE_SESSION_COOKIE = "_redmine_session=BAh7DkkiDHVzZXJfaWQGOgZFRmkvSSIKY3RpbWUGOwBGbCsHmouFWkkiCmF0aW1lBjsARmwrByk211tJIg9zZXNzaW9uX2lkBjsARkkiJTMzZWJkNmI1MzA4MzZkNmMxNGYwNjY1OWQxMDZjZmU3BjsAVEkiEF9jc3JmX3Rva2VuBjsARkkiMVB3bDlCb0F5NFFCbTd3dmdGWGx0VjdEL05WYjhVRGExdFluQmNMbnFZTHM9BjsARkkiCnF1ZXJ5BjsARnsHOgdpZGkC%2BA86D3Byb2plY3RfaWRpAssBSSIWaXNzdWVzX2luZGV4X3NvcnQGOwBGSSIMaWQ6ZGVzYwY7AEZJIg1wZXJfcGFnZQY7AEZpaUkiFWZqbGVzX2luWGV4X3NvcnQGOwBGSSINZm2sZW5hbWUGOwBG--5c961485290b3c98f38de934b939d25cc01e092f"
String data = "_method=put&authenticity_token=Pwl9BoAy4QBm7wvgFXlsV7D%2FNVb8UDa2tYnBcLnqYLs%3D&query%5Bname%5D=Current+sprint+1.75-test+API+0+0+1&query%5Bvisibility%5D=2query%5Bgroup_by%5D=category&f%5B%5D=status_id&op%5Bstatus_id%5D=o&f%5B%5D6=fixed_version_id&v%5Bfixed_version_id%5D%5B%5D=6030&c%5B%5D=tracker&c%5B%5D=status&c%5B%5D=priority&c%5B%5D=subject&c%5B%5D=assigned_to&c%5B%5D=fixed_version&c%5B%5D=start_date&c%5B%5D=due_date&c%5B%5D=estimated_hours&c%5B%5D=done_ratio&c%5B%5D=parent";
byte[] body = data.getBytes("UTF-8");
HttpURLConnection http = (HttpURLConnection) new URL(url).openConnection();
http.setRequestMethod('POST');
http.setRequestProperty('Cookie', REDMINE_SESSION_COOKIE);
http.setRequestProperty('Content-Type', 'application/x-www-form-urlencoded');
http.setRequestProperty('Host', host);
http.setRequestProperty('Content-Length', "${body.length}");
http.setDoOutput(true);
http.getOutputStream().write(body);
Both, data's authenticity_token and session cookie are fakes, but I'm copy-pasting the Fiddler one.
I'm adding the Host and Content-Length because Fiddler always add them.
Fiddler returns a 302 status that it is right, because Redmine redirects the page.
With the code above I receive a 422 status (Unprocessable Entity) with this message in the body:
Invalid form authenticity token
I've spent 3 days trying to figure out what I'm doing wrong to clone the request. Any clue?
You should rather try to use Redmine's API to acheive your goal, instead of trying to send html form data to controller.
Redmine login form creates also invisible form data fields, which you can see while inspecting with your browser (F12 usually).
One such, hidden field is authenticity token, and it's generated new, every time form is rendered.
Fiddler probably works, because it's performing basic authentication, as described here:
http://www.redmine.org/projects/redmine/wiki/Rest_api#Authentication
So in your code, you must remove part of code trying to mimic form data, and use basic authentication instead, like this:
System.setProperty("sun.net.http.allowRestrictedHeaders", "true");
String host = 'redmine.our-domain.com';
String url = 'http://redmine.our-domain.com/queries/4088';
String auth = Base64.getEncoder().encodeToString((username+":"+password).getBytes(StandardCharsets.UTF_8)); //Java 8 - not sure for 7
HttpURLConnection http = (HttpURLConnection) new URL(url).openConnection();
http.setRequestProperty("Authorization", "Basic "+auth);
http.setRequestMethod('POST');
http.setRequestProperty('Cookie', REDMINE_SESSION_COOKIE);
http.setRequestProperty('Content-Type', 'application/x-www-form-urlencoded');
http.setRequestProperty('Host', host);
http.setRequestProperty('Content-Length', "${body.length}");
http.setDoOutput(true);
http.getOutputStream().write(body);

PORT Change in error case: HttpURLConnection

I am consuming API using HttpURLConnection in my android application and its running fine but if I get response code except then 200 ok (like 404, 500) my port is changing when I hit next request after error response code:
my code for android request is below and wireshark log as well:
try {
url = new URL(path_url + apiMsg); //in the real code, there is an ip and a port
conn = (HttpURLConnection) url.openConnection();
conn.setDoInput(true);
conn.setDoOutput(true);
conn.setConnectTimeout(5000);
conn.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
conn.setRequestMethod("POST");
conn.setRequestProperty("Accept","*/*");
}
Please refer wireshark log:
https://files.fm/u/w7umrwwk
So how to avoid PORT change in error scenario as well like in success 200 case, so that we continue to run on the same PORT.
read about sun.net.http.errorstream.enableBuffering in HttpURLConnection source code.
By default when response code is >= 400 then the connection is closed.
It is a clean though not so efficient way of handling error streams.
Instead of setting obscure system properties to handle this, it would be better to move to a proper http client like apache.

JAVA POST request and then redirect to it?

What I need to do is send POST request to specific URL with two parameters and when the request is sent, I need to redirect user to that link so that he would be able to access functionality.
So far, what I have managed to do from various examples is this:
private void postRemoteAdvisoryLink() throws IOException {
URL obj = new URL(KdrmApplicationContext.getRemoteAdvisoryUrlPath());
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setConnectTimeout(60000);
con.setRequestMethod("POST");
con.setRequestProperty("User-Agent", "Mozilla/5.0");
con.setRequestProperty("Accept-Language", "en-US,en;q=0.5");
// For post only - start
con.setDoOutput(true);
OutputStream os = con.getOutputStream();
os.write(("?auth=ssor&TransportKey=" + ssorTransportKey).getBytes());
os.flush();
os.close();
int responseCode = con.getResponseCode();
}
The problem is that now I get connection time out when trying to execute OutputStream os = con.getOutputStream(); line. Also, I still have no idea how to redirect user when request is completed.
Any ideas?
Using the basic Java URL classes would require you to manually handle the details of HTTP protocol - it's better to use libraries like Apache Http Components, as they deal with the underlying protocols for you. Some examples including POST requests can be found on their website.
Given the original question, the Timeout is likely related to host not responding or your Java application being unable to connect to given URL (due to no proxy configuration for example).
If you want to redirect a request based on the answer, you need to check the response headers and http status - if the status is 302, then there should be a header called Location, which will contain the URL you should make another request to.
Before getting an OutputStream, also make sure to set the Content-Length header (and ideally the Content-Type header as well).

How can I read a text file from the internet with Java?

I want to read the second line of the text at this URL: "http://vuln2014.picoctf.com:51818/" (this is a capture-the-flag competition but only asking for flags or direction to flags breaks the competition rules). I am attempting to open an input stream from the URL but I get an Invalid HTTP Response exception. Any help is appreciated, and I recognize that my error is likely quite foolish.
Code:
URL url = new URL("http://vuln2014.picoctf.com:51818");
URLConnection con = url.openConnection();
InputStream is = con.getInputStream()
The error occurs at the third line.
java.io.IOException: Invalid Http response at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1342) at name.main(name.java:41)
curl happily gets the text from the page, and it is perfectly accessible from a web browser.
When you do this:
URL url = new URL("http://vuln2014.picoctf.com:51818");
URLConnection con = url.openConnection();
You are entering into a contract that says that this URL uses the http protocol. When you call openConnection it expects to get http responses because you used http:// in the URL as the protocol. The Java Documentation says:
If for the URL's protocol (such as HTTP or JAR), there exists a public, specialized URLConnection subclass belonging to one of the following packages or one of their subpackages: java.lang, java.io, java.util, java.net, the connection returned will be of that subclass. For example, for HTTP an HttpURLConnection will be returned, and for JAR a JarURLConnection will be returned.
The server you are connecting to just returns a couple lines of data. I retrieved them with the command nc vuln2014.picoctf.com 51818. There is no http response code like HTTP/1.1 200 OK:
Welcome to the Daedalus Corp Spies RSA Key Generation Service. The public modulus you should use to send your updates is below. Remember to use exponent 65537.
b4ab920c4772c5247e7d89ec7570af7295f92e3b584fc1a1a5624d19ca07cd72ab4ab9c8ec58a63c09f382aa319fa5a714a46ffafcb6529026bbc058fc49fb1c29ae9f414db4aa609a5cab6ff5c7b4c4cfc7c18844f048e3899934999510b2fe25fcf8c572514dd2e14c6e19c4668d9ad82fe647cf9e700dcf6dc23496be30bb
In this case I would use java.net.Socket to establish a connection and then read the lines. This is a simplistic approach that assumes there are 2 lines of data:
Socket theSocket;
try {
theSocket = new Socket("vuln2014.picoctf.com", 51818);
BufferedReader inFile = new BufferedReader(new InputStreamReader(theSocket.getInputStream()));
String strGreet = inFile.readLine();
String strData = inFile.readLine();
} catch (IOException e) {
e.printStackTrace();
}
As for why curl and browsers may render it properly? They are likely more lenient about the data they read and will just dump what is read from the port even if it doesn't conform to the specified protocol (like http)

How i reset an URL connection

I use URL connection to download stream in the Internet. But after i reset the modem, i can't continue download this stream caz it error: Connection reset. How i solve it?
Here is my code:
URL url = new URL(_URL);
HttpURLConnection hUC = (HttpURLConnection) url.openConnection();
hUC.connect();
while (true) {
if ((_data.num = is.read(_data.b)) == -1) {
break;
}
//write to file
fos.write(_data.b, 0, _data.num);
}
You can't - at least, not how you may be expecting.
Instead, you need to handle your exception, and determine how much data you've already read. Once your Internet connection is re-established - assuming that the HTTP server you're downloading from supports requestable byte ranges - you can then set custom HTTP Headers on the request and re-download the remaining portions. (This will require a new HttpURLConnection.)
http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.35 shows the related HTTP specifications involved to make this work.
This is a bit more complicated if you're looking for a "resume" type feature.
You would need to reissue the request once the internet comes back after a disconnect, and add a header to the request in order to resume the download at the byte number where you left off.
You need to set the Range property in the request header in order to specify how far in you're resuming. Then you would just continue to write to the "fos" object from there.
Check out this url: Java: resume Download in URLConnection

Categories

Resources