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

- `routes`: an array of middleware route objects. Each middleware route object accepts the following properties:
  - `matcher`: a string or a regular expression that will be used to check whether the middlewares should be applied on a API Routes.
  - `middlewares`: an array of middlewares that should be applied on API Routes matching the pattern specified in `matcher`.
  - `method`: a string or an array of strings, where each value is the name of an HTTP method. This allows you to apply the middlewares only on the specified HTTP methods in this property. If not specified, the middlewares are applied on all HTTP methods.
  - `bodyParser`: This property can have two types of values:
    - `false`: If this value is used, the default `json` body parser middleware is disabled. This allows you to override the body parser with your own middleware. For example, it's useful when changing the [default parser for webhooks](./create.mdx#parse-request-body-parameters).
    - `object`: You can pass an object with configurations for the default `json` body parser middleware. It accepts the following configurations:
      - `sizeLimit`: A number indicating the maximum body size allowed in bytes. By default, it's `1000` bytes. If a request body is greater than that, an error will be thrown. So, you can set this configuration if you expect the request body size of an API route to be greater than `1000` bytes.
- `errorHandler`: This property can have two types of values:
  - `false`: If this value is used, the default error handler is disabled. Learn more about its behavior [here](./create.mdx#disable-default-error-handler).
  - `function`: A middleware function used to define a new error handler. Learn more [here](./create.mdx#override-error-handler).

---

## 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)
