Skip to content

Conversation

@bhokaremoin
Copy link
Contributor

@bhokaremoin bhokaremoin commented Dec 16, 2025

What does this PR do?

Fixes Google Fonts being corrupted when fonts.gstatic.com returns font files with incorrect content-type: text/html header.

Changes

  • Added detectFontMimeType() utility function in packages/core/src/utils.js that uses magic bytes detection to identify font formats (WOFF, WOFF2, TTF, OTF)
  • Updated saveResponseResource() in packages/core/src/network.js to detect Google Fonts served with text/html mime type and override with the actual font mime type
  • When a Google Font is detected with incorrect mime type, the code now triggers a direct request to get properly encoded binary content
  • Added comprehensive unit tests for detectFontMimeType() utility
  • Added integration tests for Google Fonts handling in the discovery flow

Why?

Google Fonts API sometimes returns font files with content-type: text/html instead of the correct font/* mime type. This causes Percy CLI to process these font files as HTML, leading to corruption of the binary font data.

Jira Ticket

https://browserstack.atlassian.net/browse/PPLT-4742

Related PRs

@bhokaremoin bhokaremoin requested a review from a team as a code owner December 16, 2025 19:54
@bhokaremoin bhokaremoin changed the title overiding mimeType for google fonts request Fix Google Fonts corruption from incorrect text/html mime type Dec 16, 2025
// Handles Google Fonts MIME type detection and override
// Google Fonts sometimes returns font files with text/html mime type
// This function detects the actual font format from the file content
export function handleGoogleFontMimeType(urlObj, mimeType, body, log, meta) {
Copy link
Contributor

@this-is-shivamsingh this-is-shivamsingh Dec 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

const FONT_HOST_PATTERNS = [
/fonts.gstatic.com$/,
/fonts.googleapis.com$/,
/googleapisserver.com/fonts/i,
/use.typekit.net$/, // Adobe Fonts
/fonts.adobe.com$/,
];

function isKnownFontProvider(urlObj) {
return FONT_HOST_PATTERNS.some(pattern =>
pattern.test(urlObj.hostname + urlObj.pathname)
);
}

something like this i was saying
FONT_HOST_PATTERNS -> this array you can get it from env or config file, i will say add 1 config under discovery

discovery:
  fonts-domains:
     - fonts.gstatic.com
     - adobefonts.com
  • default you can add fonts.gstatic.com

These are some of the font provider

https://fonts.googleapis.com/css | Free, large library, easy embed​
-- | --
- Bunny Fonts | https://fonts.bunny.net/css | Privacy-focused, Google Fonts alternative​
- Cloudflare Fonts | https://fonts.cloudflare.com | Serve fonts from your domain, privacy​
- CDNFonts | https://www.cdnfonts.com | 30,000+ free fonts, CDN hosted​
Font Awesome | https://kit.fontawesome.com | Icon fonts, free & paid options​
- Adobe Fonts | https://use.typekit.com | Premium fonts, cloud hosted​
Typography.com | https://typography.com/webfonts

- https://fonts.googleapis.com/css	Free, large library, easy embed​
- Bunny Fonts	https://fonts.bunny.net/css	Privacy-focused, Google Fonts alternative​
- Cloudflare Fonts	https://fonts.cloudflare.com/	Serve fonts from your domain, privacy​
- CDNFonts	https://www.cdnfonts.com/	30,000+ free fonts, CDN hosted​
- Font Awesome	https://kit.fontawesome.com/	Icon fonts, free & paid options​
- Adobe Fonts	https://use.typekit.com/	Premium fonts, cloud hosted​
Typography.com	https://typography.com/webfonts

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This you can push in followup PR

const detectedFontMime = detectFontMimeType(body);
if (detectedFontMime) {
mimeType = detectedFontMime;
log.debug(`- Detected Google Font as ${detectedFontMime} from content, overriding mime type`, meta);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
log.debug(`- Detected Google Font as ${detectedFontMime} from content, overriding mime type`, meta);
log.warn(`- Detected Google Font as ${detectedFontMime} with incorrect mimeType ${originalmimeType}`, meta);

}

// Check for OpenType signature: 'OTTO'
if (header === 'OTTO') {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

header.toLowerCase() === 'otto'

in case header comes in lower, this will not get detected

}

// Read the first 4 bytes as the file header
const header = buffer.slice(0, 4).toString('binary');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • you can normalize header here, in lowerCase itself

// Returns the detected MIME type or null if not a recognized font format
export function detectFontMimeType(buffer) {
try {
// Ensure buffer has at least 4 bytes
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in follow up PR, add a comment

  • For checking a valid font file, the first 4 characters are font type

Copy link
Contributor

@this-is-shivamsingh this-is-shivamsingh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 Approved, with conditional comments for follow up PR, before stable release

Comment on lines +46 to +53
if (header === 'wOFF') {
return 'font/woff';
}

// Check for WOFF2 signature: 'wOF2'
if (header === 'wOF2') {
return 'font/woff2';
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if (header === 'wOFF') {
return 'font/woff';
}
// Check for WOFF2 signature: 'wOF2'
if (header === 'wOF2') {
return 'font/woff2';
}
obj = {
'wof2': 'font/woff2',
'otto': 'fonts/woff',
'0x000x010x000x00': 'font/ttf'
}
if obj[header]:
return obj[header]
elseif obj[header.[first 4 char code]:
return obj[header[first 4 char code]
return null

@bhokaremoin bhokaremoin force-pushed the PPLT-4742-google-font-issue branch from f41fecf to 0f1146f Compare December 18, 2025 11:25
@bhokaremoin
Copy link
Contributor Author

@this-is-shivamsingh ACK.
Will unblock the customer with this changes releasing in beta, will send a followup PR. and resolve this comments.

@bhokaremoin bhokaremoin added the ✨ enhancement New feature or request label Dec 18, 2025
@bhokaremoin bhokaremoin merged commit 8d4474b into master Dec 18, 2025
94 of 95 checks passed
@bhokaremoin bhokaremoin deleted the PPLT-4742-google-font-issue branch December 18, 2025 15:02
bhokaremoin added a commit that referenced this pull request Dec 21, 2025
bhokaremoin added a commit that referenced this pull request Dec 22, 2025
…sts (#2073)

* resolving comments from PR #2068

* fixing lint

* fixing coverage
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

✨ enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants