Repository navigation
Conversation
The Headers and Cookies tabs now have a copy button in the tab bar, the same as Request and Response. Headers are copied as key: value lines under each section title. Response cookies are copied as their raw Set-Cookie values and request cookies as a Cookie header value. Cookie values and image metadata are now selectable too. Also fixes calculateHeadersSize, which never joined list values because headers decoded from JSON are List<dynamic>, not List<String>.
There was a problem hiding this comment.
Code Review
This pull request adds copy buttons to the Headers and Cookies tabs of the network request inspector, and wraps cookie values and image metadata in SelectionArea to make them selectable. It also refactors the formatting logic for headers and cookies into reusable utility functions in http_utils.dart and adds comprehensive tests. The review feedback suggests improving robustness and idiomatic Dart by checking and casting to Iterable instead of List when handling multi-value headers.
| if (value is! List) { | ||
| yield '$key: $value'; | ||
| continue; | ||
| } |
There was a problem hiding this comment.
[CONCERN] Using Iterable instead of List is more robust and idiomatic in Dart when we only need to iterate and join elements. This also prevents potential runtime TypeErrors if the header values are represented as other Iterable types (e.g., Set or Queue) or typed as List<Object?> which might not implicitly downcast to List<dynamic> in strong mode.
| if (value is! List) { | |
| yield '$key: $value'; | |
| continue; | |
| } | |
| if (value is! Iterable) { | |
| yield '$key: $value'; | |
| continue; | |
| } |
References
- Key Principles: Readability, Maintainability, Consistency, and Code Reuse & DRY. (link)
There was a problem hiding this comment.
Good call, switched to checking Iterable here (and updated the doc comment to match). Added a test with a Set value too.
| .expand( | ||
| (entry) => entry.value is List ? entry.value as List : [entry.value], | ||
| ) |
There was a problem hiding this comment.
[CONCERN] Checking and casting to Iterable instead of List is safer and more idiomatic. This avoids potential runtime TypeErrors if entry.value is a list of a more specific type (like List<Object?> or List<String>) which might fail when cast directly to List<dynamic>.
| .expand( | |
| (entry) => entry.value is List ? entry.value as List : [entry.value], | |
| ) | |
| .expand( | |
| (entry) => entry.value is Iterable | |
| ? entry.value as Iterable | |
| : [entry.value], | |
| ) |
References
- Key Principles: Readability, Maintainability, Consistency, and Code Reuse & DRY. (link)
There was a problem hiding this comment.
Same change here, done.
|
Thanks for picking this up. Making Headers and Cookies copyable the same way as Request and Response closes a gap that's been awkward in the network inspector, and the curl-ready format (one Looking forward to seeing this land once it's ready for review. |
Part of #8190
The Headers and Cookies tabs in the network request inspector had no way to copy their contents, and the cookie table and image metadata weren't selectable at all. This adds a copy button to the tab bar for Headers and Cookies, the same as Request and Response already have, so all the tabs work the same way.
key: valuelines. Multi-value headers are joined the way they'd be sent (set-cookiegets one line per value,cookieis joined with;), so the text is easy to paste into a bug report. The General section is printed as plainkey: valuelines, the same as the tab shows it.Set-Cookievalues (parsing dropsMax-AgeandSameSite, so the raw header is used when it's there) and request cookies as aCookieheader value.SelectionArea. Selection doesn't work in VS Code on Mac (SelectableText and SelectionArea do not work correctly when calling document.execCommand("copy") unless you right-click flutter#182756), which is why the copy buttons are the main fix here.While in there I also fixed
calculateHeadersSize, used for the HAR export. It checkedvalue is List<String>, but headers decoded from JSON areList<dynamic>, so list values were counted with their brackets. It now shares the same formatting as the copy text, soheadersSizein exported HAR files changes for requests with multi-value headers (and is now correct for them).Per-row copy and the request list actions menu mentioned in the issue are left for a follow-up.
Before/after screenshots to come.
Pre-launch Checklist
General checklist
///).Issues checklist
contributions-welcomeorgood-first-issuelabel.contributions-welcomeorgood-first-issuelabel. I understand this means my PR might take longer to be reviewed.Tests checklist
AI-tooling checklist
Feature-change checklist
release-notes-not-requiredlabel or left a comment requesting the label be added.packages/devtools_app/release_notes/NEXT_RELEASE_NOTES.md.If you need help, consider asking for help on Discord.