Send Multiple POST Requests Through a DataOutputStream in Java - java

I am trying to use a for loop to send multiple POST requests through a DataOutputStream and then close it. At the moment, only the first index of the "trades" array list is sent to the website. Any other indexes are ignored and I'm assuming they are not being sent. I wonder if I am properly flushing the stream? Thank you!!!
Examples of trades values: "101841599", "101841801"
Example of code value: 85e4c22
Snippet of my code:
private ArrayList<String> trades = new ArrayList<String>();
private String code;
String url = "http://www.dota2lounge.com/ajax/bumpTrade.php";
URL obj = new URL(url);
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("POST");
con.setRequestProperty("Accept-Language", "en-US,en;q=0.8");
con.setRequestProperty("Cookie", cookie);
con.setDoOutput(true);
DataOutputStream wr = new DataOutputStream(con.getOutputStream());
for(int i=0; i<trades.size(); i++){
wr = new DataOutputStream(con.getOutputStream());
wr.writeBytes("trade=" + trades.get(i) + "&code=" + code);
wr.flush();
System.out.println("again");
}
wr.flush();
wr.close();

It turns out I had to actually get the response for it to properly close the connection before I started a new one. Appending these lines to the end of the for loop fixed the issue:
int nothing = con.getResponseCode();
String morenothing = con.getResponseMessage();

From the HttpURLConnection javadoc:
"Each HttpURLConnection instance is used to make a single request but the underlying network connection to the HTTP server may be transparently shared by other instances."
So if you want to send multiple requests, then for each request call obj.openConnection(), set the connection settings, open the OutputStream, and write the data. Your Java runtime is permitted to keep the actual connection open to save time and bandwidth.

Related

Java doesn't send HTTP POST Request

I'm implementing some simple java class in order to send an HTTP Request with POST method and also another java class in order to receive it.
The server works fine when I make a POST request by means of my browser(Chrome), or an application(I have used Postman in this case) but it ends up with problem when I send HTTP Request with java!
My sending HTTP class is "Sender.java", containing the following snippet:
String url = "http://localhost:8082/";
URL obj = new URL(url);
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
// Setting basic post request
con.setRequestMethod("POST");
//con.setRequestProperty("Accept-Language", "en-US,en;q=0.5");
//con.setRequestProperty("Content-Type","text/plain");
// Send post request
con.setDoOutput(true);
OutputStream os = con.getOutputStream();
os.write("Just Some Text".getBytes("UTF-8"));
os.flush();
os.close();
//connect to the Server(resides at Server.java)
con.connect();
I have commented some lines of code setting Headers like "Accept-Language" and "Content-Type" because I don't know whether or not are these headers required for the java program to work out?
The server is another java program named "Server.java". Here is the snippet related to reading HTTP Request made by the Sender.java(if need be).
int servPort = 8082;
// Create a server socket to accept HTTP client connection requests
HttpServer server = HttpServer.create(new InetSocketAddress(servPort), 0);
System.out.println("server started at " + servPort);
server.createContext("/", new PostHandler());//PostHandler implements HttpHandler
server.setExecutor(null);
server.start();
All I want is to send a plaintext as the body of my HTTP Request with the Post method. I have read plenty of sites and even related questions at this site. But it still doesn't work out. In other words, whenever I create an HTTP Request from "Sender.java", nothing appears at "Server.java". I just want to know what's wrong with my snippets and how should I fix that?
I tested this and it's working:
//Sender.java
String url = "http://localhost:8082/";
URL obj = new URL(url);
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setRequestMethod("POST");
con.setDoOutput(true);
OutputStream os = con.getOutputStream();
os.write("Just Some Text".getBytes("UTF-8"));
os.flush();
int httpResult = con.getResponseCode();
con.disconnect();
As you can see, connect is not necessary. The key line is
int httpResult = con.getResponseCode();
When you send a POST form using the browser, it sends the form in a certain format, defined in RFC1866, you have to recreate this on Java when making a post request.
With this format, its important you set the Content-Type header to application/x-www-form-urlencoded, and pass the body as you would do in a url with a get request.
Borrowing some code of my previous answer to POST in Java:
URL obj = new URL(url);
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
// Setting basic post request
con.setRequestMethod("POST");
Map<String,String> form = new HashMap<>();
// Define the fields
form.put("username", "root");
form.put("password", "sjh76HSn!"); // This is a fake password obviously
// Build the body
StringJoiner sj = new StringJoiner("&");
for(Map.Entry<String,String> entry : arguments.entrySet())
sj.add(URLEncoder.encode(entry.getKey(), "UTF-8") + "="
+ URLEncoder.encode(entry.getValue(), "UTF-8"));
byte[] out = sj.toString().getBytes(StandardCharsets.UTF_8);
int length = out.length;
// Prepare our `con` object
con.setFixedLengthStreamingMode(length);
con.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
con.connect();
try (OutputStream os = con.getOutputStream()) {
os.write(out);
}
Maybe “localhost” in the sender url does not resolve to the same ip that the server binds to? Try changing to 127.0.0.1 or your actual IP address.
try with PrintStream
String url = "http://localhost:8082/";
URL obj = new URL(url);
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
// Setting basic post request
con.setRequestMethod("POST");
//con.setRequestProperty("Accept-Language", "en-US,en;q=0.5");
//con.setRequestProperty("Content-Type","text/plain");
// Send post request
con.setDoOutput(true);
OutputStream os = con.getOutputStream();
java.io.PrintStream printStream = new java.io.PrintStream(os);
printStream.println("Just Some Text");
con.getInputStream();//Send request
os.flush();
os.close();

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

