So I'm currently doing a project where we have to accept and process HTTP requests, which I have done successfully.
There's an optional task of also accepting HTTPS requests, which I'm confused as to how I'd go about that, preferably using standard Java.
For regular HTTP, I'm using a regular ServerSocket accept(), then reading from the socket through an InputStreamReader in its InputStream, like so:
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
Problem is, when I try with HTTPS, the message I can read on the first line of the HTTPS GET is just garbled characters. Is there a way to process this as well?
Related
I am creating a simple Client-Server application and facing some weird behaviour when passing messages through a Socket: When the Client writes to the server, the message is passed correctly, however when the server sends a response, whichever value is sent through the socket seems to get duplicated...
Here is a sample code of what the server does:
.
.
.
public void respond(Socket socket)
{
try
{
InputStreamReader inStream = new InputStreamReader( socket.getInputStream() );
PrintWriter outStream = new PrintWriter(
new OutputStreamWriter( socket.getOutputStream(), "UTF-16" ) );
outStream.write("Message received\n");
outStream.flush();
.
.
.
}
catch (Exception e) { /* Do something */ }
}
.
.
.
Server and Client are currently running on the same machine.
Furthermore, encoding seems to be no issue when writing from client to server, but it is when writing from server to client: If I specify any other (or no) encoding than UTF-16 for the OutputStreamWriter, the Client won't be able to parse the message correctly.
Does any of you guys have an idea why that might be?
The character encoding on each end of the conversation needs to be the same: the Charset used for encoding by InputStreamReader at the client must match that used by the OutputStreamWriter at the server (and vice-versa).
If you don't specify one, it is going to use the JVM's default.
When you didn't provided your client's code, the fact that the server is using the default Charset to read and UTF-16 to write makes me think there is a potential mismatch.
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
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.
I am sending a request on a server URL but I am getting File not found exception but when I browse this file through a web browser it seems fine.
URL url = new URL(serverUrl);
connection = getSecureConnection(url);
// Connect to server
connection.connect();
// Send parameters to server
writer = new BufferedWriter(new OutputStreamWriter(connection.getOutputStream(), "UTF-8"));
writer.write(parseParameters(CoreConstants.ACTION_PREFIX + actionName, parameters));
writer.flush();
// Read server's response
reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
when I try to getInputStream then it throws error file not found.
It is an .aspx Controller page.
If the request works fine in a browser but not in code, and you've verified that the URL is the same, then the problem probably has something to do with how you are sending your parameters to the server. Specifically, this part:
writer.write(parseParameters(CoreConstants.ACTION_PREFIX + actionName, parameters));
Perhaps there is a bug in the parseParameters() function?
But more generally, I would recommend using something a bit higher-level than a raw URLConnection. HtmlUnit and HttpClient are both fine choices, particularly since it seems like your request is a fairly simple one. I've used both to perform similar client/server interaction in a number of apps. I suggest revising your code to use one of these libraries, and then see if it still produces the error.
Ok finally I have found that the problem was at IIS side it has been resolved in .Net 4.0. for previous version go to your web.config and specify validateRequest==false
I'm running a Tomcat server with some virtual hosts and I need to POST some data to a servlet on this server from another servlet on another server. Because the server that I am POSTing to uses virtual hosts just referring to this host by it's IP address will cause problem (it won't know what virtual host I'm trying to talk to).
Here is the code I have for running an HTTP 1.0 POST to "sub.example.com", but in this example "example.com" only knows to route the request to the right sub domain if it is configured as the default. This is because of the requirement that a Socket be passed a InetAddress and not the host name.
String host = "sub.example.com";
int port = 80;
String path = "/Servlet";
StringBuilder data = new StringBuilder();
data.append(URLEncoder.encode("NameA", "UTF-8")).append('=').append(URLEncoder.encode("ValueA", "UTF-8"));
data.append('&').append(URLEncoder.encode("NameB", "UTF-8")).append('=').append(URLEncoder.encode("NameB", "UTF-8"));
InetAddress addr = InetAddress.getByName(host);
Socket socket = new Socket(addr, port);
BufferedWriter wr = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream(), "UTF8"));
wr.write("POST "+path+" HTTP/1.0\r\n");
wr.write("Content-Length: "+data.length()+"\r\n");
wr.write("Content-Type: application/x-www-form-urlencoded\r\n");
wr.write("\r\n");
// Send data
wr.write(data.toString());
wr.flush();
wr.close();
Any ideas?
You may want to consider using Apache HttpClient rather than performing raw socket communications.
You might consider making life a little easier on yourself by using one of the higher-level HTTP clients available in Java, such as HttpURLConnection. You'll still have to handle constructing the multipart/form-encoded request body, but it abstracts away much of the hassle of constructing a well-formed request, and brings your code closer to the true domain.