Forwarding http package in java - java

I'm trying to write a HTTP proxy-server in java. My application takes a GET request from a browser and forwards it to its destination. I would like to read the headers of response package and then forward it back to the browser. This works great for me with text/html-content aslong as its not encoded in gzip. I've tried multiple ways to do this and I'm currently using a DataInputStream and a DataOutputStream but the browser only shows weird symbols.
Here is a simplified version of the code:
ArrayList<String> headerlist = new ArrayList<String>();
InputStream input = clientsocket.getInputStream();
dis = new DataInputStream(input);
serverinputstream = new InputStreamReader(input);
bufferreader = new BufferedReader(serverinputstream);
while(!(line = bufferedreader.readLine()).equals("")) {
headerlist.add(line);
}
PrintWriter pw = new PrintWriter(serveroutputstream, false);
DataOutputStream out = new DataOutputStream(serveroutputstream);
for (int i = 0; i < headerlist.size(); i++) {
pw.println(headerlist.get(i));
}
pw.println();
int bit;
while((bit = dis.read()) != -1) {
out.writeByte(bit);
}
out.flush();
dis.close();
out.close();
This code only handles data that isnt plain text but it doesnt seem to be working. Should I use another method or I am just doing something wrong?

I think you may be overcomplicating things a bit. Your proxy is just forwarding a request on to another destination. There's no reason for it to care about whether it is forwarding text or binary data. It should make no difference.
There's also no reason to read and write the headers individually. All you should need to do is copy the entire request body to the new output-stream.
What about something like:
//...
InputStream input = clientsocket.getInputStream();
streamCopy(input, serveroutputstream);
//...
public void streamCopy(InputStream in, OutputStream out) throws IOException {
int read = 0;
byte[] buffer = new byte[4096];
while ((read = in.read(buffer)) != -1) {
out.write(buffer, 0, read);
}
}

Related

Sending large files over socket

I got working over socket file sender, it worked perfectly, but I couldn't send large files with it. Always got heap error. Then I changed the code of client, so it would send file in chunks. Now I can send big files, but there is new problem. Now I recieve small files empty and larger files for example videos can't be played. Here is the code of client that sends file:
public void send(File file) throws UnknownHostException, IOException {
// Create socket
hostIP = "localhost";
socket = new Socket(hostIP, 22333);
//Send file
FileInputStream fis = new FileInputStream(file);
BufferedInputStream bis = new BufferedInputStream(fis);
DataInputStream dis = new DataInputStream(bis);
OutputStream os = socket.getOutputStream();
//Sending size of file.
DataOutputStream dos = new DataOutputStream(os);
dos.writeUTF(file.getName() + ":" + userName);
byte[] arr = new byte[1024];
try {
int len = 0;
while ((len = dis.read(arr)) != -1) {
dos.write(arr, 0, len);
}
} catch (IOException ex) {
ex.printStackTrace();
}
dos.flush();
socket.close();
}
and here is the server code:
void start() throws IOException {
// Starts server on port.
serverSocket = new ServerSocket(port);
int bytesRead;
while (true) {
connection = serverSocket.accept();
in = connection.getInputStream();
clientData = new DataInputStream(in);
String[] data = clientData.readUTF().split(":");
String fileName = data[0];
String userName = data[1];
output = new FileOutputStream("C:/" + fileName);
long size = clientData.readLong();
byte[] buffer = new byte[1024];
// Build new file
while (size > 0 && (bytesRead = clientData.read(buffer, 0, (int) Math.min(buffer.length, size))) != -1) {
output.write(buffer, 0, bytesRead);
size -= bytesRead;
}
output.close();
}
}
You failed to write out the length of the file to the stream in the client:
long size = clientData.readLong();
So that call in the server is reading the first 8 bytes of the actual file and who knows what that quantity is. You don't have to read the length from the stream since you only wrote a single file. After reading the filename, and username (not very secure is it?) you can just read the stream until EOF. If you ever wanted to send multiple files over the same open socket then you'd need to know the length before reading the file.
Also your buffers for reading are way to small. You should be at a minimum of 8192 instead of 1024. And you'll want to put all .close() in a finally block to make sure your server and clients shutdown appropriately if there is an exception ever.

Chunked input stream ended unexpectedly

I have tried to write a program that gets a file from web server in a chunked format. I am trying to use ChunkedInputStream class in HTTP 3.0 API. When I run the code, it gives me "chucked input stream ended unexpectedly" error. What am I doing wrong? Here is my code:
HttpClient client = new DefaultHttpClient();
HttpGet getRequest = new HttpGet(location);
HttpResponse response = client.execute(getRequest);
InputStream in = response.getEntity().getContent();
ChunkedInputStream cis = new ChunkedInputStream(in);
FileOutputStream fos = new FileOutputStream(new ile("session_"+sessionID));
while(cis.read() != -1 )
{
fos.write(cis.read());
}
in.close();
cis.close();
fos.close();
Don't use the ChunkedInputStream, as axtavt suggests, but there is another problem. You are skipping every odd numbered byte. If the data is an even number of bytes you will write the -1 that means EOS and then do another read. The correct way to copy a stream:
byte[] buffer = new byte[8192];
int count;
while ((count = in.read(buffer)) > 0)
{
out.write(buffer, 0, count);
}
Are you sure that you need to use ChunkedInputStream in this case?
I think HttpClient should handle chuncked encoding internally, therefore response.getEntity().getContent() returns already decoded stream.

Java socket transfer, buffered input and output

Ok.... Trying to learn java on my own, been having trouble with this for awhile. I'm trying to transfer a large file over the network using sockets and buffered input and output streams. Doesn't matter what size file I try to transfer. Hopefully I posted my code correctly, I know theres probably many problems with this code, although it compiles and runs ok, I get an IndexOutOfBoundsException the second the client and server go into the while loops, the server gets it during the first bis.read(buf,0,len) and the client gets it during the while(off = fis.read(buf,0,len)..... Any help would be greatly appreciated
//Server Receive code receive method and main for testing
public File receive(Socket socket) throws IOException{
//temporarily hard coded filename
File file = new File("C:\\users\\tom5\\desktop\\sales\\input.dat");
DataInputStream dis = new DataInputStream(socket.getInputStream());
FileOutputStream fos = new FileOutputStream(file);
BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());
//reads file length from datainputstream
int len = dis.readInt();
dis.close();
int bytesRead=0;
//create buffer
byte[]buf = new byte[4092];
int off = 0;
//read from BufferedInputStream and write to FileOutputStream?
while(bytesRead < len) {
bis.read(buf,0,len);
fos.write(buf,0,len);
bytesRead++;
}
fos.close();
bis.close();
return file;
}
public static void main(String[]args) throws IOException{
Server server = new Server();
Socket socket =server.accept();
File file = server.receive(socket);
}
}
//Client sending code
public void send(Socket socket,File file) throws IOException{
FileInputStream fis = new FileInputStream(file);
DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
BufferedOutputStream bos = new BufferedOutputStream(socket.getOutputStream());
int len = (int)file.length();
dos.writeInt(len);
dos.flush();
dos.close();
System.out.println(file.length());
byte[]buf = new byte[4092];
int off= 0;
while((off = fis.read(buf,0,len)) != -1 ){
bos.write(buf,0,len);
}
}
public static void main(String[]args) throws UnknownHostException, IOException{
Client client = new Client();
Socket socket =client.connect("localhost",1055);
File file = new File("C:\\users\\tom5\\desktop\\movie.avi");
}
}
while(bytesRead < len) {
bis.read(buf,0,len);
fos.write(buf,0,len);
bytesRead++;
}
You're trying to read len bytes into buf, which is larger than its length, and you're incrementing bytes by 1 each time even though read can read multiple bytes. It should be more like:
while(bytesRead < len) {
int n = bis.read(buf);
fos.write(buf, 0, n);
bytesRead += n;
}
or if there's the possibility of extra bytes after the file you don't want to read:
while(bytesRead < len) {
int n = bis.read(buf, 0, Math.min(buf.length, len - bytesRead));
fos.write(buf, 0, n);
bytesRead += n;
}
There is a similar problem in the write method. You're storing the return value in off but you never use it.
You are wrapping the stream twice, once as dis and once as bis. This means that dis is not buffered but when you close it, you close the underlying stream.
I suggest you wrap use ONLY
DataInputStream dis = new DataInputStream(new BufferedInputStream(socket.getInputStream()));
If you want an efficient buffer size, I suggest you a power of 2, i.e 4096 rather than 4092.
A #fgb notes: You correct use the length read() on the sending size but ignore it on the receiving size (The irony being that you usually get the size you ask for when reading a file, but not so much when reading a socket)
Consider using one common InputStream to OutputStream copier method which works in both situations e.g. like IOUtils.copy().
You are using fixed buffer size. Try this:
byte[] mybytearray = new byte[(int) myFile.length()];

