--- addHowToData: true --- import DetailsList from '@site/src/components/DetailsList' import ServiceLifetimeSection from '../../troubleshooting/awilix-resolution-error/_service-lifetime.md' import CustomRegistrationSection from '../../troubleshooting/awilix-resolution-error/_custom-registration.md' # Middlewares In this document, you’ll learn how to add a middleware to existing or custom API Routes in Medusa. :::tip v1.17.2 of `@medusajs/medusa` introduced a new approach to creating middlewares using a single `middlewares.ts` file. You can still use the [Express Router Approach](./add-middleware-express-route.mdx), however, it's highly recommended that you start using this new approach. ::: ## Basic Implementation ```ts title=src/api/middlewares.ts import type { MiddlewaresConfig } from "@medusajs/medusa" import type { MedusaNextFunction, MedusaRequest, MedusaResponse, } from "@medusajs/medusa" const storeMiddleware = ( req: MedusaRequest, res: MedusaResponse, next: MedusaNextFunction ) => { // do something next() } export const config: MiddlewaresConfig = { routes: [ { matcher: "/store/*", middlewares: [storeMiddleware], }, ], } ``` A middleware is a function that has access to the `MedusaRequest` and `MedusaResponse` objects that are passed to API Route method handlers. Middlewares are used to perform an action when a request is sent to an API Route, or modify the response of an API route, among other usages. ### middlewares.ts File Middlewares are defined in the `src/api/middlewares.ts` file. This file must expose a config object of type `MiddlewaresConfig` imported from `@medusajs/medusa`. This object accepts a parameter `routes`, whose value is an array of middleware route objects. Each middleware route object accepts the following properties: - The `matcher` property accepts a string or a regular expression that will be used to check whether the middlewares should be applied on a API Routes. - The `middlewares` property is an array of middlewares that should be applied on API Routes matching the pattern specified in `matcher`. --- ## Build Files Similar to custom API Routes, you must transpile the files under `src` into the `dist` directory for the backend to load them. To do that, run the following command before running the Medusa backend: ```bash npm2yarn npm run build ``` You can then test that the middleware is working by running the backend. --- ## Register New Resources in Dependency Container In some cases, you may need to register a resource to use within your commerce application. For example, you may want to register the logged-in user to access it in other resources, such as services. You can do that in your middleware. :::tip If you want to register a logged-in user and access it in your resources, you can check out [this example guide](./example-logged-in-user.mdx). ::: To register a new resource in the dependency container, use the `MedusaRequest` object's `scope.register` method. It accepts an object, where each key is the name to be registered in the dependency container, and its value is an object that has a `resolve` property. The `resolve`'s value is a function that returns the resource to be registered in the dependency container. For example: ```ts title=src/api/middlewares.ts import type { MiddlewaresConfig } from "@medusajs/medusa" import type { MedusaNextFunction, MedusaRequest, MedusaResponse, } from "@medusajs/medusa" const customResource = ( req: MedusaRequest, res: MedusaResponse, next: MedusaNextFunction) => { req.scope.register({ customResource: { resolve: () => "my custom resource", }, }) next() } export const config: MiddlewaresConfig = { routes: [ { matcher: "/store/*", middlewares: [customResource], }, ], } ``` You can then load this new resource within other resources. For example, to load it in a service: ```ts title=src/services/custom-service.ts import { TransactionBaseService } from "@medusajs/medusa" class CustomService extends TransactionBaseService { constructor(container, options) { super(...arguments) // use the registered resource. try { container.customResource } catch (e) { // avoid errors when the backend first loads } } } export default CustomService ``` :::note Make sure to wrap your usage of the new resource in a try-catch block when you use it in a constructor. This is to avoid errors that can arise when the backend first loads, as the resource isn't registered yet. ::: ### Note About Services Lifetime If you want to access new registrations in the dependency container within a service, you must set the lifetime of the service either to `Lifetime.SCOPED` or `Lifetime.TRANSIENT`. Services that have a `Lifetime.SINGLETON` lifetime can't access new registrations since they're resolved and cached in the root dependency container beforehand. You can learn more in the [Create Services documentation](../services/create-service.mdx#service-life-time). For custom services, no additional action is required as the default lifetime is `Lifetime.SCOPED`. However, if you extend a core service, you must change the lifetime since the default lifetime for core services is `Lifetime.SINGLETON`. For example: ```ts import { Lifetime } from "awilix" import { ProductService as MedusaProductService, } from "@medusajs/medusa" // extending ProductService from the core class ProductService extends MedusaProductService { // The default life time for a core service is SINGLETON static LIFE_TIME = Lifetime.SCOPED constructor(container, options) { super(...arguments) // use the registered resource. try { container.customResource } catch (e) { // avoid errors when the backend first loads } } // ... } export default ProductService ``` --- ## Troubleshooting }, { title: 'AwilixResolutionError: Could Not Resolve X (Custom Registration)', content: } ]} /> --- ## See Also - [Store API reference](https://docs.medusajs.com/api/store) - [Admin API reference](https://docs.medusajs.com/api/admin)