自己實現httpsever和httpproxy
阿新 • • 發佈:2018-12-13
package gaofeng.myhttp.v1; import java.io.BufferedReader; import java.io.File; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStream; import java.net.Inet4Address; import java.net.ServerSocket; import java.net.Socket; import java.net.URLDecoder; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.concurrent.Executor; import java.util.concurrent.Executors; public class WebServer { private static Executor pool = Executors.newFixedThreadPool(5); public static void main(String[] args) { try (ServerSocket server = new ServerSocket(5566, 5, Inet4Address.getLoopbackAddress());){ while(true) { Socket socket= server.accept(); pool.execute(()->dealRequest(socket)); } } catch (IOException e) { e.printStackTrace(); } } private static void dealRequest(Socket socket) { System.out.println("---- RemoteSocketAddress : " + socket.getRemoteSocketAddress()); try { BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream())); String firstline = null; while(true) { String line = reader.readLine(); if(line==null || line.equals("") ) { System.out.println("---- end:"+line); break; } if(firstline==null) { firstline=line; } System.out.println(">"+line); } String s[] = firstline.split(" "); OutputStream output = socket.getOutputStream(); try { if(s[0].equalsIgnoreCase("get")) { String filename = URLDecoder.decode(s[1],"utf-8"); int index = s[1].indexOf(":5566/"); if(index>-1) { String path = s[1].substring(index + ":5566/".length()); filename = path; } String baseDir = System.getProperty("user.dir") + "/webroot/"; Path filePath = Paths.get(baseDir, filename); if(filePath.toFile().isDirectory()){ StringBuilder sb = new StringBuilder(); for (File file : filePath.toFile().listFiles()) { if(file.isFile()) { sb.append("<a href=\"" + file.getName()+"\">"+file.getName()+"</a><br>"); }else { sb.append("<a href=\"" + file.getName()+"/\">"+file.getName()+"</a><br>"); } } byte[] content = sb.toString().getBytes("GBK"); output.write(String.format("http/1.1 200 ok\r\nContent-Type: text/html\r\nContent-Length: %d\r\n\r\n", content.length).getBytes()); output.write(content); }else { byte[] fileContent = Files.readAllBytes(filePath); output.write(String.format("http/1.1 200 ok\r\nContent-Type: text/html\r\nContent-Length: %d\r\n\r\n", fileContent.length).getBytes()); output.write(fileContent); } return; } }catch(Exception e) {e.printStackTrace();} String notfound = "<h1>File not found!</h1>"; byte[] response = String.format("http/1.1 404 File not found\r\nContent-Type: text/html\r\nContent-Length: %d\r\n\r\n%s",notfound.length(), notfound).getBytes(); output.write(response); }catch(Throwable e) { e.printStackTrace(); }finally { try { socket.close(); } catch (IOException e) { e.printStackTrace(); } } } }
curl -sv --proxy 127.0.0.1:80 http://www.baidu.com
curl -sv --proxy 127.0.0.1:80 https://www.baidu.com
curl --proxy 127.0.0.1:80 http://127.0.0.1:5566/mm/
package gaofeng.myhttp.v1; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.net.ServerSocket; import java.net.Socket; public class HttpProxy { public static void main(String[] args) throws IOException { ServerSocket serverSocket = new ServerSocket(80); for (;;) { new SocketHandle(serverSocket.accept()).start(); } } } class SocketHandle extends Thread{ private Socket socket; public SocketHandle(Socket socket) { this.socket = socket; } @Override public void run() { try { _run(); } catch (IOException e) { e.printStackTrace(); } } public void _run() throws IOException { BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream())); StringBuilder headStr = new StringBuilder(); String host="",port="";//http協議頭 Host: 127.0.0.1 while(true) { String line = reader.readLine(); if(line==null) { System.out.println("---- end:"+line); break; }else { System.out.println(line); headStr.append(line).append("\r\n"); } if (line.length() == 0) { break; } if (line.startsWith("Host:")) { host = line.substring(line.indexOf(' ')+1); if(host.contains(":")) { port=host.split(":")[1]; host=host.split(":")[0]; }else { port="80"; } } } String httpMethod=""; if(headStr.length()>0) { httpMethod = headStr.substring(0, headStr.indexOf(" "));//http協議第一行 GET /mm/ HTTP/1.1 } try(Socket proxySocket = new Socket(host, Integer.parseInt(port))){ InputStream proxyInput = proxySocket.getInputStream(); OutputStream proxyOutput = proxySocket.getOutputStream(); //根據HTTP method來判斷是https還是http請求 if ("CONNECT".equalsIgnoreCase(httpMethod)) {//https先建立隧道 socket.getOutputStream().write("HTTP/1.1 200 Connection Established\r\n\r\n".getBytes()); socket.getOutputStream().flush(); } else {//http直接將請求頭轉發 proxyOutput.write(headStr.toString().getBytes()); } //新開執行緒轉發客戶端請求至目標伺服器 new ProxyHandleThread(socket.getInputStream(), proxyOutput).start(); //轉發目標伺服器響應至客戶端 while (true) { int b = proxyInput.read(); if(b==-1) { socket.getOutputStream().close(); break; }else { socket.getOutputStream().write(b); } } } } } class ProxyHandleThread extends Thread{ private InputStream input; private OutputStream output; public ProxyHandleThread(InputStream input, OutputStream output) { this.input = input; this.output = output; } @Override public void run() { try { while (true) { int b = input.read(); if(b==-1) { break; }else { System.out.println("ddd"+b); output.write(b); } } } catch (IOException e) { e.printStackTrace(); } } }