Sample Projects

Simple Java Proxy Server

import java.io.*;
import java.net.*;
import java.util.*;

public class Proxy
{
    public static final String NEW_LINE = System.getProperty("line.separator");
    public static final int BUFFER_SIZE = 1024 * 10;
    public static final int PORT = 8888;
    
    public static void main(String[] arg)
    {
        try
        {
            runServer();
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }
    
    public static void runServer() throws Exception
    {
        System.out.println("Proxy Server is Running...");
        
        ServerSocket ss = new ServerSocket(PORT);
        
        while (true)
        {
            Socket client = null;
            BufferedOutputStream streamToClient = null;
            BufferedReader readerFromClient = null;
            
            Socket server = null;
            BufferedInputStream streamFromServer = null;
            PrintWriter writerToServer = null;
            
            try
            {
                //Connect to Client
                client = ss.accept();
                streamToClient = new BufferedOutputStream(client.getOutputStream());
                readerFromClient = new BufferedReader(new InputStreamReader(client.getInputStream()));
                
                //Read Request Action
                String requestAction = readRequestAction(readerFromClient);
                
                //Read Request Headers
                LinkedHashMap<String, ArrayList<String>> requestMap = readRequestHeaders(readerFromClient);
                
                //Read Request Body
                String requestBody = readRequestBody(readerFromClient);
                
                //Connect to Server
                server = new Socket(getRequestHost(requestMap), getRequestPort(requestMap));
                streamFromServer = new BufferedInputStream(server.getInputStream());
                writerToServer = new PrintWriter(new OutputStreamWriter(server.getOutputStream()));
                
                //Write Request Action
                writeRequestAction(writerToServer, requestAction);
                
                //Write Request Headers
                writeRequestHeaders(writerToServer, requestMap);
                
                //Write Request Body
                writeRequestBody(writerToServer, requestBody);
                
                //Finally, Proxy Response from Server to Client
                byte[] buffer = new byte[BUFFER_SIZE];
                int length;
                while ((length = streamFromServer.read(buffer)) != -1)
                {
                    streamToClient.write(buffer, 0, length);
                    streamToClient.flush();
                }
            }
            catch (Exception e)
            {
                e.printStackTrace();
            }
            finally
            {
                //Close Connections/Sockets
                if (writerToServer != null)
                    writerToServer.close();
                if (streamToClient != null)
                    streamToClient.close();
                if (server != null)
                    server.close();
                if (client != null)
                    client.close();
            }
        }
    }
    
    //Request Stream Methods
    public static String readRequestAction(BufferedReader reader) throws Exception
    {
        return reader.readLine();
    }
    
    public static LinkedHashMap<String, ArrayList<String>> readRequestHeaders(BufferedReader reader) throws Exception
    {
        LinkedHashMap<String, ArrayList<String>> requestMap = new LinkedHashMap<String, ArrayList<String>>();
        
        String line;
        while (reader.ready() && (line = reader.readLine()).length() > 0)
        {
            String[] pair = line.split(":", 2);
            String key = pair[0].trim();
            String value = pair[1].trim();
            addRequestHeader(requestMap, key, value);
        }
        
        //Filter/Modify the Request Headers for optimal use with Proxy
        removeRequestHeader(requestMap, "keep-alive");
        removeRequestHeader(requestMap, "connection");
        removeRequestHeader(requestMap, "proxy-connection");
        addRequestHeader(requestMap, "connection", "close");
        
        return requestMap;
    }
    
    public static String readRequestBody(BufferedReader reader) throws Exception
    {
        StringBuffer requestBody = new StringBuffer();
        
        char[] buffer = new char[BUFFER_SIZE];
        int length;
        while (reader.ready() && (length = reader.read(buffer)) != -1)
        {
            requestBody.append(new String(buffer, 0, length));
        }
        
        return requestBody.toString();
    }
    
    public static void writeRequestAction(PrintWriter writer, String requestAction)
    {
        writer.println(requestAction);
        writer.flush();
    }
    
    public static void writeRequestHeaders(PrintWriter writer, LinkedHashMap<String, ArrayList<String>> requestMap)
    {
        writer.println(requestHeadersToString(requestMap));
        writer.flush();
    }
    
    public static void writeRequestBody(PrintWriter writer, String requestBody)
    {
        if (requestBody != null && requestBody.length() > 0)
        {
            writer.print(requestBody);
            writer.flush();
        }
    }
    
    //Request Helper Methods
    public static String getRequestMethod(String requestAction)
    {
        return requestAction.split(" ", 3)[0];
    }
    
    public static String getRequestURL(String requestAction)
    {
        return requestAction.split(" ", 3)[1];
    }
    
    public static String getRequestProtocol(String requestAction)
    {
        return requestAction.split(" ", 3)[2];
    }
    
    public static String getRequestHost(LinkedHashMap<String, ArrayList<String>> requestMap)
    {
        String host = getRequestHeader(requestMap, "host");
        
        if (host.contains(":"))
        {
            host = host.split(":", 2)[0];
        }
        
        return host;
    }
    
    public static int getRequestPort(LinkedHashMap<String, ArrayList<String>> requestMap)
    {
        int port = 80;
        
        String host = getRequestHeader(requestMap, "host");
        if (host.contains(":"))
        {
            port = Integer.parseInt(host.split(":", 2)[1]);
        }
        
        return port;
    }
    
    public static void addRequestHeader(LinkedHashMap<String, ArrayList<String>> requestMap, String key, String value)
    {
        key = key.toLowerCase();
        
        if (requestMap.containsKey(key))
        {
            ArrayList<String> list = requestMap.get(key);
            list.add(value);
        }
        else
        {
            ArrayList<String> list = new ArrayList<String>();
            list.add(value);
            requestMap.put(key, list);
        }
    }
    
    public static void removeRequestHeader(LinkedHashMap<String, ArrayList<String>> requestMap, String key)
    {
        requestMap.remove(key);
    }
    
    public static String getRequestHeader(LinkedHashMap<String, ArrayList<String>> requestMap, String key)
    {
        key = key.toLowerCase();
        
        if (requestMap.containsKey(key))
        {
            return requestMap.get(key).get(0);
        }
        
        return null;
    }
    
    public static void setRequestHeaders(LinkedHashMap<String, ArrayList<String>> requestMap, String key, ArrayList<String> value)
    {
        key = key.toLowerCase();
        
        requestMap.put(key, value);
    }
    
    public static ArrayList<String> getRequestHeaders(LinkedHashMap<String, ArrayList<String>> requestMap, String key)
    {
        key = key.toLowerCase();
        
        return requestMap.get(key);
    }
    
    public static String requestHeadersToString(LinkedHashMap<String, ArrayList<String>> requestMap)
    {
        StringBuilder requestString = new StringBuilder();
        
        Iterator<Map.Entry<String, ArrayList<String>>> i = requestMap.entrySet().iterator();
        while (i.hasNext())
        {
            Map.Entry<String, ArrayList<String>> pair = i.next();
            String key = pair.getKey();
            ArrayList<String> value = pair.getValue();
            
            for (String s : value)
            {
                requestString.append(key);
                requestString.append(": ");
                requestString.append(s);
                requestString.append(NEW_LINE);
            }
        }
        
        return requestString.toString();
    }
}