Clarification about REST request in Java and output/input streams - java

I have to implement a post request in plain Java.
I have read the following question:
How to make a post request to a json RESTful Service from Java?
this is a part of the example
String url = "https://myStore.com/REST-API/";
String requestBody = "{\"searchProduct\": \"" + searchProduct + "\"}";
URL obj = new URL(url);
HttpsURLConnection connection = (HttpsURLConnection) obj
.openConnection();
connection.setDoOutput(true);
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "application/json");
OutputStream outputStream = connection.getOutputStream();
outputStream.write(requestBody.getBytes());
My question is: why the parameters are written on the output stream? As far as I know, output stream is for collecting the output of a request, not to make it.
So just a curiosity, consider that I am obviously not skilled on this.

First let explain how HttpConnectionURL works.
When you want to request data from a server,
you first create a connection to that server.
Then you write data to the connection (request)
and finally read data from the connection (response).
So to write data to the connection you get a reference to the Connection's OutputStream and write data to it.
OutputStreamWriter writer = new OutputStreamWriter(
connection.getOutputStream());
writer.write("message=" + message);
To read data from the connection you get a reference to the Connection's InputStream and read data from it.
InputStreamReader reader = new InputStreamReader(connection.getInputStream());
reader.read();
Generally you use OutputStream when data is flowing out of your program (to file,network etc.,) and InputStream when data is flowing into your program (from file,network etc.,).
I think this will give you the clarity you are looking for.
This answer explains in detail how HttpConnectionURL works

The goal of InputStream and OutputStream is to abstract streams. By stream, I mean the way of the processed data (Input of the program or Output)
If the application receives information from the stream, use the InputStream. If it sends data then OutputStream
InputStreamused to read data from a source.
var input = new FileInputStream("input.txt");// Read the data
OutputStreamused for writing data to a destination.
var output = new FileOutputStream("output.txt");// Write the data
You should read answers in the related question : There are more explanations.

Related

How to send info in body using post method in java class file

I requested to send some parameters from java file using post method. I did
String urlParameters = "param1=a&param2=b&param3=c";
URL url = new URL("http://testing/index.jsp");
URLConnection conn = url.openConnection();
conn.setDoOutput(true);
OutputStreamWriter writer = new OutputStreamWriter(conn.getOutputStream());
writer.write(urlParameters);
writer.flush();
But from receiver's end asks me to send it in body instead of url parameter. I am not sure what I am doing wrong. Please explain me how this code will work and what changes has to be done if I want to send info in request body.
i believe you either need to call the connect() method on the URLConnection at the end, or call a method that would cause the connect to be called for you, like fetching the resulting input stream.
Also you should think about what format the body should be in. Often people like to use standard formats like json, but you will have to decide that between you and the people implementing the server.

Using HttpURLConnection to POST in Java

