Backend Development 13 min read

Guide to Building RESTful APIs with ThinkJS

This article explains how to design and implement elegant RESTful APIs using ThinkJS, covering routing conventions, controller generation, custom router configuration, CRUD action mapping, token‑based authentication, permission validation with Logic layers, inheritance for reusable checks, and database operations with chainable queries.

360 Tech Engineering
360 Tech Engineering
360 Tech Engineering
Guide to Building RESTful APIs with ThinkJS

RESTful APIs are a mainstream way to design server endpoints, treating each request as a CRUD operation on a resource identified by a URI and HTTP method. ThinkJS follows a convention‑over‑configuration approach, mapping routes like /user to src/controller/user.js and automatically handling actions such as GET /user , POST /user , PUT /user/:id , and DELETE /user/:id .

To create a RESTful controller, run thinkjs controller user -r which generates src/controller/user.js . Then mark the route as RESTful in src/config/router.js :

module.exports = [
  ['/user/:id?', 'rest']
];

ThinkJS also provides the think-router-rest middleware, allowing you to enable RESTful routing by adding a static _REST property in the controller class.

When planning resources, organize your database tables to reflect them (e.g., user , post , user_post ) and define relationships: one‑to‑one, one‑to‑many, many‑to‑many. Use MySQL DESCRIBE statements to show table structures.

Authentication can be expressed as a token resource: GET /token to check login status, POST /token to create a token (login), and DELETE /token to delete it (logout).

Common request‑handling logic such as CSRF checks and login validation should be placed in a Logic layer. Define a base Logic class with an async __before() method that runs before every controller action, performing CSRF validation and user session checks. Extend this base class in specific Logic modules to inherit the checks.

//src/logic/base.js
module.exports = class extends think.Logic {
  async __before() {
    // CSRF validation
    if (!this.isCli && !this.isGet) {
      const referrer = this.referrer(true);
      if (!/^xxx\.com$/.test(referrer)) {
        return this.fail('请不要在非其它网站中使用该接口!');
      }
    }
    // Login validation
    const userInfo = await this.session('userInfo') || {};
    if (think.isEmpty(userInfo) && !/\/token\.js/.test(this.__filename)) {
      return this.ctx.throw(401, 'UnAuthorized');
    }
  }
};

Inheritance allows deeper permission checks. For example, a project‑level Logic class extends the base Logic to verify project membership, and a project‑user‑post Logic class further checks the user's permission on a specific post.

//src/logic/project/base.js
module.exports = class extends Base {
  async __before() {
    await super.__before();
    const {team_id} = this.get();
    const {id: user_id} = this.userInfo;
    const permission = await this.model('team_user').where({team_id, user_id}).find();
    if (think.isEmpty(permission)) {
      return this.fail('你没有权限操作该团队');
    }
    this.userInfo.role_id = permission.role_id;
  }
};

Database queries in ThinkJS use the think-model library, which supports chainable methods. You can create a reusable query instance in the controller constructor to avoid repeating where conditions:

//src/controller/project/user/post.js
module.exports = class extends think.Controller {
  constructor(ctx) {
    super(ctx);
    const {project_id, user_id} = this.get();
    this.modelInstance = this.model('post').where({project_id, user_id});
  }
  async getAction() {
    const ret = await this.modelInstance.select();
    return this.success(ret);
  }
};

The article also mentions that advanced RESTful implementations may include Hypermedia links and that alternatives like GraphQL exist.

backendDatabasemiddlewareNode.jsauthorizationRESTful APIthinkjs
360 Tech Engineering
Written by

360 Tech Engineering

Official tech channel of 360, building the most professional technology aggregation platform for the brand.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.