Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Simple web proxy in Java

I am trying to write a simple web proxy in java which accepts both GET and POST requests. I wrote the following code:

import java.net.*;
import java.io.*;
import java.nio.CharBuffer;
import java.util.logging.Level;
import java.util.logging.Logger;

public class InterceptionProxy2 {

    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = null;
        boolean listening = true;
        int port = 1234;
        try {
            serverSocket = new ServerSocket(port);
        } catch (IOException e) {
            System.out.println("Port Error");
            System.exit(-1);
        }
        while (listening) {
            new ProxyThread2(serverSocket.accept()).start();
        }
        serverSocket.close();
    }
}

class ProxyThread2 extends Thread {

    private Socket clientSocket = null;
    private Socket serverSocket = null;

    public ProxyThread2(Socket socket) {
        super("ProxyThread2");
        this.clientSocket = socket;
    }

    public void run() {
        //Stream to put data to the browser
        PrintWriter outGoing = null;
        try {
            outGoing = new PrintWriter(clientSocket.getOutputStream(), true);

            //Stream to get data from the browser
            BufferedReader inComing = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));

            String incomingRequest;
            String url = "";
            String request = "";
            String response = "";
            //Take the incoming request
            char[] buf = new char[8196];        //8196 is the default max size for GET requests in Apache
            int bytesRead = inComing.read(buf);   //BytesRead need to be calculated if the char buffer contains too many values
            request = new String(buf, 0, bytesRead);

            System.out.println("Request");
            System.out.println(request);

            //Create a new socket for connecting to destination server
            serverSocket = new Socket("localhost", 80);
            PrintWriter pOut = new PrintWriter(serverSocket.getOutputStream(), true);

            //Reader for response from destination server
            BufferedReader pIn = new BufferedReader(new InputStreamReader(serverSocket.getInputStream()));

            //Put data into the new socket(to the apache server) and receive its output
            pOut.print(request);
            pOut.flush();
            bytesRead = pIn.read(buf);

            //Check if data is read
            if (bytesRead > 0) {
                response = new String(buf, 0, bytesRead);
            }
            System.out.println("Response");
            System.out.println(response);

            //Put data back into the original client socket
            outGoing.write(response);
        } catch (IOException ex) {
            Logger.getLogger(ProxyThread2.class.getName()).log(Level.SEVERE, null, ex);
        } finally {
            outGoing.close();
        }
    }
}

The system properly prints the request and response as output, but, the proxy does not provide the reply back to the browser. Is there anything wrong with the outGoing stream definition? Or should I create a new socket to send data back to the browser?

like image 759
Mkl Rjv Avatar asked Jun 15 '26 11:06

Mkl Rjv


2 Answers

You don't need to create another instance of java.net.ServerSocket. Because you must connect to port 80, you are a client.

Socket socket = new Socket("localhost", 80);

e.g.:

class ProxyThread extends Thread {

    private final Socket clientSocket;

    public ProxyThread(Socket socket) {
        this.clientSocket = socket;
    }

    public void run() {
        try {
            // Read request
            InputStream incommingIS = clientSocket.getInputStream();
            byte[] b = new byte[8196];
            int len = incommingIS.read(b);

            if (len > 0) {
                System.out.println("REQUEST"
                        + System.getProperty("line.separator") + "-------");
                System.out.println(new String(b, 0, len));

                // Write request
                Socket socket = new Socket("localhost", 80);
                OutputStream outgoingOS = socket.getOutputStream();
                outgoingOS.write(b, 0, len);

                // Copy response
                OutputStream incommingOS = clientSocket.getOutputStream();
                InputStream outgoingIS = socket.getInputStream();
                for (int length; (length = outgoingIS.read(b)) != -1;) {
                    incommingOS.write(b, 0, length);
                }

                incommingOS.close();
                outgoingIS.close();
                outgoingOS.close();
                incommingIS.close();

                socket.close();
            } else {
                incommingIS.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                clientSocket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
like image 83
Paul Vargas Avatar answered Jun 17 '26 01:06

Paul Vargas


Your Code working for simple text files or html. There is only one problem, only the HTTP header are text data everything in the body of the HTTP message could be simple byte data like images.

You shouldn't use the PrintWriter and/or Strings to convert the response. You should simply forward the byte buffer you will get from the Server. Just convert the byte buffer only if you want to show yourself the HTTP message.

like image 38
garvey Avatar answered Jun 16 '26 23:06

garvey



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!