Skip to content

fix: getFileExtension returns raw URL path instead of null for URLs without file extensions #4252

Description

@cax6505

Description

In @dub/utils, the getFileExtension(url) helper function incorrectly returns the full URL pathname (e.g. "/AVATAR" or "/API/V1/USERS") when given a URL that does not contain a file extension.

Reproduction

import { getFileExtension } from "@dub/utils";

console.log(getFileExtension("https://dub.co/avatar")); 
// Output: "/AVATAR" (Expected: null)

console.log(getFileExtension("https://dub.co/api/v1/users")); 
// Output: "/API/V1/USERS" (Expected: null)

Cause

In packages/utils/src/functions/urls.ts:

export const getFileExtension = (url: string): string | null => {
  try {
    const pathname = new URL(url).pathname;
    const extension = pathname.split(".").pop(); // When pathname has no ".", returns entire pathname
    return extension ? extension.toUpperCase() : null;
  } catch { ... }
};

When pathname has no dot (.), pathname.split(".") yields ["/avatar"]. Calling .pop() returns "/avatar", which is truthy, so it returns "/AVATAR".

Impact

In ResourceCard (resources/page.tsx), brand logos with extensionless asset URLs display badge labels like "/LOGO · 24 KB" instead of "Unknown · 24 KB".

Proposed Fix

Verify that the extracted filename actually contains a dot before returning the extension:

export const getFileExtension = (url: string): string | null => {
  try {
    const pathname = new URL(url).pathname;
    const filename = pathname.split("/").pop() || "";
    if (!filename.includes(".")) return null;
    const extension = filename.split(".").pop();
    return extension && extension !== filename ? extension.toUpperCase() : null;
  } catch {
    return null;
  }
};

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions