Java HttpsURLConnection reuse - java

What am I trying to achieve:
I have a piece of Java code that's meant to connect to a web server in HTTPS. I want to use JVM's built-in HttpsURLConnection only. The intention is to keep the http connection open for an authenticated user and keep sending and receiving GET/POST requests. Once authenticated, all GET/POST requests will have the same PHP session ID I received from piece of php code at the web server. That PHP is actually the one that takes in the requests from my java app, processes (DB handling) and outputs in XML to my client for my better data handling.
The Problem:
I need to keep the same HttpsURLConnection open for the URL (since all requests are going to the same documentroot) and keep changing the parameters in the GET as I move along the client application. But as HTTP is intended to serve only one request at a time, I do not get to resend data without reinitializing the HttpsURLConnection. In that case, my session ID gets changed (because of obvious reasons of new HTTP connection) and I end up nowhere. Below is the piece of code I crafted out of my main app to clarify what I did (please disregard braces close):
try{
URL url = new URL("https://localhost:8443/?type=login&username=testu&password=testp");
HttpsURLConnection conn = (HttpsURLConnection)(url).openConnection();
conn.setDoInput(true);
conn.setDoOutput(true);
conn.setRequestProperty("Connection","Keep-Alive");
System.out.println("Connecting...");
conn.connect();
System.out.println("Response: " + conn.getResponseCode());
BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
System.out.println("" + in.readLine());
url = new URL("https://localhost:8443/?type=login&username=testu1&password=testp1");
conn = (HttpsURLConnection)url.openConnection();
conn.setDoInput(true);
conn.setDoOutput(true);
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(conn.getOutputStream()));
System.out.println("Connecting..." + conn.getRequestMethod());
in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
System.out.println("Response: " + conn.getResponseCode());
System.out.println("" + in.readLine());
System.out.println("" + conn.getHeaderFields());
} catch (MalformedURLException ex) {
System.out.println(ex);
} catch (IOException ex) {
System.out.println(ex);
}
}
Sample output from above code:
Connecting...
Response: 200
fipfk4pq0ov68bssicug3pv0d3testu
Connecting...POST
Response: 200
hqe9j1kmbdc98f5q1g2vkepb11testu1
Query:
Is it possible to keep my HttpsURLConnection still pointing to the same URL, while I change the GET request parameters?

Related

Microsoft Graph: Requesting an Extension returns http 400 bad request

I added an open extension to an event in a calendar and am trying to read it back.
Here is the url:
https://graph.microsoft.com/v1.0/users/{userid}/calendars/{calendarId}=/events?$expand=Extensions($filter=Id eq 'c.i.m.p.server.entities.outlook.Event')
I cannot get this to work in a Java program. The following combinations do work:
It works my Java program if I remove the $expand... parameter. I can also ask for certain fields, that works too.
The request works in Postman (I just have to set the token)
The request works in Graph Explorer when I log in as the owner of the calendar
Here is the extension (inside one of the events) when I use Postman to read the event. It is the last item in the event:
"extensions#odata.context": "https://graph.microsoft.com/v1.0/$metadata#users('{userid}')/calendars('{calendarId}')/events('{eventId})/extensions",
"extensions": [
{
"#odata.type": "#microsoft.graph.openTypeExtension",
"id": "Microsoft.OutlookServices.OpenTypeExtension.c.i.m.p.server.entities.outlook.Event",
"extensionName": "c.i.m.p.server.entities.outlook.Event",
"adherentId": "12346",
"timeSlotID": "346463"
}
]
Here is the Java code (Java 8, using java.io and java.net libraries):
private static void doSomething(String _accessToken) throws IOException {
String urlString = "https://graph.microsoft.com/v1.0/users/{userId}/calendars/{calendarId}/events?$expand=Extensions($filter=Id eq 'c.i.m.p.server.entities.outlook.Event')";
URL url = new URL(urlString);
Proxy webProxy
= new Proxy(Proxy.Type.HTTP, new InetSocketAddress({proxy-address}, {port}));
HttpURLConnection connection = (HttpURLConnection) url.openConnection(webProxy);
// Set the appropriate header fields in the request header.
connection.setRequestProperty("Authorization", "Bearer " + _accessToken);
connection.setRequestProperty("Accept", "application/json");
connection.setDoOutput(true);
connection.setReadTimeout(5000);
connection.setRequestMethod(HttpMethod.GET);
try {
connection.connect();
int responseCode = connection.getResponseCode();
System.out.println("execute(), response code = " + responseCode);
String responseMessage = connection.getResponseMessage();
System.out.println("execute(), response Message = " + responseMessage);
String responseString = null;
try {
InputStream ins = connection.getInputStream();
BufferedReader br=new BufferedReader(new InputStreamReader(ins));
StringBuffer sb=new StringBuffer();
String line;
while ((line=br.readLine()) != null) {
sb.append(line);
}
responseString = sb.toString();
} catch (Exception e) {
System.out.println("Could not get input stream from response, error is " + e.toString());
}
System.out.println("execute(), httpResult = " + responseString);
} catch (IOException e) {
System.out.println(".execute(), IOException : " + e.toString());
} finally {
connection.disconnect();
}
}
How do I fix this? Thanks!
400 means bad request. It could be because of url encoding. Url encode the query string.
Something like
String query = "Extensions($filter=Id eq 'c.i.m.p.server.entities.outlook.Event'";
String url = "https://graph.microsoft.com/v1.0/users/{userId}/calendars/{calendarId}/events?
$expand=" + URLEncoder.encode(query, StandardCharsets.UTF_8.name());
Alternatively you could use graph service java api based on your need which will help abstract all the interactions for you or you could use any of the rest clients available.
First of all, you should provide more info on the error - Stacktrace and error message. But 400 code indicates that was a user mistake, meaning that you are sending an invalid request. Since you say that postman request works then compare all the headers that are sent by postman and see if your code misses some hearer. As for the code, instead of coding your own Http client functionality I would suggest using 3d party Http client. Here are a few suggestions:
Apache Http client - very popular and well known 3d party Http Client
OK Http client - Open-source Http client. Here is tutorial
MgntUtils Http client - very simple 3d party HttpClient: Provided in MgntUtils Open source library (written by me). Very simple in use. Take a look at Javadoc. Library itself provided as Maven artifacts and on Git (including source code and Javadoc).

What is format to send a response to an HttpURLConnection.getInputStream() and avoid "Invalid Http Response"?

My server sends a response to an HTTPUrlConnection in this manner:
ServerSocket servSok = new ServerSocket(portNmb);
Socket sok = servSok.accept();
processTheIncomingData(sok.getInputStream());
Writer wrtr = new OutputStreamWriter(sok.getOutputStream());
wrtr.write("<html><body>123 Hello World</body></html>"); // <------- format?
wrtr.flush();
the client
HttpURLConnection conn = (HttpUTLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setDoOutput(true);
conn.setDoInput(true);
sendSomeData(conn.getOutputStream());
String mssg = conn.getResponseMessage(); // <----- Invalid Http Response
conn.getResponseCode() also gives the same "Invalid http response."
I agree with #JBNizet. HTTP is a very complex protocol. You should use a server.
But if you are writing this for a toy project, here is some code to get you started.
Do not use any of this in production :)
String content = "<html><body>123 Hello World</body></html>";
Writer wrtr = new OutputStreamWriter(sok.getOutputStream());
wrtr.write("HTTP/1.1 200 OK\n");
wrtr.write("Content-Type: text/html; charset=UTF-8\n");
//assuming content is pure ascii
wrtr.write("Content-Length: " + content.length() + "\n");
wrtr.write("Connection: close\n\n");
wrtr.write(content);
wrtr.flush();
//then close the connection, do not reuse the connection
//as you might not have consumed the full request content

getting filenotfoundexception while sending json data using java

I am trying to send json data to Influx db using following code:
String url = "http://xx.x.xx.xx:8086/db/monitoring/check_1113?u=root&p=root";
URL obj = new URL(url);
HttpURLConnection conn = (HttpURLConnection) obj.openConnection();
conn.setRequestProperty("Content-Type", "application/json");
conn.setDoOutput(true);
conn.setRequestMethod("PUT");
//String userpass = "user" + ":" + "pass";
//String basicAuth = "Basic " + javax.xml.bind.DatatypeConverter.printBase64Binary(userpass.getBytes("UTF-8"));
//conn.setRequestProperty ("Authorization", basicAuth);
//String data = "{\"format\":\"json\",\"pattern\":\"#\"}";
System.out.println("Data to send: "+"[{\"name\": \"check_222\",\"columns\": [\"time\", \"sequence_number\", \"value\"],\"points\": [["+unixTime+", 1, \"122\"]]}]");
String data = "[{\"name\": \"check_333\",\"columns\": [\"time\", \"sequence_number\", \"value\"],\"points\": [["+14444444444+", 1, \"122\"]]}]";
OutputStreamWriter out = new OutputStreamWriter(conn.getOutputStream());
out.write(data);
out.close();
new InputStreamReader(conn.getInputStream());
System.out.println("Data Sent");
Where xx.xx.xx.xx is the ip of server where influx is deployed and i am using the Ip.
When i do a manual curl with this data (on localhost), the data is sent successfully. curl is provided below:
curl -X POST -d '[{"name": "check_223","columns": ["time", "sequence_number", "value"],"points": [[1445271004000,1,70.8880519867]]}]' 'http://localhost:8086/db/monitoring/series?u=root&p=root'
But when I run the code to send the data via the java program shared above, i get following error:
java.io.FileNotFoundException: http://xx.x.xx.xx:8086/db/monitoring/check_1113?u=root&p=root
at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1834)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1439)
at com.snapdeal.hadoop.monitoring.hdfs1.App.sendJsonDataToInflux(App.java:52)
at com.snapdeal.hadoop.monitoring.hdfs1.App.main(App.java:89)
[INFO - 2015-10-20T16:27:13.152Z] ShutdownReqHand - _handle - About to shutdown
And to add to it, I am using phantomJS to get the data from web page and pass that data in the JSON request. But for simplicity I have hard-coded it at present.
This should be relatively obvious. A 405 indicates that the HTTP Method on the request is not supported by the endpoint. The service you are calling does not support a PUT method.

Java IOException "Unexpected end of file from server" when posting large data

I am trying to post XML data to a server which processes this XML and gives a response back, some times the XML data can be very large and the server takes a while to process it, in those cases i fail to get any response back instead i receive a IOException with the message "Unexpected end of file from server". I am positive the XML being sent to the server is not full of errors, is there anything i can do on my end to make sure this doesn't happen or is this a server side issue? Below is code fragment of the method i call to post the data.
Thanks.
String encodedData="some XML"
String urlString="example.com"
try {
URL url = new URL(urlString);
HttpURLConnection urlConnection;
urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setDoOutput(true);
urlConnection.setDoInput(true);
urlConnection.setRequestMethod("POST");
urlConnection.setRequestProperty("Content-Type", contentType);
urlConnection.setRequestProperty("Content-Length", encodedData.length()+"");
OutputStream os = urlConnection.getOutputStream();
os.write(encodedData.getBytes());
BufferedReader in = new BufferedReader(new InputStreamReader(urlConnection.getInputStream(), "UTF-8"));
StringBuffer sb = new StringBuffer();
String inputLine;
while ((inputLine = in.readLine()) != null) {
sb.append(inputLine);
}
in.close();
} catch (MalformedURLException e) {
logger.debug("MalformedURLException " + e.getMessage());
logger.debug((new StringBuilder()).append("urlString=").append(urlString).toString());
throw (e);
} catch (IOException e) {
logger.debug("IOException " + e.getMessage());
logger.debug((new StringBuilder()).append("urlString=").append(urlString).toString());
throw (e);
}
return sb.toString();
Not much could be done from the client side, it's just a server side issue in which the server takes very long to process the data which results in the servers connection to timeout before it could send a response.

send http request to linux server

I have to send an HTTP request to our C programme which is running on a Linux machine. How can I send an HTTP request in Java to our server which is in C and running on a Linux machine?
public void sendPostRequest() {
//Build parameter string
String data = "width=50&height=100";
try {
// Send the request
URL url = new URL("http://www.somesite.com");
URLConnection conn = url.openConnection();
conn.setDoOutput(true);
OutputStreamWriter writer = new OutputStreamWriter(conn.getOutputStream());
//write parameters
writer.write(data);
writer.flush();
// Get the response
StringBuffer answer = new StringBuffer();
BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String line;
while ((line = reader.readLine()) != null) {
answer.append(line);
}
writer.close();
reader.close();
//Output the response
System.out.println(answer.toString());
} catch (MalformedURLException ex) {
ex.printStackTrace();
} catch (IOException ex) {
ex.printStackTrace();
}
}
The above example is for sending a POST request using a URL.
If you're asking how to send an HTTP request in Java to a web server written in C, you can use the URLConnection class.
try {
// Construct data
String data = URLEncoder.encode("key1", "UTF-8") + "=" + URLEncoder.encode("value1", "UTF-8");
data += "&" + URLEncoder.encode("key2", "UTF-8") + "=" + URLEncoder.encode("value2", "UTF-8");
// Send data
URL url = new URL("http://hostname:80/cgi");
URLConnection conn = url.openConnection();
conn.setDoOutput(true);
OutputStreamWriter wr = new OutputStreamWriter(conn.getOutputStream());
wr.write(data);
wr.flush();
// Get the response
BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String line;
while ((line = rd.readLine()) != null) {
// Process line...
}
wr.close();
rd.close(); } catch (Exception e) { }
The above example is for sending a POST request using a URL.
Also take a look at Sun Tutorial on reading/Writing from/to a URLConnection. The other option is to use Apache HTTPComponents which has examples for the HttpCore and HttpClient module.
If you are looking into implementing the web Server, you will have to handle the Http request yourselves which involves a thread pool, parsing the requests, generating HTML, security, multiple sessions, etc or follow the easy route by using off-the-shelf web server like Apache and seeing which all high-level languages like Perl, Ruby can be used for developing the web application.
For implementing your own Http server, please take a look at Micro-Httpd or tinyHttpd
You may also want to look at Adding Web Interface -C++ application which has a sample code.
From the way your question is worded.. I think you need to know some basic stuff before you can start. Try try googling for a simple guide to how web servers work.
Once you have the basic idea, there are a couple of options for a C programmer:
1) You want your C program to be running continuously, waiting for a request from your Java.
In this case, you will have to code your C program to open a Socket and Listen for connections. See http://www.linuxhowtos.org/C_C++/socket.htm for example.
OR
2) You have a web Server on your server which will run your C program each time a particular request is made? In this case, you will have to code your C as a CGI program. See http://www.cs.tut.fi/~jkorpela/forms/cgic.html for example.
Hint: (2) is much easier!

Categories