I've read lots and tried lots relating to HTTP POSTS using HttpURLConnection and almost everything I come across has a similar structure which starts with these 3 lines:
url = new URL(targetURL);
connection = (HttpURLConnection)url.openConnection();
connection.setRequestMethod("POST");
When I try this I always get a "Connection Already Established" exception when calling setRequestMethod, which makes perfect sense as I'm clearly calling openConnection before setting the request type. Although reading the docs openConnection doesn't actually open the connection in theory.
There are several posts about this problem on SO such as this and this. I don't understand however why every piece of advice about how to write this code has these 3 lines in this order.
I'm guessing this code must work in most instances as someone must have tested it, so why doesn't this code work for me? How should I be writing this code?
I am aware these are other libraries I can use out there, I'm just wondering why this doesn't work.
Why the suspect code in the question has been duplicated all over the internet is something I can't answer. Nor can I answer why it seems to work for some people and not others. I can however answer the other question now, mainly thanks to this link that Luiggi pointed me to.
The key here is understanding the intricacies of the HttpURLConnection class. When first created the class defaults to a "GET" request method, so nothing needs to be changed in this instance. The following is rather unintuitive, but to set the request method to "POST" you should not call setRequestMethod("POST"), but rather setDoOutput(true) which implicitly sets the request method to post. Once you've done that you're good to go.
Below, I believe, is what a post method should look like. This is for posting json, but can obviously be altered for any other content type.
public static String doPostSync(final String urlToRead, final String content) throws IOException {
final String charset = "UTF-8";
// Create the connection
HttpURLConnection connection = (HttpURLConnection) new URL(urlToRead).openConnection();
// setDoOutput(true) implicitly set's the request type to POST
connection.setDoOutput(true);
connection.setRequestProperty("Accept-Charset", charset);
connection.setRequestProperty("Content-type", "application/json");
// Write to the connection
OutputStream output = connection.getOutputStream();
output.write(content.getBytes(charset));
output.close();
// Check the error stream first, if this is null then there have been no issues with the request
InputStream inputStream = connection.getErrorStream();
if (inputStream == null)
inputStream = connection.getInputStream();
// Read everything from our stream
BufferedReader responseReader = new BufferedReader(new InputStreamReader(inputStream, charset));
String inputLine;
StringBuffer response = new StringBuffer();
while ((inputLine = responseReader.readLine()) != null) {
response.append(inputLine);
}
responseReader.close();
return response.toString();
}
As per https://stackoverflow.com/a/3324964/436524, you need to call connection.setDoOutput(true) for it to expect a POST request.
This makes your code like this:
url = new URL(targetURL);
connection = (HttpURLConnection)url.openConnection();
connection.setDoOutput(true);

new to android - understanding the use of OutputStreamWriter in web service calls

I have been going over the following tutorial and came across this code which I do not understand the purpose of:
URLConnection conn = url.openConnection();
conn.setDoOutput(true);
OutputStreamWriter wr = new OutputStreamWriter(conn.getOutputStream());
wr.write( data );
wr.flush();
I don't know what is the purpose of the above code and where is it writing this data to...
From what I could gather, the documentation states that it converts character to bytes... but then it writes it to some where... not sure why this is.
It is basically used for turning a character stream into a byte stream.
The byte streams and character streams are incompatible for linking as the first one operates on 8-bit ASCII characters and the other on 16-bit Unicode characters. To link them explicitly, two classes exist in java.io package, InputStreamReader and OutputStreamWriter.
InputStreamReader links a byte stream, with the character stream BufferedReader (on reading-side) .
Whereas with the OutputStreamWriter, the characters of 2-bytes are encoded (converted) into bytes of 1-byte (InputStreamReader does it other way – bytes to characters).
For a Java program to interact with a server-side process it simply must be able to write to a URL, thus providing data to the server. It can do this by following these steps:
1.Create a URL.
2.Retrieve the URLConnection object.
3.Set output capability on the URLConnection.
4.Open a connection to the resource.
5.Get an output stream from the connection.
6.Write to the output stream.
7.Close the output stream.
Now in the snippet you provided ,
OutputStreamWriter wr = new OutputStreamWriter(conn.getOutputStream());
creates an output stream on the connection and opens an
OutputStreamWriter on it--Step 5 If the URL does support output, then
this method returns an output stream that is connected to the input
stream of the URL on the server side — the client's output is the
server's input.If the URL does not support output, getOutputStream
method throws an UnknownServiceException.
And
wr.write( data );
wr.close();
wr.flush();
It writes the required information to the output stream and closes the
stream. The data written to the output stream on the client side is
the input on the server side.
It's writing it to the output stream of the URLConnection - which is basically used for the body of an HTTP request (assuming it's an HTTP URL, of course).

reading bytes from web site

