mirror of
https://github.com/wanghongenpin/proxypin.git
synced 2026-05-09 00:34:17 +08:00
详情增加快速请求重写
This commit is contained in:
@@ -292,7 +292,7 @@
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastSwiftUpdateCheck = 1420;
|
||||
LastUpgradeCheck = 1300;
|
||||
LastUpgradeCheck = 1430;
|
||||
ORGANIZATIONNAME = "";
|
||||
TargetAttributes = {
|
||||
331C8080294A63A400263BE5 = {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1300"
|
||||
LastUpgradeVersion = "1430"
|
||||
version = "1.3">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
|
||||
@@ -114,7 +114,7 @@ class FluentApp extends StatelessWidget {
|
||||
builder: (_, current, __) {
|
||||
uiConfiguration.theme = current;
|
||||
uiConfiguration.flushConfig();
|
||||
print(current.mode.name);
|
||||
|
||||
return MaterialApp(
|
||||
title: 'ProxyPin',
|
||||
debugShowCheckedModeBanner: false,
|
||||
|
||||
@@ -40,7 +40,7 @@ class Configuration {
|
||||
bool upgradeNotice = true;
|
||||
|
||||
//请求重写
|
||||
RequestRewrites requestRewrites = RequestRewrites();
|
||||
RequestRewrites requestRewrites = RequestRewrites.instance;
|
||||
|
||||
//外部代理
|
||||
ProxyInfo? externalProxy;
|
||||
|
||||
@@ -1,10 +1,16 @@
|
||||
|
||||
/// @author wanghongen
|
||||
/// 2023/7/26
|
||||
class RequestRewrites {
|
||||
bool enabled = true;
|
||||
final List<RequestRewriteRule> rules = [];
|
||||
|
||||
RequestRewrites._();
|
||||
|
||||
//单例
|
||||
static final RequestRewrites _instance = RequestRewrites._();
|
||||
|
||||
static RequestRewrites get instance => _instance;
|
||||
|
||||
load(Map<String, dynamic>? map) {
|
||||
if (map == null) {
|
||||
return;
|
||||
@@ -47,7 +53,8 @@ class RequestRewrites {
|
||||
return null;
|
||||
}
|
||||
|
||||
addRule(RequestRewriteRule rule) {
|
||||
void addRule(RequestRewriteRule rule) {
|
||||
rules.removeWhere((it) => it.path == rule.path && it.domain == rule.domain);
|
||||
rules.add(rule);
|
||||
}
|
||||
|
||||
|
||||
@@ -69,6 +69,7 @@ class _Item {
|
||||
_Item(this.request, [this.response]) {
|
||||
response ??= request.response;
|
||||
request.response = response;
|
||||
response?.request = request;
|
||||
}
|
||||
|
||||
factory _Item.fromJson(Map<String, dynamic> json) {
|
||||
|
||||
@@ -5,10 +5,14 @@ import 'package:desktop_multi_window/desktop_multi_window.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_toastr/flutter_toastr.dart';
|
||||
import 'package:network_proxy/network/bin/configuration.dart';
|
||||
import 'package:network_proxy/network/http/http.dart';
|
||||
import 'package:network_proxy/network/util/request_rewrite.dart';
|
||||
import 'package:network_proxy/ui/component/json/json_viewer.dart';
|
||||
import 'package:network_proxy/ui/component/json/theme.dart';
|
||||
import 'package:network_proxy/ui/component/utils.dart';
|
||||
import 'package:network_proxy/ui/desktop/toolbar/setting/request_rewrite.dart';
|
||||
import 'package:network_proxy/ui/mobile/setting/request_rewrite.dart';
|
||||
import 'package:network_proxy/utils/num.dart';
|
||||
import 'package:network_proxy/utils/platform.dart';
|
||||
import 'package:window_manager/window_manager.dart';
|
||||
@@ -99,30 +103,71 @@ class HttpBodyState extends State<HttpBodyWidget> {
|
||||
return tabController;
|
||||
}
|
||||
|
||||
/// 标题
|
||||
Widget titleWidget({inNewWindow = false}) {
|
||||
var type = widget.httpMessage is HttpRequest ? "Request" : "Response";
|
||||
|
||||
var list = [
|
||||
Text('$type Body', style: const TextStyle(fontSize: 16, fontWeight: FontWeight.w500)),
|
||||
const SizedBox(width: 15),
|
||||
IconButton(
|
||||
icon: const Icon(Icons.copy),
|
||||
tooltip: '复制',
|
||||
onPressed: () {
|
||||
var body = bodyKey.currentState?.body;
|
||||
if (body == null) {
|
||||
return;
|
||||
}
|
||||
Clipboard.setData(ClipboardData(text: body)).then((value) => FlutterToastr.show("已复制到剪切板", context));
|
||||
}),
|
||||
];
|
||||
|
||||
if (!inNewWindow || Platforms.isMobile()) {
|
||||
list.add(const SizedBox(width: 5));
|
||||
list.add(IconButton(
|
||||
icon: const Icon(Icons.edit_document),
|
||||
tooltip: '请求重写',
|
||||
onPressed: () {
|
||||
HttpRequest? request;
|
||||
if (widget.httpMessage is HttpRequest) {
|
||||
request = widget.httpMessage as HttpRequest;
|
||||
} else {
|
||||
request = (widget.httpMessage as HttpResponse).request;
|
||||
}
|
||||
|
||||
var body = bodyKey.currentState?.body;
|
||||
var rule = RequestRewriteRule(true, request?.path() ?? '', request?.remoteDomain(),
|
||||
requestBody: widget.httpMessage is HttpRequest ? body : null,
|
||||
responseBody: widget.httpMessage is HttpResponse ? body : null);
|
||||
|
||||
if (Platforms.isMobile()) {
|
||||
Navigator.push(context, MaterialPageRoute(builder: (_) => RewriteRule(rule: rule))).then((value) {
|
||||
if (value is RequestRewriteRule) {
|
||||
Configuration.instance.then((it) => it.flushRequestRewriteConfig());
|
||||
}
|
||||
});
|
||||
} else {
|
||||
showDialog(
|
||||
context: context,
|
||||
barrierDismissible: false,
|
||||
builder: (BuildContext context) => RuleAddDialog(rule: rule)).then((value) {
|
||||
if (value != null) {
|
||||
Configuration.instance.then((it) => it.flushRequestRewriteConfig());
|
||||
FlutterToastr.show("添加请求重写规则成功", context);
|
||||
}
|
||||
});
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
if (!inNewWindow) {
|
||||
list.add(const SizedBox(width: 5));
|
||||
list.add(IconButton(icon: const Icon(Icons.open_in_new), tooltip: '新窗口打开', onPressed: () => openNew()));
|
||||
}
|
||||
|
||||
return Row(
|
||||
mainAxisAlignment: widget.inNewWindow ? MainAxisAlignment.center : MainAxisAlignment.start,
|
||||
children: [
|
||||
Text('$type Body', style: const TextStyle(fontWeight: FontWeight.w500)),
|
||||
const SizedBox(width: 15),
|
||||
IconButton(
|
||||
icon: const Icon(Icons.copy),
|
||||
tooltip: '复制',
|
||||
onPressed: () {
|
||||
var body = bodyKey.currentState?.body;
|
||||
if (body == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Clipboard.setData(ClipboardData(text: body)).then((value) => FlutterToastr.show("已复制到剪切板", context));
|
||||
}),
|
||||
const SizedBox(width: 5),
|
||||
inNewWindow
|
||||
? const SizedBox()
|
||||
: IconButton(icon: const Icon(Icons.open_in_new), tooltip: '新窗口打开', onPressed: () => openNew())
|
||||
],
|
||||
children: list,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -193,14 +238,16 @@ class _BodyState extends State<_Body> {
|
||||
if (viewType == ViewType.hex) {
|
||||
return message!.body!.map(intToHex).join(" ");
|
||||
}
|
||||
if (viewType == ViewType.formUrl) {
|
||||
return Uri.decodeFull(message!.bodyAsString);
|
||||
}
|
||||
if (viewType == ViewType.jsonText || viewType == ViewType.json) {
|
||||
//json格式化
|
||||
var jsonObject = json.decode(message!.bodyAsString);
|
||||
return const JsonEncoder.withIndent(" ").convert(jsonObject);
|
||||
}
|
||||
try {
|
||||
if (viewType == ViewType.formUrl) {
|
||||
return Uri.decodeFull(message!.bodyAsString);
|
||||
}
|
||||
if (viewType == ViewType.jsonText || viewType == ViewType.json) {
|
||||
//json格式化
|
||||
var jsonObject = json.decode(message!.bodyAsString);
|
||||
return const JsonEncoder.withIndent(" ").convert(jsonObject);
|
||||
}
|
||||
} catch (_) {}
|
||||
return message!.bodyAsString;
|
||||
}
|
||||
|
||||
|
||||
@@ -97,33 +97,29 @@ class _RequestRewriteState extends State<RequestRewrite> {
|
||||
barrierDismissible: false,
|
||||
builder: (BuildContext context) {
|
||||
return RuleAddDialog(
|
||||
requestRewrites: widget.configuration.requestRewrites,
|
||||
currentIndex: currentIndex,
|
||||
onChange: () {
|
||||
changed = true;
|
||||
requestRuleList.changeState();
|
||||
});
|
||||
});
|
||||
rule: currentIndex >= 0 ? widget.configuration.requestRewrites.rules[currentIndex] : null);
|
||||
}).then((value) {
|
||||
if (value != null) {
|
||||
changed = true;
|
||||
requestRuleList.changeState();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
///请求重写规则添加对话框
|
||||
class RuleAddDialog extends StatelessWidget {
|
||||
final RequestRewrites requestRewrites;
|
||||
final int currentIndex;
|
||||
final Function onChange;
|
||||
final RequestRewriteRule? rule;
|
||||
|
||||
const RuleAddDialog({super.key, required this.currentIndex, required this.onChange, required this.requestRewrites});
|
||||
const RuleAddDialog({super.key, this.currentIndex = -1, this.rule});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
GlobalKey formKey = GlobalKey<FormState>();
|
||||
RequestRewriteRule? rule;
|
||||
if (currentIndex >= 0) {
|
||||
rule = requestRewrites.rules[currentIndex];
|
||||
}
|
||||
|
||||
ValueNotifier<bool> enableNotifier = ValueNotifier(rule == null || rule.enabled);
|
||||
ValueNotifier<bool> enableNotifier = ValueNotifier(rule == null || rule?.enabled == true);
|
||||
String? domain = rule?.domain;
|
||||
String? path = rule?.path;
|
||||
String? requestBody = rule?.requestBody;
|
||||
@@ -179,17 +175,18 @@ class RuleAddDialog extends StatelessWidget {
|
||||
if ((formKey.currentState as FormState).validate()) {
|
||||
(formKey.currentState as FormState).save();
|
||||
|
||||
var rule = RequestRewriteRule(
|
||||
enableNotifier.value, path!, domain?.trim().isEmpty == true ? null : domain?.trim(),
|
||||
requestBody: requestBody, responseBody: responseBody);
|
||||
|
||||
if (currentIndex >= 0) {
|
||||
requestRewrites.rules[currentIndex] = RequestRewriteRule(enableNotifier.value, path!, domain,
|
||||
requestBody: requestBody, responseBody: responseBody);
|
||||
RequestRewrites.instance.rules[currentIndex] = rule;
|
||||
} else {
|
||||
requestRewrites.addRule(RequestRewriteRule(enableNotifier.value, path!, domain,
|
||||
requestBody: requestBody, responseBody: responseBody));
|
||||
RequestRewrites.instance.addRule(rule);
|
||||
}
|
||||
|
||||
enableNotifier.dispose();
|
||||
onChange.call();
|
||||
Navigator.of(context).pop();
|
||||
Navigator.of(context).pop(rule);
|
||||
}
|
||||
}),
|
||||
ElevatedButton(
|
||||
@@ -210,19 +207,10 @@ class RequestRuleList extends StatefulWidget {
|
||||
State<RequestRuleList> createState() => _RequestRuleListState();
|
||||
|
||||
List<int> removeSelected() {
|
||||
var index = currentSelectedIndex();
|
||||
var state = (key as GlobalKey<_RequestRuleListState>).currentState;
|
||||
List<int> list = [];
|
||||
var selectedIndex = state?.currentSelectedIndex;
|
||||
state?.selected.forEach((key, value) {
|
||||
if (value == true) {
|
||||
list.add(key);
|
||||
if (selectedIndex == key) {
|
||||
state.currentSelectedIndex = -1;
|
||||
}
|
||||
}
|
||||
});
|
||||
state?.selected.clear();
|
||||
return list;
|
||||
state?.currentSelectedIndex = -1;
|
||||
return index >= 0 ? [index] : [];
|
||||
}
|
||||
|
||||
int currentSelectedIndex() {
|
||||
@@ -237,7 +225,6 @@ class RequestRuleList extends StatefulWidget {
|
||||
}
|
||||
|
||||
class _RequestRuleListState extends State<RequestRuleList> {
|
||||
final Map<int, bool> selected = {};
|
||||
int currentSelectedIndex = -1;
|
||||
|
||||
changeState() {
|
||||
@@ -248,8 +235,7 @@ class _RequestRuleListState extends State<RequestRuleList> {
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
padding: const EdgeInsets.only(top: 10),
|
||||
height: 300,
|
||||
constraints: const BoxConstraints(minWidth: 500),
|
||||
constraints: const BoxConstraints(minWidth: 500, minHeight: 300),
|
||||
child: SingleChildScrollView(
|
||||
child: DataTable(
|
||||
columnSpacing: 36,
|
||||
@@ -283,10 +269,9 @@ class _RequestRuleListState extends State<RequestRuleList> {
|
||||
style: const TextStyle(fontSize: 12)),
|
||||
))
|
||||
],
|
||||
selected: selected[index] == true,
|
||||
selected: currentSelectedIndex == index,
|
||||
onSelectChanged: (value) {
|
||||
setState(() {
|
||||
selected[index] = value!;
|
||||
currentSelectedIndex = index;
|
||||
});
|
||||
})),
|
||||
|
||||
@@ -86,17 +86,17 @@ class MobileHomeState extends State<MobileHomePage> implements EventListener {
|
||||
]),
|
||||
drawer: DrawerWidget(proxyServer: proxyServer),
|
||||
floatingActionButton: FloatingActionButton(
|
||||
onPressed: () {},
|
||||
child: SocketLaunch(
|
||||
proxyServer: proxyServer,
|
||||
startup: false,
|
||||
size: 38,
|
||||
onStart: () => Vpn.startVpn("127.0.0.1", proxyServer.port, proxyServer.configuration.appWhitelist),
|
||||
onStop: () => Vpn.stopVpn())),
|
||||
onPressed: null,
|
||||
child: Center(
|
||||
child: SocketLaunch(
|
||||
proxyServer: proxyServer,
|
||||
size: 36,
|
||||
startup: false,
|
||||
onStart: () => Vpn.startVpn("127.0.0.1", proxyServer.port, proxyServer.configuration.appWhitelist),
|
||||
onStop: () => Vpn.stopVpn()))),
|
||||
body: ValueListenableBuilder(
|
||||
valueListenable: desktop,
|
||||
builder: (context, value, _) {
|
||||
|
||||
return Column(children: [
|
||||
value.connect ? remoteConnect(value) : const SizedBox(),
|
||||
Expanded(child: RequestListWidget(key: requestStateKey, proxyServer: proxyServer))
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_toastr/flutter_toastr.dart';
|
||||
import 'package:network_proxy/network/bin/configuration.dart';
|
||||
import 'package:network_proxy/network/util/request_rewrite.dart';
|
||||
|
||||
@@ -87,117 +88,118 @@ class _MobileRequestRewriteState extends State<MobileRequestRewrite> {
|
||||
})
|
||||
]),
|
||||
const SizedBox(height: 10),
|
||||
requestRuleList,
|
||||
Expanded(child: requestRuleList),
|
||||
],
|
||||
)));
|
||||
}
|
||||
|
||||
void add([int currentIndex = -1]) {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return RuleAddDialog(
|
||||
requestRewrites: widget.configuration.requestRewrites,
|
||||
currentIndex: currentIndex,
|
||||
onChange: () {
|
||||
changed = true;
|
||||
requestRuleList.changeState();
|
||||
});
|
||||
var rewriteRule =
|
||||
RewriteRule(rule: currentIndex == -1 ? null : widget.configuration.requestRewrites.rules[currentIndex]);
|
||||
|
||||
Navigator.push(context, MaterialPageRoute(builder: (_) => rewriteRule)).then((rule) {
|
||||
if (rule != null) {
|
||||
changed = true;
|
||||
setState(() {
|
||||
if (currentIndex == -1) {
|
||||
widget.configuration.requestRewrites.addRule(rule);
|
||||
} else {
|
||||
widget.configuration.requestRewrites.rules[currentIndex] = rule;
|
||||
}
|
||||
requestRuleList.changeState();
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
///请求重写规则添加对话框
|
||||
class RuleAddDialog extends StatelessWidget {
|
||||
final RequestRewrites requestRewrites;
|
||||
class RewriteRule extends StatelessWidget {
|
||||
final int currentIndex;
|
||||
final Function onChange;
|
||||
final RequestRewriteRule? rule;
|
||||
|
||||
const RuleAddDialog({super.key, required this.currentIndex, required this.onChange, required this.requestRewrites});
|
||||
const RewriteRule({super.key, required this.rule, this.currentIndex = -1});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
GlobalKey formKey = GlobalKey<FormState>();
|
||||
RequestRewriteRule? rule;
|
||||
if (currentIndex >= 0) {
|
||||
rule = requestRewrites.rules[currentIndex];
|
||||
}
|
||||
|
||||
ValueNotifier<bool> enableNotifier = ValueNotifier(rule == null || rule.enabled);
|
||||
ValueNotifier<bool> enableNotifier = ValueNotifier(rule == null || rule!.enabled);
|
||||
String? domain = rule?.domain;
|
||||
String? path = rule?.path;
|
||||
String? requestBody = rule?.requestBody;
|
||||
String? responseBody = rule?.responseBody;
|
||||
|
||||
return AlertDialog(
|
||||
title: const Text("添加请求重写规则", style: TextStyle(fontSize: 16)),
|
||||
scrollable: true,
|
||||
content: Form(
|
||||
key: formKey,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: <Widget>[
|
||||
ValueListenableBuilder(
|
||||
valueListenable: enableNotifier,
|
||||
builder: (_, bool enable, __) {
|
||||
return SwitchListTile(
|
||||
contentPadding: const EdgeInsets.only(left: 0),
|
||||
title: const Text('是否启用', textAlign: TextAlign.start),
|
||||
value: enable,
|
||||
onChanged: (value) => enableNotifier.value = value);
|
||||
}),
|
||||
TextFormField(
|
||||
decoration: const InputDecoration(labelText: '域名(可选)', hintText: 'baidu.com 不需要填写HTTP'),
|
||||
initialValue: domain,
|
||||
onSaved: (val) => domain = val),
|
||||
TextFormField(
|
||||
decoration: const InputDecoration(labelText: 'Path', hintText: '/api/v1/*'),
|
||||
validator: (val) {
|
||||
if (val == null || val.isEmpty) {
|
||||
return 'Path不能为空';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
initialValue: path,
|
||||
onSaved: (val) => path = val),
|
||||
TextFormField(
|
||||
initialValue: requestBody,
|
||||
decoration: const InputDecoration(labelText: '请求体替换为:'),
|
||||
onSaved: (val) => requestBody = val),
|
||||
TextFormField(
|
||||
initialValue: responseBody,
|
||||
minLines: 3,
|
||||
maxLines: 10,
|
||||
decoration: const InputDecoration(labelText: '响应体替换为:', hintText: '{"code":"200","data":{}}'),
|
||||
onSaved: (val) => responseBody = val)
|
||||
])),
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text("请求重写规则", style: TextStyle(fontSize: 16)),
|
||||
actions: [
|
||||
FilledButton(
|
||||
TextButton(
|
||||
child: const Text("保存"),
|
||||
onPressed: () {
|
||||
if ((formKey.currentState as FormState).validate()) {
|
||||
(formKey.currentState as FormState).save();
|
||||
enableNotifier.dispose();
|
||||
var requestRewriteRule = RequestRewriteRule(
|
||||
enableNotifier.value, path!, domain?.trim().isEmpty == true ? null : domain?.trim(),
|
||||
requestBody: requestBody, responseBody: responseBody);
|
||||
|
||||
if (currentIndex >= 0) {
|
||||
requestRewrites.rules[currentIndex] = RequestRewriteRule(enableNotifier.value, path!, domain,
|
||||
requestBody: requestBody, responseBody: responseBody);
|
||||
RequestRewrites.instance.rules[currentIndex] = requestRewriteRule;
|
||||
} else {
|
||||
requestRewrites.addRule(RequestRewriteRule(enableNotifier.value, path!, domain,
|
||||
requestBody: requestBody, responseBody: responseBody));
|
||||
RequestRewrites.instance.addRule(requestRewriteRule);
|
||||
}
|
||||
|
||||
enableNotifier.dispose();
|
||||
onChange.call();
|
||||
Navigator.of(context).pop();
|
||||
FlutterToastr.show("添加请求重写规则成功", context);
|
||||
Navigator.of(context).pop(requestRewriteRule);
|
||||
}
|
||||
}),
|
||||
ElevatedButton(
|
||||
child: const Text("关闭"),
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
})
|
||||
]);
|
||||
],
|
||||
),
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.all(10),
|
||||
child: Form(
|
||||
key: formKey,
|
||||
child: ListView(children: <Widget>[
|
||||
ValueListenableBuilder(
|
||||
valueListenable: enableNotifier,
|
||||
builder: (_, bool enable, __) {
|
||||
return SwitchListTile(
|
||||
contentPadding: const EdgeInsets.only(left: 0),
|
||||
title: const Text('是否启用', textAlign: TextAlign.start),
|
||||
value: enable,
|
||||
onChanged: (value) => enableNotifier.value = value);
|
||||
}),
|
||||
TextFormField(
|
||||
decoration: const InputDecoration(labelText: '域名(可选)', hintText: 'baidu.com 不需要填写HTTP'),
|
||||
initialValue: domain,
|
||||
onSaved: (val) => domain = val),
|
||||
TextFormField(
|
||||
decoration: const InputDecoration(labelText: 'Path', hintText: '/api/v1/*'),
|
||||
validator: (val) {
|
||||
if (val == null || val.isEmpty) {
|
||||
return 'Path不能为空';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
minLines: 1,
|
||||
maxLines: 3,
|
||||
initialValue: path,
|
||||
onSaved: (val) => path = val),
|
||||
TextFormField(
|
||||
initialValue: requestBody,
|
||||
decoration: const InputDecoration(labelText: '请求体替换为:'),
|
||||
minLines: 1,
|
||||
maxLines: 3,
|
||||
onSaved: (val) => requestBody = val),
|
||||
TextFormField(
|
||||
initialValue: responseBody,
|
||||
minLines: 3,
|
||||
maxLines: 10,
|
||||
decoration: const InputDecoration(labelText: '响应体替换为:', hintText: '{"code":"200","data":{}}'),
|
||||
onSaved: (val) => responseBody = val)
|
||||
]))),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -210,24 +212,15 @@ class RequestRuleList extends StatefulWidget {
|
||||
State<RequestRuleList> createState() => _RequestRuleListState();
|
||||
|
||||
List<int> removeSelected() {
|
||||
var index = currentSelectedIndex();
|
||||
var state = (key as GlobalKey<_RequestRuleListState>).currentState;
|
||||
List<int> list = [];
|
||||
var selectedIndex = state?.currentSelectedIndex;
|
||||
state?.selected.forEach((key, value) {
|
||||
if (value == true) {
|
||||
list.add(key);
|
||||
if (selectedIndex == key) {
|
||||
state.currentSelectedIndex = -1;
|
||||
}
|
||||
}
|
||||
});
|
||||
state?.selected.clear();
|
||||
return list;
|
||||
state?.selected = -1;
|
||||
return index == -1 ? [] : [index];
|
||||
}
|
||||
|
||||
int currentSelectedIndex() {
|
||||
var state = (key as GlobalKey<_RequestRuleListState>).currentState;
|
||||
return state?.currentSelectedIndex ?? -1;
|
||||
return state?.selected ?? -1;
|
||||
}
|
||||
|
||||
changeState() {
|
||||
@@ -237,8 +230,7 @@ class RequestRuleList extends StatefulWidget {
|
||||
}
|
||||
|
||||
class _RequestRuleListState extends State<RequestRuleList> {
|
||||
final Map<int, bool> selected = {};
|
||||
int currentSelectedIndex = -1;
|
||||
int selected = -1;
|
||||
|
||||
changeState() {
|
||||
setState(() {});
|
||||
@@ -262,32 +254,43 @@ class _RequestRuleListState extends State<RequestRuleList> {
|
||||
rows: List.generate(
|
||||
widget.requestRewrites.rules.length,
|
||||
(index) => DataRow(
|
||||
cells: [
|
||||
DataCell(Text(widget.requestRewrites.rules[index].enabled ? "是" : "否")),
|
||||
DataCell(ConstrainedBox(
|
||||
constraints: const BoxConstraints(minWidth: 60),
|
||||
child: Text(
|
||||
'${widget.requestRewrites.rules[index].domain ?? ''}${widget.requestRewrites.rules[index].path}'))),
|
||||
DataCell(Container(
|
||||
constraints: const BoxConstraints(maxWidth: 180),
|
||||
cells: [
|
||||
cell(Text(widget.requestRewrites.rules[index].enabled ? "是" : "否"), index),
|
||||
cell(
|
||||
ConstrainedBox(
|
||||
constraints: const BoxConstraints(minWidth: 60, maxWidth: 150),
|
||||
child: Text(
|
||||
'${widget.requestRewrites.rules[index].domain ?? ''}${widget.requestRewrites.rules[index].path}')),
|
||||
index),
|
||||
cell(
|
||||
Container(
|
||||
constraints: const BoxConstraints(maxWidth: 150),
|
||||
child: SelectableText.rich(
|
||||
maxLines: 3,
|
||||
TextSpan(text: widget.requestRewrites.rules[index].requestBody),
|
||||
style: const TextStyle(fontSize: 12))),
|
||||
index),
|
||||
cell(
|
||||
Container(
|
||||
constraints: const BoxConstraints(maxWidth: 200),
|
||||
padding: const EdgeInsetsDirectional.all(10),
|
||||
child: SelectableText.rich(
|
||||
TextSpan(text: widget.requestRewrites.rules[index].requestBody),
|
||||
style: const TextStyle(fontSize: 12)))),
|
||||
DataCell(Container(
|
||||
constraints: const BoxConstraints(maxWidth: 300),
|
||||
padding: const EdgeInsetsDirectional.all(10),
|
||||
child: SelectableText.rich(
|
||||
TextSpan(text: widget.requestRewrites.rules[index].responseBody),
|
||||
style: const TextStyle(fontSize: 12)),
|
||||
))
|
||||
],
|
||||
selected: selected[index] == true,
|
||||
onSelectChanged: (value) {
|
||||
setState(() {
|
||||
selected[index] = value!;
|
||||
currentSelectedIndex = index;
|
||||
});
|
||||
})),
|
||||
maxLines: 5,
|
||||
TextSpan(text: widget.requestRewrites.rules[index].responseBody),
|
||||
style: const TextStyle(fontSize: 12)),
|
||||
),
|
||||
index)
|
||||
],
|
||||
selected: selected == index,
|
||||
)),
|
||||
)));
|
||||
}
|
||||
|
||||
DataCell cell(Widget child, int index) {
|
||||
return DataCell(child, onTap: () {
|
||||
setState(() {
|
||||
selected = index;
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,6 @@ String curlRequest(HttpRequest request) {
|
||||
if (request.bodyAsString.isNotEmpty) {
|
||||
body = " --data '${request.bodyAsString}' \\\n";
|
||||
}
|
||||
return "curl '${request.requestUrl}' \\\n"
|
||||
return "curl -X ${request.method.name} '${request.requestUrl}' \\\n"
|
||||
"${headers.join('\\\n')} $body \\\n --compressed";
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user