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

feat: Replace existing router with the new implementation #11646

Merged
merged 26 commits into from
Mar 4, 2025

Conversation

thetutlage
Copy link
Contributor

@thetutlage thetutlage commented Feb 27, 2025

Fixes: FRMW-2925

This PR revamps the internal implementation of our HTTP router to be more predicatable and fixes some long pending issues like #11595, #11355, and #11620

The root of the issues with the old implementation were mainly around the following decisions.

  • Plugins, Medusa core and the application used isolated router instances of Express. This means global middlewares and error handlers are isolated too. If you define an error handler in your app, it won't be able to handle errors from the core routes.

  • Middlewares defined inside the src/api/middlewares.ts file were always defined before the filesystem routes and this lead to unexpected behavior in many scanerios. For example, the middleware handler registered for route admin/payments/payment-providers will also run when a request comes in for /admin/payments/:id, even though there is a static route in place for the /admin/payments/payment-providers URI.

  • There was no clarity on the ordering in which routes and middleware were executed. With the new implementation, this has been fixed (more on ordering is discussed below).

  • Overriding an existing route defines multiple express handlers under the hood. It worked previously, because the route handlers never call next, hence the previous implementation was never executed. With the newer implementation, the route overrides from a Medusa application will be registered over the routes from core or the plugins.

To resolve these issues, we’ve rebuilt the loader from scratch to ensure predictable behavior in how routes and middleware are registered within the application. Additionally, the old API Routes loader unintentionally allowed overriding core API routes and middleware. While this behavior remains for now, it will be removed in a future release. Please prepare your application based on the updated behavior outlined below.

Global middleware

A global middleware is defined using the defineMiddlewares function without specifying an HTTP method.

defineMiddlewares([
  {
    matcher: '/admin',
    middleware: [
      (req, res, next) => console.log("Hi from global middleware")
    ],
  }
])

The order of registering global middleware is as follows:

  1. Global middleware from the core
  2. Global middleware from plugins (in the order plugins are registered)
  3. Global middleware from the app

Route middleware

A route middleware is also defined using the defineMiddlewares method. However, they must always specify the HTTP method(s) they want to target.

defineMiddlewares([
  {
    matcher: '/admin/*',
    methods: ["GET", "POST"],
    middleware: [
      (req, res, next) => console.log("Hi from route middleware")
    ],
  }
])

The order of registering route middleware is as follows:

  1. Route middleware from the core
  2. Route middleware from plugins (in the order plugins are registered)
  3. Route middleware from the app

API Routes

An API Route is always attached to a method, decided by the exported const from the route file. API Routes are registered by scanning the filesystem.

Two types of API Routes are supported:

  1. Static segments: /admin/products/route.ts
  2. Dynamic segments: /admin/products/[id]/route.ts

Sorting routes and middleware

Before registering routes + middleware with Express, they are sorted as described below:

  1. Global middleware
  2. Route middleware
  3. API Routes

