# Extend BFF Server

In some applications, developers may want to handle all BFF functions uniformly, such as for authentication, logging, data processing, etc.

Modern.js provides two methods that allow developers to extend the BFF Server freely according to the runtime framework.

## Middleware

Developers can write middleware in the `api/_app.ts` file to extend the BFF Server. Taking Express as the runtime framework, here is an example of how to write a middleware to add permission checks:

```ts title="api/_app.ts"
import { hook } from '@modern-js/runtime/server';
import { Request, Response, NextFunction } from 'express';

export default hook(({ addMiddleware }) => {
  addMiddleware(async (req: Request, res: Response, next: NextFunction) => {
    if (req.url !== '/api/login') {
      const sid = req?.cookies?.sid;
      if (!sid) {
        res.status(400);
        res.json({ code: -1, message: 'need login' });
      } else {
        next();
      }
    } else {
      next();
    }
  });
});
```

Then add a standard BFF function `api/lambda/hello.ts`:

```ts title="api/lambda/hello.ts"
export default async () => {
  return 'Hello Modern.js';
};
```

Next, in the frontend, add the code to access the API in `src/routes/page.tsx`, directly using the integrated method for the call:

```ts title="src/routes/page.tsx"
import { useState, useEffect } from 'react';
import { get as hello } from '@api/hello';

export default () => {
  const [text, setText] = useState('');

  useEffect(() => {
    async function fetchMyApi() {
      const { message } = await hello();
      setText(message);
    }

    fetchMyApi();
  }, []);

  return <p>{text}</p>;
};
```

Now run the `dev` command to start the project, and visit `http://localhost:8080/`. You will find that the request to `/api/hello` is intercepted:

![Network](https://lf3-static.bytednsdoc.com/obj/eden-cn/aphqeh7uhohpquloj/modern-js/docs/network2.png)

Finally, modify the frontend code in `src/routes/page.tsx` to call the login interface before accessing `/api/hello`:

:::note
Here the login interface is not actually implemented; the code is just for demonstration.
:::

```ts
import { useState, useEffect } from 'react';
import { get as hello } from '@api/hello';
import { post as login } from '@api/login';

export default () => {
  const [text, setText] = useState('');

  useEffect(() => {
    async function fetchAfterLogin() {
      const { code } = await login();
      if (code === 0) {
        const { message } = await hello();
        setText(message);
      }
    }
    fetchAfterLogin();
  }, []);

  return <p>{text}</p>;
};
```

Refresh the page to see that the access to `/api/hello` is successful:

![Network](https://lf3-static.bytednsdoc.com/obj/eden-cn/aphqeh7uhohpquloj/modern-js/docs/network3.png)

The above code simulates adding middleware in `api/_app.ts` to implement simple login functionality. Similarly, other functionalities can be implemented in this hook file to extend the BFF Server.

:::info
The way middleware is written may differ depending on the runtime framework. For details, see [Runtime Frameworks](/guides/advanced-features/bff/frameworks).
:::

## Define Server Instance

In addition to middleware, you can also define a BFF Server instance via the `api/app.ts`. Developers need to export an instance that can be recognized by the runtime framework plugin. Here is a simple demonstration of how to define a server instance with Koa and Express.

import { Tabs, Tab as TabItem } from "@theme";

<Tabs>
  <TabItem value="express" label="Express.js" default>

```ts title="api/app.ts"
import express from 'express';

const app = express();
app.use(async (req, res, next) => {
  console.info(`access url: ${req.url}`);
  next();
});

export default app;
```

  </TabItem>
  <TabItem value="koa" label="Koa.js">

```ts title="api/app.ts"
import koa from 'koa';

const app = new Koa();
app.use(async (ctx, next) => {
  console.info(`access url: ${ctx.url}`);
  await next();
});

export default app;
```

  </TabItem>
</Tabs>

In complex BFF logic, defining a server instance allows for easier organization of code logic and directory structure design through a single entry point. In this file, you can perform initialization logic, add global middleware, declare routes, and even extend the original framework.

The routes defined by the BFF functions will be registered after the routes defined in the `app.ts` file. Therefore, you can also intercept the routes defined by the BFF functions here for preprocessing or early responses.

:::note
At this time, if `api/_app.ts` exists in the application, the defined middleware will be executed after the middleware exported by the `api/app.ts` instance. In most cases, middleware can cover most customization needs for BFF functions. Only when the application's server-side logic is more complex do you need to customize the server instance.
:::

:::caution
When `api/app.ts` does not exist in the application, Modern.js will default to adding [koa-body](https://www.npmjs.com/package/koa-body). When `api/app.ts` does exist in the application, if developers wish to use BFF functions with bodies, they will need to **add `koa-body` themselves**.
:::