[英]The way of building a simple http proxy
I'm trying to build a simple http proxy , which does four really basic things: 我正在尝试构建一个简单的http代理 ,它执行四个非常基本的事情:
The troubles i met with: 我遇到的麻烦 :
What i've done: 我做了什么:
public void Listen()
{
Listener.Start();
while (true)
{
var client = Listener.AcceptTcpClient();
Task.Run(() => StartReceivingData(client));
}
}
public void StartReceivingData(TcpClient client)
{
NetworkStream clientStream = client.GetStream();
var buffer = new byte[16000];
while (true)
{
try
{
if (!clientStream.CanRead)
return;
//connection is closed
if (clientStream.Read(buffer).Equals(0))
return;
OnNewRequestReceived?.Invoke(this, new RequestReceivedEventArgs() { User = client, Request = buffer });
} // when clientStream is disposed, exception is thrown.
catch { return; }
}
}
private void Listener_OnNewConnectionReceived(object sender, RequestReceivedEventArgs e)
{
string hostname = HttpQueryParser.GetHostName(e.Request);
NetworkStream proxyClientStream = e.User.GetStream();
try
{
if (firewall.CheckIfBlocked(hostname))
{
//send error page
e.User.GetStream().Write(Encoding.ASCII.GetBytes("<html><body style=\"padding:0; margin:0;\"><img style=\"padding:0; margin:0; width:100%; height:100%;\" src=\"https://www.hostinger.co.id/tutorial/wp-content/uploads/sites/11/2017/08/what-is-403-forbidden-error-and-how-to-fix-it.jpg\"</body></html>"));
return;
}
var targetServer = new TcpClient(hostname, 80);
NetworkStream targetServerStream = targetServer.GetStream();
targetServerStream.Write(e.Request);
var responseBuffer = new byte[32];
for (int offsetCounter = 0; true; ++offsetCounter)
{
var bytesRead = targetServerStream.Read(responseBuffer, 0, responseBuffer.Length);
// Console.WriteLine($"Read {bytesRead} from {hostname}.");
if (bytesRead.Equals(0))
return;
proxyClientStream.Write(responseBuffer, 0, responseBuffer.Length);
if (offsetCounter.Equals(0))
{
var headers = Encoding.UTF8.GetString(responseBuffer).Split("\r\n");
logger.Log(new HttpRequestEntry()
{
ResponseCode = headers[0].Substring(headers[0].IndexOf(" ") + 1),
Hostname = hostname
});
}
}
}
catch { return; }
finally { proxyClientStream.Dispose(); }
}
So, i'm guessing there's a problem with my buffer size, but changing it to higher values actually doesn't change anything . 所以,我猜我的缓冲区大小有问题,但将其更改为更高的值实际上并没有改变任何东西。
Ok so i don't know what's the problem with my byte arrays was, but i made it work, using Stream.CopyTo , which i was quite surprized about - it works on two NetworkStreams. 好的,所以我不知道我的字节数组是什么问题, 但是我使用Stream.CopyTo使它工作,我很惊讶 - 它适用于两个NetworkStreams。 Here's working method if you are curious: 如果你好奇,这是工作方法:
private void Listener_OnNewConnectionReceived(object sender, RequestReceivedEventArgs e)
{
string hostname = HttpQueryParser.GetHostName(e.Request);
NetworkStream proxyClientStream = e.User.GetStream();
try
{
if (firewall.CheckIfBlocked(hostname))
{
//send error page
e.User.GetStream().Write(Encoding.ASCII.GetBytes("<html><body style=\"padding:0; margin:0;\"><img style=\"padding:0; margin:0; width:100%; height:100%;\" src=\"https://www.hostinger.co.id/tutorial/wp-content/uploads/sites/11/2017/08/what-is-403-forbidden-error-and-how-to-fix-it.jpg\"</body></html>"));
return;
}
var targetServer = new TcpClient(hostname, 80);
NetworkStream targetServerStream = targetServer.GetStream();
targetServerStream.Write(e.Request);
var responseBuffer = new byte[32];
//this is to capture status of http request and log it.
targetServerStream.Read(responseBuffer, 0, responseBuffer.Length);
proxyClientStream.Write(responseBuffer, 0, responseBuffer.Length);
var headers = Encoding.UTF8.GetString(responseBuffer).Split("\r\n");
logger.Log(new HttpRequestEntry()
{
ResponseCode = headers[0].Substring(headers[0].IndexOf(" ") + 1),
Hostname = hostname
});
targetServerStream.CopyTo(proxyClientStream);
}
catch { return; }
finally { proxyClientStream.Dispose(); }
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.