eggjs implementation server request tutorial document-2

Posted by nofxsapunk on Thu, 17 Feb 2022 18:29:45 +0100

Continue with the previous article. If you want to review the content of the previous article, please click here eggjs implementation server request tutorial document-1

3, User details interface development (post request)

egg

With the example of get request, the post implementation is the same.

/app/router/detail.js

'use strict';

module.exports = app => {
  const { router, controller } = app;
  router.post('/api/getUserDetail', controller.home.userDetailController);
};

/app/controller/home.js

...
class HomeController extends Controller {
  async userListController() { ... }

  async userDetailController() {
    const { ctx } = this;
    ctx.body = {
      data: 'userDetail query success',
      success: true,
    };
  }
}
...

Because the post request cannot realize the interface call through the url, our primary purpose is to successfully call the interface:

web

# The terminal executes and creates a page using the command line
alita g pages userDetail

/src/pages/userDetail/service.ts

import { request } from 'alita';

export async function queryUserDetail(params: any): Promise<any> {
  return request('/api/getUserDetail', { method: 'post', data: params });
}

/src/pages/userDetail/index.tsx

import React, { FC } from 'react';
import { useRequest } from 'alita';
import { queryUserDetail } from './service';
import styles from './index.less';

interface UserDetailPageProps {
  location: any;
}

const UserDetailPage: FC<UserDetailPageProps> = ({ location }) => {
  const { id } = location.query;
  const { data } = useRequest(() => queryUserDetail({ id }));
  return <div className={styles.center}>{data}</div>;
};

export default UserDetailPage;

Click any item on the list page to jump to the user details page. url is http://localhost:8000/#/userDetail?id=1

But the request did not seem to be as successful as expected.

Interface 403, error message {"message":"invalid csrf token"}.

Baidu learned that the framework has a built-in security system, which is enabled by default to prevent XSS attacks and CSRF attacks. reference resources Egg post failed {message: 'invalid csrf token'} solution The following solutions can be obtained

egg

/config/config.default.js :

config.security = {
  csrf: {
    headerName: 'x-csrf-token', // Custom request header
  },
};

web

Add x-csrf-token to the request header:

/src/utils/index.ts

// Encapsulating the method of obtaining cookie s
export const getCookie = (name: any) => {
  var arr,
    reg = new RegExp('(^| )' + name + '=([^;]*)(;|$)');
  if ((arr = document.cookie.match(reg))) return unescape(arr[2]);
  else return '';
};

/src/app.ts

Add header s to the request interface through middleware

const middleware = async (ctx: Context, next: any) => {
  // You can write some things to do before the request to operate CTX req
  ctx.req.options = {
    ...ctx.req.options,
    headers: {
      'x-csrf-token': getCookie('csrfToken'), // If the front and back ends are not separated, and each time the client is opened, egg will directly write the Key in the client's Cookie. The Key of the Key is the field 'scrfToken', so it's good to get it directly
    },
  };
  await next();
  // Here you can do some operations on the response data CTX res
};

egg

Finally, we get the input parameters requested by the interface in the controller and re encapsulate the data of the parameters.

/app/controller/home.js

async userDetailController() {
    const { ctx } = this;
    const { id } = ctx.request.body;
    console.log(ctx.request.body);
    ctx.body = {
      data: {
        id,
        name: `name${id}`,
      },
      success: true,
    };
}

When there is a call to the interface, the terminal will display CTX request. Body data.

Feat user detail branch

4, egg Middleware

After writing the middleware, all requests will pass through the middleware. It can be operated and processed in the middleware.

You can refer to the official website Writing Middleware Examples.

Here we will implement a requirement to add the parameter of requestHeader in the request header. On the interface side, verify the correctness of the requestHeader in the middleware. If correct, the process continues. If not, the interface cannot be requested.

egg

Create a new / Middleware folder under / app. This is also a convention for storing middleware.

/app/middleware/request.js

Don't worry about realizing the function. First try whether the middleware is successful.

It can be seen from the following code that if the middleware is successfully implemented, whenever there is an interface request, the terminal will display the parameters of options(config.default.js) and the input parameters of the request.

'use strict';
module.exports = options => {
  return async function requestMiddleware(ctx, next) {
    console.log(options.requestHeader, ctx.request.body);
    await next();
  };
};

/config.config.default.js

module.exports = appInfo => {
    ...//Part of the code is omitted here

    config.middleware = ['request']; // Add ` request JS ` file added to middleware

    // To ` request JS ` add configuration parameters
    exports.request = {
        requestHeader: 'hang',
    };

    return {
        ...config,
        ...userConfig,
    };
};

visit http://localhost:8000/#/userDetail?id=2

Then the middleware configuration is successful. Start writing function code

/app/middleware/request.js

module.exports = options => {
  return async function requestMiddleware(ctx, next) {
    const { requestHeader } = ctx.request.header;
    if (ctx.request.header.requestheader === options.requestHeader) {
      await next();
    } else {
      ctx.status = 403;
      ctx.body = {
        data: 'access was denied',
        success: false,
      };
    }
  };
};

web

If the interface request fails, it will be displayed and processed uniformly in the web middleware.

/config/config.ts

export const request = {
  prefix: '', // Unified request header
  middlewares: [middleware],
  errorHandler: (error: ResponseError) => {
    if (error.response.status === 403) {
      Toast.fail('access was denied');
    }
  },
};

/config/config.ts

const middleware = async (ctx: Context, next: any) => {
  // You can write some things to do before the request to operate CTX req
  ctx.req.options = {
    ...ctx.req.options,
    headers: {
      'x-csrf-token': getCookie('csrfToken'), // If the front and back ends are not separated, and each time the client is opened, egg will directly write the Key in the client's Cookie. The Key of the Key is the field 'scrfToken', so it's good to get it directly
      requestHeader: 'hang',
    },
  };
  await next();
};

After the web interface requests to add a header requestHeader uniformly, the interface requests again normally.

Feat middleware branch

Topics: node.js eggjs