-
Notifications
You must be signed in to change notification settings - Fork 389
Fix cancelled HTTP requests showing as Pending in DevTools Network tab #9685
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from 5 commits
45b1c2a
3ecd00f
d74f363
f5204f6
39babfa
2ad05f8
54eafea
0503e54
d9162b6
0f7a854
76cd92d
8a50293
5de8e82
d3d1ae7
8f8ed54
59d02dc
686699f
f5c8639
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -50,11 +50,8 @@ ExpansionTile _buildTile( | |
| class HttpRequestHeadersView extends StatelessWidget { | ||
| const HttpRequestHeadersView(this.data, {super.key}); | ||
|
|
||
| @visibleForTesting | ||
| static const generalKey = Key('General'); | ||
| @visibleForTesting | ||
| static const requestHeadersKey = Key('Request Headers'); | ||
| @visibleForTesting | ||
| static const responseHeadersKey = Key('Response Headers'); | ||
|
|
||
| final DartIOHttpRequestData data; | ||
|
|
@@ -460,9 +457,7 @@ bool _isJsonDecodable(String source) { | |
| class HttpRequestCookiesView extends StatelessWidget { | ||
| const HttpRequestCookiesView(this.data, {super.key}); | ||
|
|
||
| @visibleForTesting | ||
| static const requestCookiesKey = Key('Request Cookies'); | ||
| @visibleForTesting | ||
| static const responseCookiesKey = Key('Response Cookies'); | ||
|
|
||
| final DartIOHttpRequestData data; | ||
|
|
@@ -600,9 +595,7 @@ class NetworkRequestOverviewView extends StatelessWidget { | |
|
|
||
| static const _keyWidth = 110.0; | ||
| static const _timingGraphHeight = 18.0; | ||
| @visibleForTesting | ||
| static const httpTimingGraphKey = Key('Http Timing Graph Key'); | ||
| @visibleForTesting | ||
| static const socketTimingGraphKey = Key('Socket Timing Graph Key'); | ||
|
|
||
| final NetworkRequest data; | ||
|
|
@@ -721,7 +714,9 @@ class NetworkRequestOverviewView extends StatelessWidget { | |
|
|
||
| Widget _buildHttpTimeGraph() { | ||
| final data = this.data as DartIOHttpRequestData; | ||
| if (data.duration == null || data.instantEvents.isEmpty) { | ||
| if (data.duration == null || | ||
|
||
| data.duration!.inMicroseconds == 0 || | ||
| data.instantEvents.isEmpty) { | ||
| return Container( | ||
| key: httpTimingGraphKey, | ||
| height: 18.0, | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -140,9 +140,27 @@ class DartIOHttpRequestData extends NetworkRequest { | |
|
|
||
| @override | ||
| Duration? get duration { | ||
| if (inProgress || !isValid) return null; | ||
| // Timestamps are in microseconds | ||
| return _endTime!.difference(_request.startTime); | ||
| if (_hasError) { | ||
|
||
| final start = _request.startTime; | ||
| final end = _request.endTime; | ||
| return end?.difference(start); | ||
| } | ||
|
|
||
| // Cancelled request | ||
srawlins marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| if (_request.isRequestComplete && | ||
| !_request.isResponseComplete && | ||
| _request.response == null) { | ||
| return Duration.zero; | ||
|
||
| } | ||
|
|
||
| final start = _request.startTime; | ||
| final end = _request.response?.endTime ?? _request.endTime; | ||
|
|
||
| if (end != null) { | ||
| return end.difference(start); | ||
| } | ||
|
|
||
| return null; | ||
| } | ||
|
|
||
| /// Whether the request is safe to display in the UI. | ||
|
|
@@ -227,11 +245,19 @@ class DartIOHttpRequestData extends NetworkRequest { | |
| return connectionInfo != null ? connectionInfo[_localPortKey] : null; | ||
| } | ||
|
|
||
| /// True if the HTTP request hasn't completed yet, determined by the lack of | ||
| /// an end time in the response data. | ||
| @override | ||
srawlins marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| bool get inProgress => | ||
| _hasError ? !_request.isRequestComplete : !_request.isResponseComplete; | ||
| bool get inProgress { | ||
| // Detect cancelled requests (request finished but response never arrived) | ||
| if (_request.isRequestComplete && | ||
| !_request.isResponseComplete && | ||
| _request.response == null) { | ||
| return false; | ||
| } | ||
|
|
||
| return !(_hasError | ||
| ? _request.isRequestComplete | ||
| : _request.isResponseComplete); | ||
| } | ||
|
|
||
| /// All instant events logged to the timeline for this HTTP request. | ||
| List<DartIOHttpInstantEvent> get instantEvents { | ||
|
|
@@ -301,8 +327,17 @@ class DartIOHttpRequestData extends NetworkRequest { | |
| DateTime get startTimestamp => _request.startTime; | ||
|
|
||
| @override | ||
| String? get status => | ||
| _hasError ? 'Error' : _request.response?.statusCode.toString(); | ||
| String? get status { | ||
| if (_hasError) return 'Error'; | ||
srawlins marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| if (_request.isRequestComplete && | ||
| !_request.isResponseComplete && | ||
| _request.response == null) { | ||
| return 'Cancelled'; | ||
| } | ||
|
|
||
| return _request.response?.statusCode.toString(); | ||
| } | ||
|
|
||
| @override | ||
| String get uri => _request.uri.toString(); | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.