On top of this, each segment from the API Route matcher is sorted by its specificity:

  1. Wildcard segments, e.g. /admin/products/*
  2. Regex segments, e.g. /admin/(product-types|product-collections)
  3. Static segments, e.g. /admin/products
  4. Dynamic segments, e.g. /admin/products/:id

Important note about middleware
Middleware never overrides any existing middleware; they are added to the stack of existing middleware. For example, if you define a custom validation middleware on an existing route, then both the original and the custom validation middleware will run.

Copy link

vercel bot commented Feb 27, 2025

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
api-reference 🔄 Building (Inspect) Visit Preview 💬 Add feedback Mar 4, 2025 11:39am
medusa-dashboard ✅ Ready (Inspect) Visit Preview 💬 Add feedback Mar 4, 2025 11:39am
6 Skipped Deployments
Name Status Preview Comments Updated (UTC)
api-reference-v2 ⬜️ Ignored (Inspect) Visit Preview Mar 4, 2025 11:39am
docs-ui ⬜️ Ignored (Inspect) Visit Preview Mar 4, 2025 11:39am
docs-v2 ⬜️ Ignored (Inspect) Visit Preview Mar 4, 2025 11:39am
medusa-docs ⬜️ Ignored (Inspect) Visit Preview Mar 4, 2025 11:39am
resources-docs ⬜️ Ignored (Inspect) Visit Preview Mar 4, 2025 11:39am
user-guide ⬜️ Ignored (Inspect) Visit Preview Mar 4, 2025 11:39am

Copy link

changeset-bot bot commented Feb 27, 2025

🦋 Changeset detected

Latest commit: af3ff46

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 65 packages
Name Type
@medusajs/medusa Patch
@medusajs/framework Patch
integration-tests-http Patch
@medusajs/test-utils Patch
@medusajs/api-key Patch
@medusajs/auth Patch
@medusajs/cache-inmemory Patch
@medusajs/cache-redis Patch
@medusajs/cart Patch
@medusajs/currency Patch
@medusajs/customer Patch
@medusajs/event-bus-local Patch
@medusajs/event-bus-redis Patch
@medusajs/file Patch
@medusajs/fulfillment Patch
@medusajs/index Patch
@medusajs/inventory Patch
@medusajs/link-modules Patch
@medusajs/locking Patch
@medusajs/notification Patch
@medusajs/order Patch
@medusajs/payment Patch
@medusajs/pricing Patch
@medusajs/product Patch
@medusajs/promotion Patch
@medusajs/region Patch
@medusajs/sales-channel Patch
@medusajs/stock-location Patch
@medusajs/store Patch
@medusajs/tax Patch
@medusajs/user Patch
@medusajs/workflow-engine-inmemory Patch
@medusajs/workflow-engine-redis Patch
@medusajs/auth-emailpass Patch
@medusajs/auth-github Patch
@medusajs/auth-google Patch
@medusajs/file-local Patch
@medusajs/file-s3 Patch
@medusajs/fulfillment-manual Patch
@medusajs/locking-postgres Patch
@medusajs/locking-redis Patch
@medusajs/notification-local Patch
@medusajs/notification-sendgrid Patch
@medusajs/payment-stripe Patch
@medusajs/core-flows Patch
@medusajs/js-sdk Patch
@medusajs/modules-sdk Patch
@medusajs/orchestration Patch
@medusajs/types Patch
@medusajs/utils Patch
@medusajs/workflows-sdk Patch
@medusajs/cli Patch
@medusajs/medusa-oas-cli Patch
@medusajs/oas-github-ci Patch
@medusajs/telemetry Patch
@medusajs/admin-bundler Patch
@medusajs/admin-sdk Patch
@medusajs/admin-shared Patch
@medusajs/admin-vite-plugin Patch
@medusajs/dashboard Patch
@medusajs/icons Patch
@medusajs/toolbox Patch
@medusajs/ui-preset Patch
create-medusa-app Patch
medusa-dev-cli Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@thetutlage thetutlage changed the title feat: begin router refactoring feat: Replace existing router with the new implementation Feb 28, 2025
@thetutlage
Copy link
Contributor Author

/snapshot-this

This comment was marked as outdated.

@thetutlage
Copy link
Contributor Author

/snapshot-this

This comment was marked as outdated.

@thetutlage
Copy link
Contributor Author

/snapshot-this

This comment was marked as outdated.

Copy link
Member

@adrien2p adrien2p left a comment

Choose a reason for hiding this comment

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

LGTM 🎉 few comment that we need to resolve but excellent work 💪

@thetutlage thetutlage force-pushed the feat/implement-revamped-router branch from 5a09626 to 8bd8ca1 Compare March 4, 2025 11:08
@thetutlage
Copy link
Contributor Author

/snapshot-this

@thetutlage
Copy link
Contributor Author

/snapshot-this

Copy link
Contributor

github-actions bot commented Mar 4, 2025

🚀 A snapshot release has been made for this PR

Test the snapshots by updating your package.json with the newly published versions:

yarn add @medusajs/admin-bundler@2.5.2-snapshot-20250304114234
yarn add @medusajs/admin-sdk@2.5.2-snapshot-20250304114234
yarn add @medusajs/admin-shared@2.5.2-snapshot-20250304114234
yarn add @medusajs/admin-vite-plugin@2.5.2-snapshot-20250304114234
yarn add @medusajs/dashboard@2.5.2-snapshot-20250304114234
yarn add create-medusa-app@2.5.2-snapshot-20250304114234
yarn add @medusajs/cli@2.5.2-snapshot-20250304114234
yarn add medusa-dev-cli@2.5.2-snapshot-20250304114234
yarn add @medusajs/medusa-oas-cli@2.5.2-snapshot-20250304114234
yarn add @medusajs/core-flows@2.5.2-snapshot-20250304114234
yarn add @medusajs/framework@2.5.2-snapshot-20250304114234
yarn add @medusajs/js-sdk@2.5.2-snapshot-20250304114234
yarn add @medusajs/modules-sdk@2.5.2-snapshot-20250304114234
yarn add @medusajs/orchestration@2.5.2-snapshot-20250304114234
yarn add @medusajs/types@2.5.2-snapshot-20250304114234
yarn add @medusajs/utils@2.5.2-snapshot-20250304114234
yarn add @medusajs/workflows-sdk@2.5.2-snapshot-20250304114234
yarn add @medusajs/icons@2.5.2-snapshot-20250304114234
yarn add @medusajs/ui-preset@2.5.2-snapshot-20250304114234
yarn add @medusajs/medusa@2.5.2-snapshot-20250304114234
yarn add @medusajs/telemetry@2.5.2-snapshot-20250304114234
yarn add @medusajs/test-utils@2.5.2-snapshot-20250304114234
yarn add @medusajs/api-key@2.5.2-snapshot-20250304114234
yarn add @medusajs/auth@2.5.2-snapshot-20250304114234
yarn add @medusajs/cache-inmemory@2.5.2-snapshot-20250304114234
yarn add @medusajs/cache-redis@2.5.2-snapshot-20250304114234
yarn add @medusajs/cart@2.5.2-snapshot-20250304114234
yarn add @medusajs/currency@2.5.2-snapshot-20250304114234
yarn add @medusajs/customer@2.5.2-snapshot-20250304114234
yarn add @medusajs/event-bus-local@2.5.2-snapshot-20250304114234
yarn add @medusajs/event-bus-redis@2.5.2-snapshot-20250304114234
yarn add @medusajs/file@2.5.2-snapshot-20250304114234
yarn add @medusajs/fulfillment@2.5.2-snapshot-20250304114234
yarn add @medusajs/index@2.5.2-snapshot-20250304114234
yarn add @medusajs/inventory@2.5.2-snapshot-20250304114234
yarn add @medusajs/link-modules@2.5.2-snapshot-20250304114234
yarn add @medusajs/locking@2.5.2-snapshot-20250304114234
yarn add @medusajs/notification@2.5.2-snapshot-20250304114234
yarn add @medusajs/order@2.5.2-snapshot-20250304114234
yarn add @medusajs/payment@2.5.2-snapshot-20250304114234
yarn add @medusajs/pricing@2.5.2-snapshot-20250304114234
yarn add @medusajs/product@2.5.2-snapshot-20250304114234
yarn add @medusajs/promotion@2.5.2-snapshot-20250304114234
yarn add @medusajs/auth-emailpass@2.5.2-snapshot-20250304114234
yarn add @medusajs/auth-github@2.5.2-snapshot-20250304114234
yarn add @medusajs/auth-google@2.5.2-snapshot-20250304114234
yarn add @medusajs/file-local@2.5.2-snapshot-20250304114234
yarn add @medusajs/file-s3@2.5.2-snapshot-20250304114234
yarn add @medusajs/fulfillment-manual@2.5.2-snapshot-20250304114234
yarn add @medusajs/locking-postgres@2.5.2-snapshot-20250304114234
yarn add @medusajs/locking-redis@2.5.2-snapshot-20250304114234
yarn add @medusajs/notification-local@2.5.2-snapshot-20250304114234
yarn add @medusajs/notification-sendgrid@2.5.2-snapshot-20250304114234
yarn add @medusajs/payment-stripe@2.5.2-snapshot-20250304114234
yarn add @medusajs/region@2.5.2-snapshot-20250304114234
yarn add @medusajs/sales-channel@2.5.2-snapshot-20250304114234
yarn add @medusajs/stock-location@2.5.2-snapshot-20250304114234
yarn add @medusajs/store@2.5.2-snapshot-20250304114234
yarn add @medusajs/tax@2.5.2-snapshot-20250304114234
yarn add @medusajs/user@2.5.2-snapshot-20250304114234
yarn add @medusajs/workflow-engine-inmemory@2.5.2-snapshot-20250304114234
yarn add @medusajs/workflow-engine-redis@2.5.2-snapshot-20250304114234

Latest commit: c2e24b6

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants