我如何使用 Titanium-Web-Proxy 获得类似 AfterSessionComplete 的回调
How do I get a callback like AfterSessionComplete with Titanium-Web-Proxy
我曾经使用另一个带有 C# 的代理服务器库来捕获 HTTP 请求,它只有一个 AfterSessionComplete
事件,该事件在整个 request/response 操作全部完成后触发,您可以得到主机、路径和查询、请求和响应正文都来自事件参数。然而,该库前一段时间停止了维护,所以我正在考虑切换到 Titanium-Web-Proxy,并且它似乎有一个 AfterResponse
事件。这是我用来测试的:
private static async Task Server_AfterResponse(object sender, SessionEventArgs e)
{
try
{
Uri url = e.HttpClient.Request.RequestUri;
string method = e.HttpClient.Request.Method.ToUpper();
string req = e.HttpClient.Request.HasBody ? e.HttpClient.Request.BodyString : null;
string resp = e.HttpClient.Response.HasBody ? e.HttpClient.Response.BodyString : null;
ThreadPool.QueueUserWorkItem(new WaitCallback((s) =>
{
// Goes back to my old AfterSessionComplete method.
HttpProxy.AfterSessionComplete?.Invoke(url, method, req, resp);
}));
}
catch(Exception ex)
{
Debug.Print($"{ex}");
}
}
public static void Start(int port = 37123)
{
HttpProxy.server = new ProxyServer(false, false, false);
HttpProxy.server.AddEndPoint(new ExplicitProxyEndPoint(IPAddress.Any, port, false));
HttpProxy.server.AfterResponse += Server_AfterResponse;
HttpProxy.server.Start();
}
而且它不起作用。 HTTP 流量会随机堵塞:某些请求不会触发 AfterResponse
事件,在 Chrome DevTools 中表示待处理并最终超时。即使对服务器发出请求,我也没有得到请求和响应主体,试图获取它们会触发异常,如:
System.Exception: You cannot get the request body after request is made to server.
System.Exception: Response body is not read yet. Use SessionEventArgs.GetResponseBody() or SessionEventArgs.GetResponseBodyAsString() method to read the response body.
我也尝试了 await GetRequestBodyAsString()
和 await GetResponseBodyAsString()
但仍然没有。在那个阶段我很迷茫,我到底应该怎么做?我是否需要放弃 AfterResponse
并使用提供的其他活动?
在 Titanium 中,AfterResponse 事件标记响应被发送到浏览器(并且不再可用)的时刻。因此,要读取响应正文,您需要附加到 BeforeResponse 事件。此外,正如您所观察到的,您无法在 * 响应事件中访问请求正文。克服此限制的一种选择是使用 UserData 属性 并在 BeforeRequest 事件中保存您稍后可能需要的请求正文中的所有数据。下面的示例代码展示了如何做到这一点:
void Main()
{
var proxyServer = new ProxyServer(userTrustRootCertificate: false);
proxyServer.BeforeRequest += OnBeforeRequest;
proxyServer.BeforeResponse += OnBeforeResponse;
var httpProxy = new ExplicitProxyEndPoint(IPAddress.Loopback, 8080, decryptSsl: true);
proxyServer.AddEndPoint(httpProxy);
proxyServer.Start();
Console.ReadLine();
proxyServer.Stop();
}
// Define other methods and classes here
public async Task OnBeforeRequest(object sender, SessionEventArgs ev)
{
var request = ev.HttpClient.Request;
ev.UserData = request.HasBody ? await ev.GetRequestBodyAsString() : "";
}
public async Task OnBeforeResponse(object sender, SessionEventArgs ev)
{
var request = ev.HttpClient.Request;
var response = ev.HttpClient.Response;
var requestBody = (string)ev.UserData;
var responseBody = response.HasBody ? await ev.GetResponseBodyAsString() : "";
// TODO: Your old AfterSessionComplete method.
}
我曾经使用另一个带有 C# 的代理服务器库来捕获 HTTP 请求,它只有一个 AfterSessionComplete
事件,该事件在整个 request/response 操作全部完成后触发,您可以得到主机、路径和查询、请求和响应正文都来自事件参数。然而,该库前一段时间停止了维护,所以我正在考虑切换到 Titanium-Web-Proxy,并且它似乎有一个 AfterResponse
事件。这是我用来测试的:
private static async Task Server_AfterResponse(object sender, SessionEventArgs e)
{
try
{
Uri url = e.HttpClient.Request.RequestUri;
string method = e.HttpClient.Request.Method.ToUpper();
string req = e.HttpClient.Request.HasBody ? e.HttpClient.Request.BodyString : null;
string resp = e.HttpClient.Response.HasBody ? e.HttpClient.Response.BodyString : null;
ThreadPool.QueueUserWorkItem(new WaitCallback((s) =>
{
// Goes back to my old AfterSessionComplete method.
HttpProxy.AfterSessionComplete?.Invoke(url, method, req, resp);
}));
}
catch(Exception ex)
{
Debug.Print($"{ex}");
}
}
public static void Start(int port = 37123)
{
HttpProxy.server = new ProxyServer(false, false, false);
HttpProxy.server.AddEndPoint(new ExplicitProxyEndPoint(IPAddress.Any, port, false));
HttpProxy.server.AfterResponse += Server_AfterResponse;
HttpProxy.server.Start();
}
而且它不起作用。 HTTP 流量会随机堵塞:某些请求不会触发 AfterResponse
事件,在 Chrome DevTools 中表示待处理并最终超时。即使对服务器发出请求,我也没有得到请求和响应主体,试图获取它们会触发异常,如:
System.Exception: You cannot get the request body after request is made to server.
System.Exception: Response body is not read yet. Use SessionEventArgs.GetResponseBody() or SessionEventArgs.GetResponseBodyAsString() method to read the response body.
我也尝试了 await GetRequestBodyAsString()
和 await GetResponseBodyAsString()
但仍然没有。在那个阶段我很迷茫,我到底应该怎么做?我是否需要放弃 AfterResponse
并使用提供的其他活动?
在 Titanium 中,AfterResponse 事件标记响应被发送到浏览器(并且不再可用)的时刻。因此,要读取响应正文,您需要附加到 BeforeResponse 事件。此外,正如您所观察到的,您无法在 * 响应事件中访问请求正文。克服此限制的一种选择是使用 UserData 属性 并在 BeforeRequest 事件中保存您稍后可能需要的请求正文中的所有数据。下面的示例代码展示了如何做到这一点:
void Main()
{
var proxyServer = new ProxyServer(userTrustRootCertificate: false);
proxyServer.BeforeRequest += OnBeforeRequest;
proxyServer.BeforeResponse += OnBeforeResponse;
var httpProxy = new ExplicitProxyEndPoint(IPAddress.Loopback, 8080, decryptSsl: true);
proxyServer.AddEndPoint(httpProxy);
proxyServer.Start();
Console.ReadLine();
proxyServer.Stop();
}
// Define other methods and classes here
public async Task OnBeforeRequest(object sender, SessionEventArgs ev)
{
var request = ev.HttpClient.Request;
ev.UserData = request.HasBody ? await ev.GetRequestBodyAsString() : "";
}
public async Task OnBeforeResponse(object sender, SessionEventArgs ev)
{
var request = ev.HttpClient.Request;
var response = ev.HttpClient.Response;
var requestBody = (string)ev.UserData;
var responseBody = response.HasBody ? await ev.GetResponseBodyAsString() : "";
// TODO: Your old AfterSessionComplete method.
}