Send POST and read streaming response

I have a server that takes a POST request and answers with a data stream. I have seen that on URL I can open a connection or a stream. A stream, however, has no method for writing out data:
URL url = new URL("...");
url.openConnection(); //either I open a connection which has a output stream, but no input
url.openStream(); //or I open a stream, but I cannot write anything out
How can I solve this problem elegantly?
Sample code snippet to use OutputStream.
Note: You can set content types & send some URL parameters to the URL only.
URL obj = new URL(url);//some url
HttpURLConnection con = (HttpURLConnection) obj.openConnection();
con.setDoOutput(true);
DataOutputStream wr = new DataOutputStream(con.getOutputStream());
String urlParams = "fName=xyz&lname=ABC&pin=12345"; // some parameters
wr.writeBytes(urlParams);
wr.flush();
wr.close();
Have a look at detailed explanation in this article1 and article2

HTTP POST is not working from Java

I am trying to do an http post. Same code was working.But now it is not hitting my servlet now, but giving http response code 200. From browser same url is hitting the servlet. Is there anything that restricting my post?. Please help me on it. Sorry for bad english.
int timeout=3000;
String url="http://localhost:8020/WiCodeDynamic/WiCode?json=";
String requestUrl="{\"vspCredentials\":{\"id\":\"TET\",\"password\":\"test\"}}";
URL x = new URL(url);
HttpURLConnection connection =(HttpURLConnection)x.openConnection();
connection.setRequestMethod("POST");
//;charset=utf-8
connection.setRequestProperty("Content-type","application/json");
connection.setDoOutput(true);
connection.setConnectTimeout(timeout);
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(connection.getOutputStream()));
bw.write(requestUrl);
bw.flush();
int resp_code = connection.getResponseCode();
String resp_msg = connection.getResponseMessage();
System.out.println("resp_code="+resp_code);
System.out.println("resp_msg="+resp_msg);
brs,
Only a minor mistake. Move the json= from the end of your URL to the beginning of your POST request (requestUrl) and you should be fine.
Also I suggest you use URLEncoder.encode to escape the string you are transfering properly.

TCP connection is not reused for HTTP requests with HttpURLConnection

I'm have created an application which sends GET requests to a URL, and then downloads the full content of that page.
The client sends a GET to e.g. stackoverflow.com, and forwards the response to a parser, which has the resposibility to find all the sources from the page that needs to be downloaded with subsequent GET requests.
The method below is used to send those GET requests. It is called many times consecutively, with the URLs returned by the parser. Most of those URLs are located on the same host, and should be able to share the TCP connection.
public static void sendGetRequestToSubObject(String RecUrl)
{
URL url = new URL(recUrl.toString());
URLConnection connection = url.openConnection ();
InputStreamReader isr = new InputStreamReader(connection.getInputStream());
}
Each time this method is called, a new TCP connection is created (with a TCP 3-way handshake) and the GET is then sent on that connection. But I want to reuse the TCP connections, to improve performance.
I guess that since I create a new URL object each time the method is called, this is the way it going to work...
Maybe someone can help me do this in a better way?
Thanks!
HttpURLConnection will reuse connections if it can!
For this to work, several preconditions need to be fulfilled, mostly on the server side. Those preconditions are described in the article linked to above.
Found the problem! I was not reading the input stream properly. This caused the input stream objects to hang, and they could not be reused.
I only defined it, like this:
InputStreamReader isr = new InputStreamReader(connection.getInputStream());
but I never read from it :-)
I changed the read method as well. Instead of a buffered reader I stole this:
InputStream in = null;
String queryResult = "";
try {
URL url = new URL(archiveQuery);
HttpURLConnection urlConn = (HttpURLConnection) url.openConnection();
HttpURLConnection httpConn = (HttpURLConnection) urlConn;
httpConn.setAllowUserInteraction(false);
httpConn.connect();
in = httpConn.getInputStream();
BufferedInputStream bis = new BufferedInputStream(in);
ByteArrayBuffer baf = new ByteArrayBuffer(50);
int read = 0;
int bufSize = 512;
byte[] buffer = new byte[bufSize];
while(true){
read = bis.read(buffer);
if(read==-1){
break;
}
baf.append(buffer, 0, read);
}
queryResult = new String(baf.toByteArray());
} catch (MalformedURLException e) {
// DEBUG
Log.e("DEBUG: ", e.toString());
} catch (IOException e) {
// DEBUG
Log.e("DEBUG: ", e.toString());
}
}
From here: Reading HttpURLConnection InputStream - manual buffer or BufferedInputStream?

Categories