Java 中的简单 Web 代理
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/18896465/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Simple web proxy in Java
提问by Mkl Rjv
I am trying to write a simple web proxy in java which accepts both GET and POST requests. I wrote the following code:
我正在尝试用 Java 编写一个简单的 Web 代理,它接受 GET 和 POST 请求。我写了以下代码:
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?
系统正确地将请求和响应打印为输出,但是,代理不向浏览器提供回复。outGoing 流定义有什么问题吗?或者我应该创建一个新的套接字来将数据发送回浏览器?
采纳答案by Paul Vargas
You don't need to create another instance of java.net.ServerSocket
. Because you must connect to port 80
, you are a client.
您不需要创建另一个java.net.ServerSocket
. 因为您必须连接到端口80
,所以您是一个客户端。
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();
}
}
}
}
回答by garvey
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.
您的代码适用于简单的文本文件或 html。只有一个问题,只有 HTTP 标头是文本数据,HTTP 消息正文中的所有内容都可以是简单的字节数据,如图像。
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.
您不应使用 PrintWriter 和/或字符串来转换响应。您应该简单地转发将从服务器获得的字节缓冲区。仅当您想向自己显示 HTTP 消息时才转换字节缓冲区。