Skip to content
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

fix: test before using Buffers #3400

Open
wants to merge 4 commits into
base: next
Choose a base branch
from
Open

fix: test before using Buffers #3400

wants to merge 4 commits into from

Conversation

ST-DDT
Copy link
Member

@ST-DDT ST-DDT commented Feb 12, 2025

Fixes #3285


Adds a feature check before committing to use the Buffer methods.

Alternative

Remove the Buffer "shortcut" check and usage from the base64url method.

@ST-DDT ST-DDT added c: bug Something isn't working c: docs Improvements or additions to documentation p: 1-normal Nothing urgent labels Feb 12, 2025
@ST-DDT ST-DDT added this to the vAnytime milestone Feb 12, 2025
@ST-DDT ST-DDT requested review from a team February 12, 2025 21:25
@ST-DDT ST-DDT self-assigned this Feb 12, 2025
Copy link

netlify bot commented Feb 12, 2025

Deploy Preview for fakerjs ready!

Name Link
🔨 Latest commit e1b0b4b
🔍 Latest deploy log https://app.netlify.com/sites/fakerjs/deploys/67ad147ba0bf67000878322f
😎 Deploy Preview https://deploy-preview-3400.fakerjs.dev
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify site configuration.

Copy link

codecov bot commented Feb 12, 2025

Codecov Report

Attention: Patch coverage is 77.77778% with 2 lines in your changes missing coverage. Please review.

Project coverage is 99.97%. Comparing base (7c749b6) to head (e1b0b4b).

Files with missing lines Patch % Lines
src/internal/base64.ts 77.77% 2 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             next    #3400      +/-   ##
==========================================
- Coverage   99.97%   99.97%   -0.01%     
==========================================
  Files        2811     2811              
  Lines      216965   216972       +7     
  Branches      941      941              
==========================================
+ Hits       216914   216919       +5     
- Misses         51       53       +2     
Files with missing lines Coverage Δ
src/internal/base64.ts 44.00% <77.77%> (+10.66%) ⬆️

Copy link
Member

@xDivisionByZerox xDivisionByZerox left a comment

Choose a reason for hiding this comment

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

I'm honestly fine with both solutions. Having the explicit check function with documentation linking to the related upstream issues, might remind someone in the future to look into this and remove the workaround. On the other side, most of us are propably suvscribed to the external issues as well and will get notified anyway.

src/internal/base64.ts Show resolved Hide resolved
@ST-DDT ST-DDT requested review from Shinigami92 and a team February 13, 2025 22:00
@Shinigami92
Copy link
Member

Shinigami92 commented Feb 14, 2025

My opinionated solution:

/* eslint-disable no-undef -- This file serves as a compatibility layer between environments */

/**
 * Checks whether the environment supports the given encoding on the `Buffer` class.
 * This is required because some `Buffer` polyfills do not support all encodings.
 *
 * @param encoding The encoding to check.
 *
 * @see https://www.npmjs.com/package/buffer
 * @see https://github.com/feross/buffer/issues/309
 */
function bufferFeatureCheck(encoding: BufferEncoding): boolean {
  try {
    return typeof Buffer.from("test").toString(encoding) === "string";
  } catch {
    return false;
  }
}

const SUPPORTS_BASE64_BUFFER =
  typeof Buffer === "undefined" || !bufferFeatureCheck("base64");
const SUPPORTS_BASE64_URL_BUFFER =
  typeof Buffer === "undefined" || !bufferFeatureCheck("base64url");

/**
 * This works the same as `Buffer.from(input).toString('base64')`
 * to work on both Node.js and browser environment.
 *
 * @internal
 *
 * @param input The string to encode to Base64.
 *
 * @returns Base64 encoded string.
 *
 * @see https://datatracker.ietf.org/doc/html/rfc4648
 *
 * @example const encodedHeader = toBase64(JSON.stringify(header));
 */
export function toBase64(input: string): string {
  if (SUPPORTS_BASE64_BUFFER) {
    return Buffer.from(input).toString("base64");
  }

  const utf8Bytes = new TextEncoder().encode(input);
  const binaryString = Array.from(utf8Bytes, (byte) =>
    String.fromCodePoint(byte)
  ).join("");
  return btoa(binaryString);
}

/**
 * This works the same as `Buffer.from(input).toString('base64url')`
 * to work on both Node.js and browser environment.
 *
 * @internal
 *
 * @param input The string to encode to Base64 URL.
 *
 * @returns Base64 URL encoded string.
 *
 * @see https://datatracker.ietf.org/doc/html/rfc4648
 *
 * @example const encodedHeader = toBase64Url(JSON.stringify(header));
 */
export function toBase64Url(input: string): string {
  if (SUPPORTS_BASE64_URL_BUFFER) {
    return Buffer.from(input).toString("base64url");
  }

  return toBase64(input)
    .replaceAll("+", "-")
    .replaceAll("/", "_")
    .replaceAll(/=+$/g, "");
}

I know this moves the check into the function, but makes it (to me) much more readable. I don't think that the condition has a to bad performance compared to actually craft the base64 string.

Edit: we might even be able to remove the typeof Buffer === "undefined", because the try-catch would catch it anyway 😅

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
c: bug Something isn't working c: docs Improvements or additions to documentation p: 1-normal Nothing urgent
Projects
None yet
Development

Successfully merging this pull request may close these issues.

internet.jwt() fails on documentation website
3 participants