如何实现自定义代理服务器?

时间:2022-09-02 12:14:28

Ultimately, I want to block downloads in .NET WebBrowser control, effectively restricting it to displaying HTML, images, scripts and the like, but never, ever display a "Save as" dialog to the user.

最终,我想阻止.NET WebBrowser控件中的下载,有效地限制它显示HTML,图像,脚本等,但从来没有向用户显示“另存为”对话框。

The solution proposed in an answer to that question was to hook up a custom proxy server that checks the responses and filters out anything that would lead to a download prompt. How can I implement such a proxy in my .NET application? I don't want to install third-party software or libraries.

在该问题的答案中提出的解决方案是连接自定义代理服务器,该服务器检查响应并过滤掉任何会导致下载提示的内容。如何在我的.NET应用程序中实现这样的代理?我不想安装第三方软件或库。

I found the HttpListener class, but I've got two problems with it:

我找到了HttpListener类,但我遇到了两个问题:

  1. The listener requires a predefined set of prefixes that trigger it. I would, however, prefer not to hard-code host names or port numbers in my application, and keep it generic.
  2. 侦听器需要一组触发它的预定义前缀。但是,我不想在我的应用程序中硬编码主机名或端口号,并保持通用。

  3. I would have to implement the code that does the actual request myself - isn't there something that does this for me where I can simply tap into the line, examining the contents of the response and changing them as neccessary (like a request filter in J2EE does on the server side)?
  4. 我必须实现自己执行实际请求的代码 - 是不是有什么东西可以帮助我,我可以直接进入行,检查响应的内容并根据需要更改它们(如请求过滤器中的J2EE在服务器端做什么)?

Update

Okay, I guess I need to make this clearer: My .NET (rich client) application is being used in multiple projects which also have web-based applications. The .NET application includes a reusable, generic form with a WebBrowser control. Other developers use that form to integrate access to their web applications into the .NET application.

好吧,我想我需要更清楚:我的.NET(富客户端)应用程序正在多个项目中使用,这些项目也有基于Web的应用程序。 .NET应用程序包含一个带有WebBrowser控件的可重用的通用表单。其他开发人员使用该表单将对其Web应用程序的访问集成到.NET应用程序中。

I want to block downloads, so I want to have my WebBrowser form intercept all traffic and ensure that it does not lead to a "Save as" dialog. Thus...

我想阻止下载,所以我希望我的WebBrowser表单拦截所有流量,并确保它不会导致“另存为”对话框。从而...

  • I do not know what the host names will be
  • 我不知道主机名是什么

  • The WebBrowser points to the real URLs, the user clicks regular links, triggers JavaScript... all as served by the web application
  • WebBrowser指向真实的URL,用户点击常规链接,触发JavaScript ...所有这些都由Web应用程序提供

  • If the WebBrowser pointed to localhost (as proposed), I'd have to parse responses and rewrite all links so they point at localhost again, preserving the original URL. I don't want to go through that hassle.
  • 如果WebBrowser指向localhost(如建议的那样),我必须解析响应并重写所有链接,以便它们再次指向localhost,保留原始URL。我不想经历那个麻烦。

2 个解决方案

#1


HttpListener should be fine but it's just wrapper around http.sys and this library is available only on Windows XP and higher.

HttpListener应该没问题,但它只是http.sys的包装,这个库只在Windows XP及更高版本上可用。

HttpPrefixes

You only need one prefix http://127.0.0.1:8080/ because it's just for your local webcontrol. Alternatively, wildcards are supported like http://*:8080/ but there is no reason to use it in your case.

您只需要一个前缀http://127.0.0.1:8080/,因为它只适用于您本地的webcontrol。或者,支持通配符,如http:// *:8080 /,但没有理由在您的情况下使用它。

Jens Bannmann wrote:

Jens Bannmann写道:

The applications that are accessed are not on localhost, they can be anywhere. That's why I don't want to hard-code anything.

访问的应用程序不在localhost上,它们可以在任何地方。这就是为什么我不想硬编码任何东西。

what do you mean by applications? you mean websites? this is something completely else, your special proxy server will listen for HttpListenerRequests on http://127.0.0.1:8080/, and therefore your webcontrol has to use proxy server http://127.0.0.1:8080/. It's still all within local machine at this point.

申请是什么意思?你的意思是网站?这完全不同,您的特殊代理服务器将在http://127.0.0.1:8080/上侦听HttpListenerRequests,因此您的webcontrol必须使用代理服务器http://127.0.0.1:8080/。此时它仍然在本地机器内。

Converting between HttpListenerRequest/Response and HttpWebRequest/Response

Convert each incoming HttpListenerRequest into HttpWebRequest, ask for response and you'll get HttpWebResponse object, analyze it whether it's allowed response for your WebBrowser control and if it is, write it into HttpListnererResponse object otherwise write in something else (error status).

将每个传入的HttpListenerRequest转换为HttpWebRequest,请求响应并获取HttpWebResponse对象,分析它是否允许对WebBrowser控件进行响应,如果是,则将其写入HttpListnererResponse对象,否则写入其他内容(错误状态)。

This is probably the easiest way to build your own proxy server on .NET

这可能是在.NET上构建自己的代理服务器的最简单方法

Jens Bannmann wrote:

Jens Bannmann写道:

Right, this conversion was the thing I wanted to avoid having to do. Or can I do that in only a few code lines? From looking at the API, it looks more complicated.

是的,这种转换是我想要避免的事情。或者我可以只在几个代码行中做到这一点?从查看API看起来更复杂。

It's actually quite easy because http protocol is trivial. It has basically three parts.

它实际上非常简单,因为http协议是微不足道的。它基本上有三个部分。

  • Request line (it contains URL, http method and http version)
  • 请求行(包含URL,http方法和http版本)

  • Headers (this is actually what makes API look so huge and important but in reality all those properties and methods are just thin layer over raw http headers. All you need to do is to copy all headers directly in generic way from HttpListenerRequest into HttpWebRequest. Both classes have generic Headers property for raw access)
  • 标题(这实际上是使API看起来如此巨大和重要的原因,但实际上所有这些属性和方法都只是原始http标题上的薄层。您需要做的就是直接以通用方式将所有标题从HttpListenerRequest复制到HttpWebRequest中。类具有用于原始访问的通用Headers属性)

  • Message body (just copy its content if there's any)
  • 消息正文(只要复制其内容,如果有的话)

Whole conversion would look something like this:

整个转换看起来像这样:

HttpListenerRequest listenerRequest;

WebRequest webRequest = WebRequest.Create(listenerRequest.Url);
webRequest.Method = listenerRequest.HttpMethod;
webRequest.Headers.Add(listenerRequest.Headers);
byte[] body = new byte[listenerRequest.InputStream.Length];
listenerRequest.InputStream.Read(body, 0, body.Length);
webRequest.GetRequestStream().Write(body, 0, body.Length);

WebResponse webResponse = webRequest.GetResponse();

If you need more assistence about http protocol, refer to this wikipedia article.

如果您需要更多关于http协议的帮助,请参阅此*文章。

You can also check this open source project for another way of doing it. It doesn't depend on HttpListener class but it's complete proxy server solution and it should be easy to modify for your needs.

您还可以检查此开源项目以获取其他方法。它不依赖于HttpListener类,但它是完整的代理服务器解决方案,应该很容易根据您的需要进行修改。

#2


Perhaps an open source proxy?

也许是一个开源代理?

http://www.mentalis.org/soft/projects/proxy/

#1


HttpListener should be fine but it's just wrapper around http.sys and this library is available only on Windows XP and higher.

HttpListener应该没问题,但它只是http.sys的包装,这个库只在Windows XP及更高版本上可用。

HttpPrefixes

You only need one prefix http://127.0.0.1:8080/ because it's just for your local webcontrol. Alternatively, wildcards are supported like http://*:8080/ but there is no reason to use it in your case.

您只需要一个前缀http://127.0.0.1:8080/,因为它只适用于您本地的webcontrol。或者,支持通配符,如http:// *:8080 /,但没有理由在您的情况下使用它。

Jens Bannmann wrote:

Jens Bannmann写道:

The applications that are accessed are not on localhost, they can be anywhere. That's why I don't want to hard-code anything.

访问的应用程序不在localhost上,它们可以在任何地方。这就是为什么我不想硬编码任何东西。

what do you mean by applications? you mean websites? this is something completely else, your special proxy server will listen for HttpListenerRequests on http://127.0.0.1:8080/, and therefore your webcontrol has to use proxy server http://127.0.0.1:8080/. It's still all within local machine at this point.

申请是什么意思?你的意思是网站?这完全不同,您的特殊代理服务器将在http://127.0.0.1:8080/上侦听HttpListenerRequests,因此您的webcontrol必须使用代理服务器http://127.0.0.1:8080/。此时它仍然在本地机器内。

Converting between HttpListenerRequest/Response and HttpWebRequest/Response

Convert each incoming HttpListenerRequest into HttpWebRequest, ask for response and you'll get HttpWebResponse object, analyze it whether it's allowed response for your WebBrowser control and if it is, write it into HttpListnererResponse object otherwise write in something else (error status).

将每个传入的HttpListenerRequest转换为HttpWebRequest,请求响应并获取HttpWebResponse对象,分析它是否允许对WebBrowser控件进行响应,如果是,则将其写入HttpListnererResponse对象,否则写入其他内容(错误状态)。

This is probably the easiest way to build your own proxy server on .NET

这可能是在.NET上构建自己的代理服务器的最简单方法

Jens Bannmann wrote:

Jens Bannmann写道:

Right, this conversion was the thing I wanted to avoid having to do. Or can I do that in only a few code lines? From looking at the API, it looks more complicated.

是的,这种转换是我想要避免的事情。或者我可以只在几个代码行中做到这一点?从查看API看起来更复杂。

It's actually quite easy because http protocol is trivial. It has basically three parts.

它实际上非常简单,因为http协议是微不足道的。它基本上有三个部分。

  • Request line (it contains URL, http method and http version)
  • 请求行(包含URL,http方法和http版本)

  • Headers (this is actually what makes API look so huge and important but in reality all those properties and methods are just thin layer over raw http headers. All you need to do is to copy all headers directly in generic way from HttpListenerRequest into HttpWebRequest. Both classes have generic Headers property for raw access)
  • 标题(这实际上是使API看起来如此巨大和重要的原因,但实际上所有这些属性和方法都只是原始http标题上的薄层。您需要做的就是直接以通用方式将所有标题从HttpListenerRequest复制到HttpWebRequest中。类具有用于原始访问的通用Headers属性)

  • Message body (just copy its content if there's any)
  • 消息正文(只要复制其内容,如果有的话)

Whole conversion would look something like this:

整个转换看起来像这样:

HttpListenerRequest listenerRequest;

WebRequest webRequest = WebRequest.Create(listenerRequest.Url);
webRequest.Method = listenerRequest.HttpMethod;
webRequest.Headers.Add(listenerRequest.Headers);
byte[] body = new byte[listenerRequest.InputStream.Length];
listenerRequest.InputStream.Read(body, 0, body.Length);
webRequest.GetRequestStream().Write(body, 0, body.Length);

WebResponse webResponse = webRequest.GetResponse();

If you need more assistence about http protocol, refer to this wikipedia article.

如果您需要更多关于http协议的帮助,请参阅此*文章。

You can also check this open source project for another way of doing it. It doesn't depend on HttpListener class but it's complete proxy server solution and it should be easy to modify for your needs.

您还可以检查此开源项目以获取其他方法。它不依赖于HttpListener类,但它是完整的代理服务器解决方案,应该很容易根据您的需要进行修改。

#2


Perhaps an open source proxy?

也许是一个开源代理?

http://www.mentalis.org/soft/projects/proxy/