Skip to content

Commit e9da702

Browse files
AlexV525Copilot
andauthored
✨ Add requestUrl & responseUrl to LogInterceptor for more precise controls (#2452)
Resolves #2450 --------- Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com>
1 parent c53d0b3 commit e9da702

File tree

3 files changed

+277
-35
lines changed

3 files changed

+277
-35
lines changed

dio/CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ See the [Migration Guide][] for the complete breaking changes list.**
55

66
## Unreleased
77

8-
*None.*
8+
- Add `requestUrl` and `responseUrl` parameters to `LogInterceptor` for more precise control over URL logging.
99

1010
## 5.9.0
1111

dio/lib/src/interceptors/log.dart

Lines changed: 65 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -15,36 +15,44 @@ import '../response.dart';
1515
/// ```dart
1616
/// dio.interceptors.add(
1717
/// LogInterceptor(
18-
/// logPrint: (o) => debugPrint(o.toString()),
18+
/// logPrint: (o) => debugPrint(o.toString()),
1919
/// ),
2020
/// );
2121
/// ```
2222
class LogInterceptor extends Interceptor {
2323
LogInterceptor({
2424
this.request = true,
25+
this.requestUrl = true,
2526
this.requestHeader = true,
2627
this.requestBody = false,
28+
this.responseUrl = true,
2729
this.responseHeader = true,
2830
this.responseBody = false,
2931
this.error = true,
3032
this.logPrint = _debugPrint,
3133
});
3234

33-
/// Print request [Options]
35+
/// Print request [RequestOptions]
3436
bool request;
3537

36-
/// Print request header [Options.headers]
38+
/// Print request URL [RequestOptions.uri]
39+
bool requestUrl;
40+
41+
/// Print request headers [RequestOptions.headers]
3742
bool requestHeader;
3843

39-
/// Print request data [Options.data]
44+
/// Print request data [RequestOptions.data]
4045
bool requestBody;
4146

42-
/// Print [Response.data]
43-
bool responseBody;
47+
/// Print [Response.realUri]
48+
bool responseUrl;
4449

4550
/// Print [Response.headers]
4651
bool responseHeader;
4752

53+
/// Print [Response.data]
54+
bool responseBody;
55+
4856
/// Print error message
4957
bool error;
5058

@@ -65,9 +73,40 @@ class LogInterceptor extends Interceptor {
6573
RequestOptions options,
6674
RequestInterceptorHandler handler,
6775
) {
68-
logPrint('*** Request ***');
69-
_printKV('uri', options.uri);
70-
//options.headers;
76+
_printRequest(options);
77+
handler.next(options);
78+
}
79+
80+
@override
81+
void onResponse(Response response, ResponseInterceptorHandler handler) {
82+
_printResponse(response);
83+
handler.next(response);
84+
}
85+
86+
@override
87+
void onError(DioException err, ErrorInterceptorHandler handler) {
88+
if (error) {
89+
logPrint('*** DioException ***:');
90+
logPrint('uri: ${err.requestOptions.uri}');
91+
logPrint('$err');
92+
if (err.response != null) {
93+
_printResponse(err.response!);
94+
}
95+
logPrint('');
96+
}
97+
98+
handler.next(err);
99+
}
100+
101+
void _printRequest(RequestOptions options) {
102+
if (!request && !requestUrl && !requestHeader && !requestBody) {
103+
return;
104+
}
105+
106+
if (requestUrl) {
107+
logPrint('*** Request ***');
108+
_printKV('uri', options.uri);
109+
}
71110

72111
if (request) {
73112
_printKV('method', options.method);
@@ -83,56 +122,48 @@ class LogInterceptor extends Interceptor {
83122
);
84123
_printKV('extra', options.extra);
85124
}
125+
86126
if (requestHeader) {
87127
logPrint('headers:');
88128
options.headers.forEach((key, v) => _printKV(' $key', v));
89129
}
130+
90131
if (requestBody) {
91132
logPrint('data:');
92133
_printAll(options.data);
93134
}
94-
logPrint('');
95-
96-
handler.next(options);
97-
}
98135

99-
@override
100-
void onResponse(Response response, ResponseInterceptorHandler handler) {
101-
logPrint('*** Response ***');
102-
_printResponse(response);
103-
handler.next(response);
136+
logPrint('');
104137
}
105138

106-
@override
107-
void onError(DioException err, ErrorInterceptorHandler handler) {
108-
if (error) {
109-
logPrint('*** DioException ***:');
110-
logPrint('uri: ${err.requestOptions.uri}');
111-
logPrint('$err');
112-
if (err.response != null) {
113-
_printResponse(err.response!);
114-
}
115-
logPrint('');
139+
void _printResponse(Response response) {
140+
if (!responseUrl && !responseHeader && !responseBody) {
141+
return;
116142
}
117143

118-
handler.next(err);
119-
}
144+
if (responseUrl) {
145+
logPrint('*** Response ***');
146+
_printKV('uri', response.realUri);
147+
}
120148

121-
void _printResponse(Response response) {
122-
_printKV('uri', response.requestOptions.uri);
123149
if (responseHeader) {
124150
_printKV('statusCode', response.statusCode);
125-
if (response.isRedirect == true) {
126-
_printKV('redirect', response.realUri);
151+
if (response.statusMessage != null) {
152+
_printKV('statusMessage', response.statusMessage);
153+
}
154+
if (response.redirects.isNotEmpty) {
155+
_printKV('redirects', response.redirects);
127156
}
128157

129158
logPrint('headers:');
130159
response.headers.forEach((key, v) => _printKV(' $key', v.join('\r\n\t')));
131160
}
161+
132162
if (responseBody) {
133163
logPrint('Response Text:');
134164
_printAll(response.toString());
135165
}
166+
136167
logPrint('');
137168
}
138169

dio/test/interceptor_test.dart

Lines changed: 211 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -765,6 +765,217 @@ void main() {
765765
});
766766
});
767767

768+
group('LogInterceptor', () {
769+
test('requestUrl controls URL logging in requests', () async {
770+
final dio = Dio();
771+
dio.options.baseUrl = MockAdapter.mockBase;
772+
dio.httpClientAdapter = MockAdapter();
773+
774+
final logs = <String>[];
775+
dio.interceptors.add(
776+
LogInterceptor(
777+
requestUrl: true,
778+
requestHeader: false,
779+
requestBody: false,
780+
request: false,
781+
responseUrl: false,
782+
responseHeader: false,
783+
responseBody: false,
784+
logPrint: (o) => logs.add(o.toString()),
785+
),
786+
);
787+
788+
await dio.get('/test');
789+
790+
expect(logs.any((log) => log.contains('*** Request ***')), true);
791+
expect(logs.any((log) => log.contains('uri:')), true);
792+
expect(logs.any((log) => log.contains('/test')), true);
793+
});
794+
795+
test('requestUrl=false prevents URL logging in requests', () async {
796+
final dio = Dio();
797+
dio.options.baseUrl = MockAdapter.mockBase;
798+
dio.httpClientAdapter = MockAdapter();
799+
800+
final logs = <String>[];
801+
dio.interceptors.add(
802+
LogInterceptor(
803+
requestUrl: false,
804+
requestHeader: false,
805+
requestBody: false,
806+
request: false,
807+
responseUrl: false,
808+
responseHeader: false,
809+
responseBody: false,
810+
logPrint: (o) => logs.add(o.toString()),
811+
),
812+
);
813+
814+
await dio.get('/test');
815+
816+
expect(logs.any((log) => log.contains('*** Request ***')), false);
817+
expect(logs.any((log) => log.contains('uri:')), false);
818+
});
819+
820+
test('responseUrl controls URL logging in responses', () async {
821+
final dio = Dio();
822+
dio.options.baseUrl = MockAdapter.mockBase;
823+
dio.httpClientAdapter = MockAdapter();
824+
825+
final logs = <String>[];
826+
dio.interceptors.add(
827+
LogInterceptor(
828+
requestUrl: false,
829+
requestHeader: false,
830+
requestBody: false,
831+
request: false,
832+
responseUrl: true,
833+
responseHeader: false,
834+
responseBody: false,
835+
logPrint: (o) => logs.add(o.toString()),
836+
),
837+
);
838+
839+
await dio.get('/test');
840+
841+
expect(logs.any((log) => log.contains('*** Response ***')), true);
842+
expect(logs.any((log) => log.contains('uri:')), true);
843+
expect(logs.any((log) => log.contains('/test')), true);
844+
});
845+
846+
test('responseUrl=false prevents URL logging in responses', () async {
847+
final dio = Dio();
848+
dio.options.baseUrl = MockAdapter.mockBase;
849+
dio.httpClientAdapter = MockAdapter();
850+
851+
final logs = <String>[];
852+
dio.interceptors.add(
853+
LogInterceptor(
854+
requestUrl: false,
855+
requestHeader: false,
856+
requestBody: false,
857+
request: false,
858+
responseUrl: false,
859+
responseHeader: false,
860+
responseBody: false,
861+
logPrint: (o) => logs.add(o.toString()),
862+
),
863+
);
864+
865+
await dio.get('/test');
866+
867+
expect(logs.any((log) => log.contains('*** Response ***')), false);
868+
});
869+
870+
test('requestUrl and responseUrl work independently', () async {
871+
final dio = Dio();
872+
dio.options.baseUrl = MockAdapter.mockBase;
873+
dio.httpClientAdapter = MockAdapter();
874+
875+
// Test: requestUrl=true, responseUrl=false
876+
final logs1 = <String>[];
877+
dio.interceptors.clear();
878+
dio.interceptors.add(
879+
LogInterceptor(
880+
requestUrl: true,
881+
requestHeader: false,
882+
requestBody: false,
883+
request: false,
884+
responseUrl: false,
885+
responseHeader: false,
886+
responseBody: false,
887+
logPrint: (o) => logs1.add(o.toString()),
888+
),
889+
);
890+
891+
await dio.get('/test');
892+
893+
expect(logs1.any((log) => log.contains('*** Request ***')), true);
894+
expect(logs1.any((log) => log.contains('*** Response ***')), false);
895+
896+
// Test: requestUrl=false, responseUrl=true
897+
final logs2 = <String>[];
898+
dio.interceptors.clear();
899+
dio.interceptors.add(
900+
LogInterceptor(
901+
requestUrl: false,
902+
requestHeader: false,
903+
requestBody: false,
904+
request: false,
905+
responseUrl: true,
906+
responseHeader: false,
907+
responseBody: false,
908+
logPrint: (o) => logs2.add(o.toString()),
909+
),
910+
);
911+
912+
await dio.get('/test');
913+
914+
expect(logs2.any((log) => log.contains('*** Request ***')), false);
915+
expect(logs2.any((log) => log.contains('*** Response ***')), true);
916+
});
917+
918+
test('requestUrl can be combined with other request flags', () async {
919+
final dio = Dio();
920+
dio.options.baseUrl = MockAdapter.mockBase;
921+
dio.httpClientAdapter = MockAdapter();
922+
923+
final logs = <String>[];
924+
dio.interceptors.add(
925+
LogInterceptor(
926+
requestUrl: true,
927+
requestHeader: true,
928+
requestBody: true,
929+
request: true,
930+
responseUrl: false,
931+
responseHeader: false,
932+
responseBody: false,
933+
logPrint: (o) => logs.add(o.toString()),
934+
),
935+
);
936+
937+
await dio.get('/test');
938+
939+
expect(logs.any((log) => log.contains('*** Request ***')), true);
940+
expect(logs.any((log) => log.contains('uri:')), true);
941+
expect(logs.any((log) => log.contains('method:')), true);
942+
expect(logs.any((log) => log.contains('headers:')), true);
943+
});
944+
945+
test('responseUrl can be combined with other response flags', () async {
946+
final dio = Dio();
947+
dio.options.baseUrl = MockAdapter.mockBase;
948+
dio.httpClientAdapter = MockAdapter();
949+
950+
final logs = <String>[];
951+
dio.interceptors.add(
952+
LogInterceptor(
953+
requestUrl: false,
954+
requestHeader: false,
955+
requestBody: false,
956+
request: false,
957+
responseUrl: true,
958+
responseHeader: true,
959+
responseBody: true,
960+
logPrint: (o) => logs.add(o.toString()),
961+
),
962+
);
963+
964+
await dio.get('/test');
965+
966+
expect(logs.any((log) => log.contains('*** Response ***')), true);
967+
expect(logs.any((log) => log.contains('uri:')), true);
968+
expect(logs.any((log) => log.contains('statusCode:')), true);
969+
expect(logs.any((log) => log.contains('headers:')), true);
970+
});
971+
972+
test('default values enable requestUrl and responseUrl', () {
973+
final interceptor = LogInterceptor();
974+
expect(interceptor.requestUrl, true);
975+
expect(interceptor.responseUrl, true);
976+
});
977+
});
978+
768979
test('Size of Interceptors', () {
769980
final interceptors1 = Dio().interceptors;
770981
expect(interceptors1.length, equals(1));

0 commit comments

Comments
 (0)