fix(web): render AVIF images and IANA icon favicons in the response tab (#8232)

* fix(web): render AVIF images and IANA icon favicons in the response tab

The `ViewImage` regex in `HttpMessage.tsx` rejected two valid image
content types, so the response tab did not render them inline:

1. `image/avif` was missing from the alternation. AVIF is widely served
   by image CDNs and decoded natively in `<img>` by Chrome 85+,
   Firefox 93+, and Safari 16.1+.
2. `image/vnd.microsoft.icon` (the IANA-canonical `.ico` MIME) never
   matched because the alternation had `vnc.microsoft.icon` — a
   `vnc`/`vnd` typo. The de-facto legacy `image/x-icon` continued to
   work, which made the bug easy to miss. The dots are also unescaped,
   so the regex coincidentally matches `image/vncXmicrosoftXicon` for
   any single character `X`.

Added `avif`, corrected `vnc` → `vnd`, and escaped the dots. Added a
`ViewImage.matches` unit test covering both the additions and the
existing image MIME types.

* [autofix.ci] apply automated fixes

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
This commit is contained in:
Ariel 2026-05-15 11:12:27 +03:00 committed by GitHub
parent fb8c1a9862
commit e20a24b54e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 24 additions and 1 deletions

View file

@ -7,6 +7,8 @@
## Unreleased: mitmproxy next
- mitmweb: Fix AVIF images and `image/vnd.microsoft.icon` favicons not rendering in the response tab.
([#8232](https://github.com/mitmproxy/mitmproxy/pull/8232), @ariel42)
## 12 May 2026: mitmproxy 12.2.3

View file

@ -101,6 +101,27 @@ test("ViewImage", async () => {
expect(asFragment()).toMatchSnapshot();
});
test("ViewImage.matches", () => {
const flow = TFlow();
const matches = (contentType: string) => {
flow.response.headers = [["Content-Type", contentType]];
return ViewImage.matches(flow.response);
};
expect(matches("image/png")).toBe(true);
expect(matches("image/jpeg")).toBe(true);
expect(matches("image/jpg")).toBe(true);
expect(matches("image/gif")).toBe(true);
expect(matches("image/webp")).toBe(true);
expect(matches("image/avif")).toBe(true);
expect(matches("image/svg+xml")).toBe(true);
expect(matches("image/vnd.microsoft.icon")).toBe(true);
expect(matches("image/x-icon")).toBe(true);
expect(matches("IMAGE/AVIF")).toBe(true);
expect(matches("image/heic")).toBe(false);
expect(matches("application/json")).toBe(false);
expect(matches("video/mp4")).toBe(false);
});
/*
This test differs from the one above because clicking the copy button triggers 'handleClickCopyButton'.
In the previous test, the response contained "raw content," which caused an "invalid JSON response body" error

View file

@ -228,7 +228,7 @@ function CopyButton({ flow, message }: CopyButtonProps) {
}
const isImage =
/^image\/(png|jpe?g|gif|webp|vnc.microsoft.icon|x-icon|svg\+xml)$/i;
/^image\/(png|jpe?g|gif|webp|avif|vnd\.microsoft\.icon|x-icon|svg\+xml)$/i;
ViewImage.matches = (msg) =>
isImage.test(MessageUtils.getContentType(msg) || "");