-
-
Notifications
You must be signed in to change notification settings - Fork 4.1k
Description
Package.json file
{
"name": "medusa project",
"version": "0.0.1",
"description": "The backend for the storefront",
"author": "Medusa (https://medusajs.com)",
"license": "UNLICENSED",
"keywords": [
"sqlite",
"postgres",
"typescript",
"ecommerce",
"headless",
"medusa"
],
"scripts": {
"build": "medusa build",
},
"lint-staged": {
"**/*": "prettier --write --ignore-unknown"
},
"dependencies": {
"@clerk/backend": "^2.29.3",
"@clerk/express": "^1.7.63",
"@clerk/shared": "^3.43.0",
"@medusajs/admin-sdk": "2.13.1",
"@medusajs/admin-shared": "2.13.1",
"@medusajs/cache-redis": "2.13.1",
"@medusajs/cli": "2.13.1",
"@medusajs/dashboard": "2.13.1",
"@medusajs/draft-order": "2.13.1",
"@medusajs/event-bus-redis": "2.13.1",
"@medusajs/file-s3": "2.13.1",
"@medusajs/framework": "2.13.1",
"@medusajs/js-sdk": "2.13.1",
"@medusajs/medusa": "2.13.1",
"@medusajs/types": "2.13.1",
"@medusajs/ui": "^4.0.21",
"@medusajs/utils": "2.13.1",
"@medusajs/workflow-engine-redis": "2.13.1",
"@mikro-orm/core": "6.4.16",
"@mikro-orm/knex": "6.4.16",
"@mikro-orm/migrations": "6.4.16",
"@mikro-orm/postgresql": "6.4.16",
"@opentelemetry/api": "^1.9.0",
"@opentelemetry/exporter-trace-otlp-grpc": "^0.203.0",
"@opentelemetry/instrumentation-pg": "^0.56.1",
"@opentelemetry/resources": "^2.0.1",
"@opentelemetry/sdk-node": "^0.203.0",
"@opentelemetry/sdk-trace-node": "^2.0.1",
"@react-email/components": "0.5.7",
"@segment/analytics-node": "^2.3.0",
"@sentry/node": "^10.9.0",
"@sentry/opentelemetry-node": "^7.114.0",
"@tanstack/react-query": "^5.67.3",
"awilix": "^8.0.1",
"dotenv": "^16.5.0",
"express": "^4.21.0",
"jsonwebtoken": "^9.0.2",
"mime-types": "^2.1.35",
"multer": "^2.0.2",
"nodemailer": "^7.0.4",
"pg": "^8.13.0",
"posthog-node": "^4.17.1",
"rate-limiter-flexible": "^7.1.1",
"resend": "^4.6.0",
"sharp": "^0.34.3",
"slugify": "^1.6.6",
"ssh2-sftp-client": "^12.0.0",
"stripe": "^17.7.0",
"svix": "^1.68.0",
"zod": "^3.22.4"
},
"devDependencies": {
"@clerk/types": "^4.101.11",
"@faker-js/faker": "^9.2.0",
"@medusajs/test-utils": "2.13.1",
"@mikro-orm/cli": "6.4.16",
"@swc/core": "1.5.7",
"@swc/jest": "^0.2.36",
"@types/jest": "^29.5.13",
"@types/jsonwebtoken": "^9.0.7",
"@types/multer": "^2.0.0",
"@types/node": "^20.0.0",
"@types/nodemailer": "^6.4.17",
"@types/pg": "^8.11.10",
"@types/react": "^18.3.2",
"@types/react-dom": "^18.3.2",
"@types/ssh2-sftp-client": "^9.0.4",
"@vitejs/plugin-react": "^4.4.1",
"jest": "^29.7.0",
"msw": "2.6.8",
"prop-types": "^15.8.1",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-email": "4.3.2",
"rimraf": "^6.0.1",
"ts-node": "^10.9.2",
"tsc-alias": "^1.8.16",
"tsx": "^4.19.3",
"type-fest": "^4.37.0",
"typescript": "^5.8.3",
"vite": "^5.2.11",
"vite-tsconfig-paths": "^5.1.4",
"vitest": "^3.1.2"
},
"engines": {
"node": ">=22.0.0 <23.0.0",
"pnpm": ">=10.6"
},
"packageManager": "pnpm@10.15.0+sha512.486ebc259d3e999a4e8691ce03b5cac4a71cbeca39372a9b762cb500cfdf0873e2cb16abe3d951b1ee2cf012503f027b98b6584e4df22524e0c7450d9ec7aa7b"
}Node.js version
v22
Database and its version
16.2
Operating system name and version
MacOS Tahoe 26.2 (25C56)
Browser name
No response
What happended?
This bug was introduced in PR #14209 - "fix: escape non-ascii characters in filenames in s3 file provider".
The PR added encodeURIComponent(fileKey) to handle non-ASCII characters in filenames (e.g., Chinese characters). The problem is encodeURIComponent also encodes / → %2F, which breaks path prefixes like public/ → public%2F.
The problem statement is valid - non-ASCII filenames (e.g., 文档.pdf) and special characters (file?.jpg) do need URL encoding for S3 URLs to work. But the PR uses encodeURIComponent(fileKey) on the entire key including the path prefix. This fixes the edge case (non-ASCII characters) but broke the common case (any file with a path prefix containing /.
// fileKey = "public/thumbnail.jpg"
url: `${this.config_.fileUrl}/${encodeURIComponent(fileKey)}`
// Result: https://cdn.example.com/public%2Fthumbnail.jpg ❌The fix should have used encodeURI() instead (which preserves /), or only encoded the filename portion, not the entire key including the path prefix.
url: `${this.config_.fileUrl}/${encodeURI(fileKey)}`
// Result: https://cdn.example.com/public/文档.pdf ✓Or
url: `${this.config_.fileUrl}/${prefix}${encodeURIComponent(filename)}`
// Result: https://cdn.example.com/public/文档.pdf && https://cdn.example.com/public/image.png ✓Steps to Reproduce
- Configure S3 file provider with a prefix (e.g.,
prefix: "public/") - Upload any file
- Observe the returned URL
Expected behavior
fileKey: "public/thumbnail-01ABC123.jpg"
URL: "https://cdn.example.com/public/thumbnail-01ABC123.jpg"
Actual behavior
fileKey: "public/thumbnail-01ABC123.jpg"
URL: "https://cdn.example.com/public%2Fthumbnail-01ABC123.jpg"
Link to reproduction repo
n/a