I am trying to create a proxy server.
I want to read the websites byte by byte so that I can display images and all other stuff. I tried readLine but I can't display images. Do you have any suggestions how I can change my code and send all data with DataOutputStream object to browser ?
try{
Socket s = new Socket(InetAddress.getByName(req.hostname), 80);
String file = parcala(req.url);
DataOutputStream out = new DataOutputStream(clientSocket.getOutputStream());
BufferedReader dis = new BufferedReader(new InputStreamReader(s.getInputStream()));
PrintWriter socketOut = new PrintWriter(s.getOutputStream());
socketOut.print("GET "+ req.url + "\n\n");
//socketOut.print("Host: "+req.hostname);
socketOut.flush();
String line;
while ((line = dis.readLine()) != null){
System.out.println(line);
}
}
catch (Exception e){}
}
Edited Part
This is what I should have to do. I can block banned web sites but can't allow other web sites in my program.
In the filter program, you will open a TCP socket at the specified port and wait for connections. If a
request comes (i.e. the client types a URL to access a web site), the application will process it to
decide whether access is allowed or not and then, using the same socket, it will send the reply back
to the client. After the client opened her connection to WebPolice (and her request has been checked
and is allowed), the real web page needs to be shown to the client. Therefore, since the user already gave her request, now it is WebPolice’s turn to forward the request so that the user can get the web page. Thus, WebPolice acts as a client and requests the web page. This means you need to open a connection to the web server (without closing the connection to the user), forward the request over this connection, get the reply and forward it back to the client. You will use threads to handle multiple connections (at the same time and/or at different times).
I don't know what exactly you're trying to do, but crafting an HTTP request and reading its response incorporates somewhat more than you have done here. Readline won't work on binary data anyway.
You can take a look at the URLConnection class (stolen here):
URL oracle = new URL("http://www.oracle.com/");
URLConnection yc = oracle.openConnection();
BufferedReader in = new BufferedReader(new InputStreamReader(yc.getInputStream()));
Then you can read textual or binary data from the in object.
Read line will treat the line read as a String, so unless you want to mess around with conversions over to bytes, I wouldn't recommend that.
I would just read bytes until you can't read anymore, then write them out to a file, this should allow you to grab the images, keeping file headers intact which can be important when dealing with files other than text.
Hope this helps.
Instead of using BufferedReader you can try to use InputStream.
It has several methods for reading bytes.
http://docs.oracle.com/javase/6/docs/api/java/io/InputStream.html

Reading from a URLConnection

I have a php page in my server that accepts a couple of POST requests and process them. Lets say it's a simple page and the output is simply an echoed statement. With the URLConnection I established from a Java program to send the POST request, I tried to get the input using the input stream got through connection.getInputStream(). But All I get is the source of the page(the whole php script) and not the output it produces. We shall avoid socket connections here. Can this be done with Url connection or HttpRequest? How?
class htttp{
public static void main(String a[]) throws IOException{
URL url=new URL("http://localhost/test.php");
URLConnection conn = url.openConnection();
//((HttpURLConnection) conn).setRequestMethod("POST");
conn.setDoOutput(true);
conn.setDoInput(true);
OutputStreamWriter wr = new OutputStreamWriter(conn.getOutputStream());
wr.write("Hello");
wr.flush();
wr.close();
InputStream ins = conn.getInputStream();
InputStreamReader isr = new InputStreamReader(ins);
BufferedReader in = new BufferedReader(isr);
String inputLine;
String result = "";
while( (inputLine = in.readLine()) != null )
result += inputLine;
System.out.print(result);
}
}
I get the whole source of the webpage test.php in result. But I want only the output of the php script.
The reason you get the PHP source itself, rather than the output it should be rendering, is that your local HTTP server - receiving your request targeted at http://localhost/test.php - decided to serve back the PHP source, rather than forward the HTTP request to a PHP processor to render the output.
Why this happens? that has to do with your HTTP server's configuration; there might be a few reasons for that. For starters, you should validate your HTTP server's configuration.
Which HTTP server are you using on your machine?
What happens when you browse http://localhost/test.php through your browser?
The problem here is not the Java code - the problem lies with the web server. You need to investigate why your webserver is not executing your PHP script but sending it back raw. You can begin by testing using a simple PHP scipt which returns a fixed result and is accessed using a GET request (from a web browser). Once that is working you can test using the one that responds to POST requests.

Categories

Resources