javax.net.ssl.HttpsURLConnection when are the request fired - java

I'm debugging some method which is supposed to call a webservice and return the response.
Already found a lot of information regarding http(s) requests in these threads :
[Can you explain the HttpURLConnection connection process?
[Using java.net.URLConnection to fire and handle HTTP requests
Still one point is not clear to me :
Would a request be sent each time one of this method is called :
connect, getInputStream, getOutputStream, getResponseCode or getResponseMessage
or is it fired only on first occurence of one of these method ?
On my particular case, would this code snippet fire multiple time the request ?
URL url = new URL(webservice);
conn = (HttpsURLConnection) url.openConnection();
conn.setHostnameVerifier(new HostnameVerifier() {//blabla});
conn.setRequestMethod("GET");
conn.setRequestProperty("Accept", "application/xml");
// As far as I understood : request is still not fired there.
System.out.println("callWebService : calling conn.getResponseCode()");
if (conn.getResponseCode() == 400 //Bad Request
|| conn.getResponseCode() == 403 //Forbidden
|| conn.getResponseCode() == 404 //Not Found
|| conn.getResponseCode() == 500 //Internal Server Error
|| conn.getResponseCode() == 501 //Not Implemented
|| conn.getResponseCode() == 502 //Bad Gateway ou Proxy Error
|| conn.getResponseCode() == 503 //Service Unavailable
|| conn.getResponseCode() == 504 //Gateway Time-out
|| conn.getResponseCode() == 505 //HTTP Version not supported)
{
//handle wrong response
}else{
System.out.println("callWebService : received correct responseCode ");
isr = new InputStreamReader(conn.getInputStream());
br = new BufferedReader(isr);
output = br.readLine();
return output;
}
//close operations handled in finally blocks
Yes there is already much to say about not using a local int to store response code, to check only a few of these possible values and so on. This i gonna refactor anyway, I'm only interested in understanding if this request may be fired multiple times.

In cases like this you may want to check the source code. Most of JVM classes have included sources, and java.net.HttpURLConnection does.
There is this snip in beginning of method getResponseCode() (as JDK 1.8_71)
/*
* We're got the response code already
*/
if (responseCode != -1) {
return responseCode;
}
So its cached. If response is still default value, -1, its executing request to server. But since this behavior is not described in JavaDoc for this method, I would not rely on this and use own integer variable.
JV

Related

ERROR 411 consuming API in java (POST METHOD)

I am working on a personal project to learn how to work with Rest web services.
I have an API web application in Visual, which is my controller and where the connection to Oracle is made, and a web application in JAVA and with a JSON library, in addition to trying to do it in layers according to what I learned in the institute.
When I make the GET request, I have no problem, they bring me the data, but when I make a POST request as a customer's registrar it is when the problems start and I get the error 411 in java.
I Read looking for the solution that some worked for them by placing the "Content-Length" I don't know if I put it right but I still have the problem.
public int insertarCliente(Cliente c){
globalURL += "?rut=" + c.getRut() + "&nom="+ c.getNombre() +"&app=" + c.getApellidoP() + "&apm=" + c.getApellidoM();
try {
HttpURLConnection conn = Conectar(globalURL);
conn.setRequestMethod("POST");
conn.setRequestProperty("ACCEPT", "application/json");
conn.setRequestProperty("Content-Length", "0");
if (conn.getResponseCode() == 200) {
//InputStreamReader in = new InputStreamReader(conn.getInputStream());
BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String resp = br.readLine();
JSONObject obj = new JSONObject(resp);
return obj.getInt("resp");
}
} catch (Exception e) {
Logger.getLogger(ClienteDAO.class.getName()).log(Level.SEVERE, null, e);
}
return 0;
}
The problem start in the IF.
And the error that shows me is the following:
Glook2 was successfully deployed in 227 milliseconds.
**Grave: java.lang.RuntimeException: Failed : HTTP Error code : 411**
at Controllers.ClienteDAO.insertarCliente(ClienteDAO.java:50)
at Services.cliente.registrar(cliente.java:104)
at Services.cliente.processRequest(cliente.java:46)
at Services.cliente.doPost(cliente.java:77)
I must emphasize that I have proven in the POSTMAN that the web services method works and correctly adds the data to the database.
String globalURL = "http://localhost:60367/api/Cliente";
HttpURLConnection conn;
public ClienteDAO() {
conn = Conectar(this.globalURL);
}
private HttpURLConnection Conectar(String urlRest) {
try {
URL url;
url = new URL(urlRest);
return (HttpURLConnection) url.openConnection();
} catch (Exception e) {
Logger.getLogger(ClienteDAO.class.getName()).log(Level.SEVERE, null, e);
}
return null;
}
Enable logging as shown here: How to enable wire logging for a java HttpURLConnection traffic?
You will then see1 that the Content-Length header is not sent:
FINE: sun.net.www.MessageHeader#4bf558aa5 pairs:
{POST / HTTP/1.1: null}
{ACCEPT: application/json}
{User-Agent: Java/13}
{Host: localhost:8080}
{Connection: keep-alive}
1: Sample log entry, wrapped for easier reading
That is because HttpURLConnection manages that header.
To send a Content-Length: 0 header, send no output, i.e. replace:
conn.setRequestProperty("Content-length", "0");
with:
conn.setDoOutput(true);
conn.getOutputStream().close();
Logging now shows the header:
FINE: sun.net.www.MessageHeader#5fa7e7ff7 pairs:
{POST / HTTP/1.1: null}
{ACCEPT: application/json}
{User-Agent: Java/13}
{Host: localhost:8080}
{Connection: keep-alive}
{Content-type: application/x-www-form-urlencoded}
{Content-Length: 0}
See also: JDK-6997628: HttpURLConnection strips Content-Length header on Post:
Affects Version/s: 6u22
Status: Open
Resolution: Unresolved
BT2:EVALUATION
The fix for CR 6961084 restricts the setting of some potentially security sensitive headers. Since these headers were allowed to be set in previous releases then of course compatibility is effected. A decision was made that compatibility was secondary to the security risk these headers posed. We understand that there may be valid apps out there that will be effected by this, so the sun.net.http.allowRestrictedHeaders property was added to revert to previous behavior.
BT2:WORK AROUND
Run with -Dsun.net.http.allowRestrictedHeaders=true
I would not recommend using that workaround.

How to fix the Server returned HTTP response code 400 and tranisitions cannot be processed

I'm trying to proceed the JIRA transitions by java coding, most of the time it works, but the jira rest api call sometimes return the below error: (Actually with this error, the transition is processed)
java.io.IOException: Server returned HTTP response code: 400 for URL: http://testingSite/jira/rest/api/latest/issue/ABC-123/transitions
Also, there are some case the rest api call do not return errors but the transition is not proceed.
Here is my coding, most of the time it works, so it ruined my days to figure out what is happening.
try {
String authkey = "YWRtaW46cGFzc3dvcmQ=";
URL url = new URL("http://testingSite/jira/rest/api/latest/issue/ABC-123/transitions");
connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("POST");
connection.setDoOutput(true);
connection.setRequestProperty("Authorization", "Basic " + authkey);
connection.setRequestProperty("Accept-Charset", "UTF-8");
connection.setRequestProperty("Content-Type", "application/json;charset=UTF-8");
OutputStream os = connection.getOutputStream();
String data = "{\"transition\": {\"id\": \"71\"}}";
os.write(data.toString().getBytes("UTF-8"));
os.close();
content = connection.getInputStream();
in = new InputStreamReader(content);
br = new BufferedReader(in);
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
} catch (Exception e) {
e.printStackTrace();
}
The error comes from this line:
content = connection.getInputStream();
I expect there is not exception and all transition is processed but the behaviour is quite strange for me.
Behaviour 1 : Server returned HTTP response code : 400 but the transition is processed
Behaviour 2 : Server do not return any error but the transition is not processed
So I was looking for reference documentation here. And its stated that
POST: 400 - If there is no transition specified.
You have you transition id hardcoded and maybe for that type of issue it has different transition id or something similar. Try to call
GET /rest/api/2/issue/{issueIdOrKey}/transitions?{transitionId}
to verify you transition is actually there.

Parse REST API, Validate User session

I am using Parse REST API for a game, altough there are java libraries for Parse I would like to handle the transfer protocolls my self using java.net for learning purposes. Please look away from things like, why dont I use Apache HttpClient.
Following the Parse REST API Guide
Here is what I am trying to achive:
Signup
User Login
validating session tokens / Retriving current user
The first two steps works just fine, the former using POST request method and the latter using GET with some paramaters.
Keeping the Request and Response format in mind I also provide the Application-ID and the REST-API-Key which are the appropriate request headers needed.
Now, for the third step using GET request with no paramaters, but with an additional header, the API expects there to be a Session-Token provided.
Code
private static void validateSessionToken(String token) throws IOException {
System.out.println("Token: " + token);
URL url = new URL("https://api.parse.com/1/users/me");
HttpsURLConnection con = (HttpsURLConnection) url.openConnection();
con.setRequestMethod("GET");
con.setRequestProperty("X-Parse-Application-Id", "xxxxxxx");
con.setRequestProperty("X-Parse-REST-API-Key", "xxxxxxxx");
con.setRequestProperty("X-Parse-Session-Token", token);
con.setRequestProperty("content-type", "application/json");
int responseCode = con.getResponseCode();
System.out.println("\nSending 'GET' request to URL : " + url);
System.out.println("Response Code : " + responseCode);
if(responseCode == 400) {
System.out.println("Bad request!");
return;
}
BufferedReader in = new BufferedReader(
new InputStreamReader(con.getInputStream()));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = in.readLine()) != null) {
response.append(inputLine);
}
in.close();
System.out.println(response.toString());
}
Outputs
Sending 'GET' request to URL : https://api.parse.com/1/users/me
Response Code : 400
Bad request!
Debugging
I have been using the PARSE API CONSOLE and Chrome network debugging tool to try and see what the difference is, but cannot see any.
From wiki:
400 Bad Request
The server cannot or will not process the request due to something that is perceived to be a client error (e.g., malformed request syntax, invalid request message framing, or deceptive request routing)
Some photos that may help
So when I asked my JsonObject for the session token:
jsonObject.get("sessionToken").toString();
It returned: "r:WzB7qdmhkcW5qd2moM8gbBLDp" in quotation, but using:
jsonObject.get("sessionToken").getAsString();
it returned: r:WzB7qdmhkcW5qd2moM8gbBLDp
I was so focused on the request I did not even notice...

Read response even though it's 404

Is there a way to read a response of a simple http-get made like below, if getResponseCode() == 404 and thus getInputStream() would throw an exception? I'd prefer to stay with java.net, if it's possible.
HttpURLConnection c = (HttpURLConnection)new URL("http://somesite.com").openConnection;
c.openInputStream();
Thing is, that I have (indeed) a site I want to read out with java that responds with 404, but displays in a browser, because it obviously caries a response anyway.
You want to use the getErrorStream() method if the getResponseCode() == 404.
HttpURLConnection c = (HttpURLConnection)new URL("http://somesite.com").openConnection();
InputStream in = null;
if (c.getResponseCode() >= 400) {
in = c.getErrorStream();
}
else {
in = c.getInputStream();
}

Java function to detect valid webpage

I am trying to write a Java program that will load pages pointed to by valid links and report other links as broken. My problem is that the Java URL will download the appropriate page if the url is valid, and the search-engine results for the url if the url is invalid.
Is there a Java function that detects if the url resolves to a legitimate page . . . thanks very much,
Joel
HttpURLConnection#getResponseCode will give you an HTTP status code
You can get the HTTP response code for a URL like so:
public static int getResponseCode(URL url) throws IOException {
URLConnection conn = url.openConnection();
if (!(conn instanceof HttpURLConnection)) {
throw new IllegalArgumentException("not an HTTP url: " + url);
}
HttpURLConnection httpConn = (HttpURLConnection) conn;
return httpConn.getResponseCode();
}
Now the question is, what do you consider a "valid" webpage? For me, if a URL parses correctly and it's protocol is "http" (or https) and it's response code is in the 200 block or 302 (Found/Redirect) or 304 (Not modified), then it's valid:
public boolean isValidHttpResponseCode(int code) {
return ((code / 100) == 2) || (code == 302) || (code == 304);
}

Categories

Resources