Java File Upload using socket,Percentage of uploded file required?

Hii i am uploading a file to server using socket and i need the percent of file loaded?how can i do that?i have the maximun value i.e the file length ,how can i get how much file has been uploaded?
FileInputStream fis = new FileInputStream(fil);
BufferedInputStream in = new BufferedInputStream(fis);
BufferedOutputStream out = new BufferedOutputStream(skt.getOutputStream());
//Write the file to the server socket
int i;
while ((i = in.read()) != -1) {
publishProgress(???);
out.write(i);
System.out.println(i);
}
I need to pass the length of file uploded in the publishProgress method.
using buffered copying
FileInputStream fis = new FileInputStream(fil);
BufferedInputStream in = new BufferedInputStream(fis);
BufferedOutputStream out = new BufferedOutputStream(skt.getOutputStream());
//Write the file to the server socket
int i;
int written = 0;
byte[] buf = new byte[512];
while ((i = in.read(buff)) != -1) {
out.write(buff,0,i);
written += i;
publishProgress((double)written/length);
//passing a double value from 0-1 to say how much is transmitted (length is length of file)
System.out.println(buff+", "+i);
}
To do this you need to do one of a couple of things:
Use a Flash uploader such as swfupload (see http://demo.swfupload.org/Documentation/) as these typically provide access to upload progress of this sort.
Provide a back channel of your own: perform the form submit with Ajax and then while the form submit occurs you run a javascript timer that hits a URL on the server with a key of some kind that corresponds to the upload. The URL on the server looks up how much of the file has been uploaded and returns that number and you pass that through to your uploadProgress method.
Below is your modified code. written holds the number of ints written to the socket.
FileInputStream fis = new FileInputStream(fil);
BufferedInputStream in = new BufferedInputStream(fis);
BufferedOutputStream out = new BufferedOutputStream(skt.getOutputStream());
//Write the file to the server socket
int i;
int written = 0;
while ((i = in.read()) != -1) {
out.write(i);
publishProgress(++written);
System.out.println(i);
}
javax.swing.ProgressMonitorInputStream

HTTPRequest Get Data in Java

I would like to do an HTTPRequest in Java and then get the data from the server (it's not a webpage the data come from a database).
I try this but the getData doesn't work.
Do you know how I can get the Data?
public static void main(String args[]) throws Exception {
URL url = new URL("http://ip-ad.com");
HttpURLConnection httpCon = (HttpURLConnection) url.openConnection();
System.out.println("Request method is " + httpCon.getData());
}
Thanks
You can get the response body of the web request as an InputStream with:
httpCon.getInputStream();
From there it depends on what the format of the response data is. If it's XML then pass it to a library to parse XML. If you want to read it into a String see: Reading website's contents into string. Here's an example of writing it to a local file:
InputStream in = httpCon.getInputStream();
OutputStream out = new FileOutputStream("file.dat");
out = new BufferedOutputStream(out);
byte[] buf = new byte[8192];
int len = 0;
while ((len = in.read(buf)) != -1) {
out.write(buf, 0, len);
}
out.close();
You can use http://jersey.java.net/ .
It's a simple lib for your needs.

Categories