---
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:

<!-- eslint-disable prefer-rest-params -->

```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:

<!-- eslint-disable prefer-rest-params -->

```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

<DetailsList 
  sections={[
    {
      title: 'AwilixResolutionError: Could Not Resolve X',
      content: <ServiceLifetimeSection />
    },
    {
      title: 'AwilixResolutionError: Could Not Resolve X (Custom Registration)',
      content: <CustomRegistrationSection />
    }
  ]}
/>

---

## See Also

- [Store API reference](https://docs.medusajs.com/api/store)
- [Admin API reference](https://docs.medusajs.com/api/admin)
