Skip to content

Commit

Permalink
请求重写增加重定向&请求体重写增加URL参数重写
Browse files Browse the repository at this point in the history
  • Loading branch information
wanghongenpin committed Sep 7, 2023
1 parent 51cadcd commit b8525e7
Show file tree
Hide file tree
Showing 8 changed files with 224 additions and 110 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@

国内下载地址: https://gitee.com/wanghongenpin/network-proxy-flutter/releases

iOS美版香港AppStore下载地址或直接搜ProxyPin(推荐)https://apps.apple.com/app/proxypin/id6450932949
iOS美版香港AppStore下载地址或直接搜ProxyPin: https://apps.apple.com/app/proxypin/id6450932949

iOS国内下载地址(有1万名额限制,满了会清理不使用的用户): https://testflight.apple.com/join/gURGH6B4
iOS国内TF下载地址(有1万名额限制,满了会清理不使用的用户): https://testflight.apple.com/join/gURGH6B4

TG: https://t.me/proxypin_tg

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,12 @@ import androidx.core.app.NotificationCompat
* VPN服务
* @author wanghongen
*/
class ProxyVpnService : VpnService(), IProtectSocket {
class ProxyVpnService : VpnService() {
private var vpnInterface: ParcelFileDescriptor? = null

companion object {
const val MAX_PACKET_LEN = 1500

const val ProxyHost = "ProxyHost"
const val ProxyPort = "ProxyPort"
const val AllowApps = "AllowApps" //允许的名单
Expand Down
32 changes: 27 additions & 5 deletions lib/network/handler.dart
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,6 @@ class HttpChannelHandler extends ChannelHandler<HttpRequest> {
remoteChannel = await _getRemoteChannel(channel, httpRequest);
remoteChannel.putAttribute(remoteChannel.id, channel);
} catch (error) {

channel.error = error; //记录异常
//https代理新建连接请求
if (httpRequest.method == HttpMethod.connect) {
Expand All @@ -129,18 +128,41 @@ class HttpChannelHandler extends ChannelHandler<HttpRequest> {
if (httpRequest.method != HttpMethod.connect) {
log.i("[${channel.id}] ${httpRequest.method.name} ${httpRequest.requestUrl}");

var replaceBody = requestRewrites?.findRequestReplaceWith(httpRequest.hostAndPort?.host, httpRequest.path());
if (replaceBody?.isNotEmpty == true) {
httpRequest.body = utf8.encode(replaceBody!);
}
//替换请求体
_rewriteBody(httpRequest);

if (!HostFilter.filter(httpRequest.hostAndPort?.host)) {
listener?.onRequest(channel, httpRequest);
}

//重定向
var redirectRewrite =
requestRewrites?.findRequestRewrite(httpRequest.hostAndPort?.host, httpRequest.path(), RuleType.redirect);
if (redirectRewrite?.redirectUrl?.isNotEmpty == true) {
var proxyHandler = HttpResponseProxyHandler(channel, listener: listener, requestRewrites: requestRewrites);
httpRequest.uri = redirectRewrite!.redirectUrl!;
httpRequest.headers.host = Uri.parse(redirectRewrite.redirectUrl!).host;
var redirectChannel = await HttpClients.connect(Uri.parse(redirectRewrite.redirectUrl!), proxyHandler);
await redirectChannel.write(httpRequest);
return;
}

await remoteChannel.write(httpRequest);
}
}

//替换请求体
_rewriteBody(HttpRequest httpRequest) {
var rewrite = requestRewrites?.findRequestRewrite(httpRequest.hostAndPort?.host, httpRequest.path(), RuleType.body);

if (rewrite?.requestBody?.isNotEmpty == true) {
httpRequest.body = utf8.encode(rewrite!.requestBody!);
}
if (rewrite?.queryParam?.isNotEmpty == true) {
httpRequest.uri = httpRequest.requestUri?.replace(query: rewrite!.queryParam!).toString() ?? httpRequest.uri;
}
}

/// 下载证书
void _crtDownload(Channel channel, HttpRequest request) async {
const String fileMimeType = 'application/x-x509-ca-cert';
Expand Down
6 changes: 3 additions & 3 deletions lib/network/http/http.dart
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ abstract class HttpMessage {

///HTTP请求。
class HttpRequest extends HttpMessage {
final String uri;
String uri;
late HttpMethod method;

HostAndPort? hostAndPort;
Expand All @@ -90,10 +90,10 @@ class HttpRequest extends HttpMessage {

HttpRequest(this.method, this.uri, {String protocolVersion = "HTTP/1.1"}) : super(protocolVersion);

String? remoteDomain() {
String? remoteDomain() {
if (hostAndPort == null) {
try {
return Uri.parse(uri).host;
return Uri.parse(uri).host;
} catch (e) {
return null;
}
Expand Down
10 changes: 5 additions & 5 deletions lib/network/http_client.dart
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@ class HttpClients {
var client = Client()
..initChannel((channel) => channel.pipeline.handle(HttpResponseCodec(), HttpRequestCodec(), handler));

if (proxyInfo == null) {
var proxyTypes = hostAndPort.isSsl() ? ProxyTypes.https : ProxyTypes.http;
proxyInfo = await SystemProxy.getSystemProxy(proxyTypes);
}

HostAndPort connectHost = proxyInfo == null ? hostAndPort : HostAndPort.host(proxyInfo.host, proxyInfo.port!);
var channel = await client.connect(connectHost);

Expand Down Expand Up @@ -102,11 +107,6 @@ class HttpClients {
/// 发送代理请求
static Future<HttpResponse> proxyRequest(HttpRequest request,
{ProxyInfo? proxyInfo, Duration timeout = const Duration(seconds: 3)}) async {
if (proxyInfo == null) {
var proxyTypes = request.uri.startsWith("https://") ? ProxyTypes.https : ProxyTypes.http;
proxyInfo = await SystemProxy.getSystemProxy(proxyTypes);
}

if (request.headers.host == null || request.headers.host?.trim().isEmpty == true) {
try {
request.headers.host = Uri.parse(request.uri).host;
Expand Down
58 changes: 49 additions & 9 deletions lib/network/util/request_rewrite.dart
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,17 @@ class RequestRewrites {
});
}

String? findRequestReplaceWith(String? domain, String? url) {
RequestRewriteRule? findRequestRewrite(String? domain, String? url, RuleType type) {
if (!enabled || url == null) {
return null;
}

for (var rule in rules) {
if (rule.enabled && rule.urlReg.hasMatch(url)) {
if (rule.enabled && rule.urlReg.hasMatch(url) && type == rule.type) {
if (rule.domain?.isNotEmpty == true && rule.domain != domain) {
continue;
}
return rule.requestBody;
return rule;
}
}
return null;
Expand Down Expand Up @@ -72,29 +73,68 @@ class RequestRewrites {
}
}

enum RuleType {
body("重写消息体"),
// header("重写Header"),
redirect("重定向");

//名称
final String name;

const RuleType(this.name);

static RuleType fromName(String name) {
return values.firstWhere((element) => element.name == name);
}
}

class RequestRewriteRule {
bool enabled = false;
final String path;
final String? domain;
final RegExp urlReg;
String path;
String? domain;
RuleType type;

String? name;

//消息体
String? queryParam;
String? requestBody;
String? responseBody;

RequestRewriteRule(this.enabled, this.path, this.domain, {this.requestBody, this.responseBody})
//重定向
String? redirectUrl;

RegExp urlReg;

RequestRewriteRule(this.enabled, this.path, this.domain,
{this.name, this.type = RuleType.body, this.queryParam, this.requestBody, this.responseBody, this.redirectUrl})
: urlReg = RegExp(path.replaceAll("*", ".*"));

factory RequestRewriteRule.formJson(Map<String, dynamic> map) {
return RequestRewriteRule(map['enabled'] == true, map['path'] ?? map['url'], map['domain'],
requestBody: map['requestBody'], responseBody: map['responseBody']);
return RequestRewriteRule(map['enabled'] == true, map['path'], map['domain'],
name: map['name'],
type: RuleType.fromName(map['type']),
queryParam: map['queryParam'],
requestBody: map['requestBody'],
responseBody: map['responseBody'],
redirectUrl: map['redirectUrl']);
}

void updatePathReg() {
urlReg = RegExp(path.replaceAll("*", ".*"));
}

toJson() {
return {
'name': name,
'enabled': enabled,
'domain': domain,
'path': path,
'type': type.name,
'queryParam': queryParam,
'requestBody': requestBody,
'responseBody': responseBody,
'redirectUrl': redirectUrl,
};
}
}
4 changes: 2 additions & 2 deletions lib/ui/content/panel.dart
Original file line number Diff line number Diff line change
Expand Up @@ -158,9 +158,9 @@ class NetworkTabState extends State<NetworkTabController> with SingleTickerProvi

var responseCookie = widget.response.get()?.headers.getList("Set-Cookie")?.expand((e) => _cookieWidget(e)!);
return ListView(children: [
expansionTile("Request Cookies", requestCookie?.toList() ?? []),
requestCookie == null ? const SizedBox() : expansionTile("Request Cookies", requestCookie.toList()),
const SizedBox(height: 20),
expansionTile("Response Cookies", responseCookie?.toList() ?? []),
responseCookie == null ? const SizedBox() : expansionTile("Response Cookies", responseCookie.toList()),
]);
}

Expand Down
Loading

0 comments on commit b8525e7

Please sign in to comment.