How API Endpoints Are Organized Between the v1 and cms Modules in mini-shop-server

The mini-shop-server separates public client APIs and administrative CMS APIs using a custom Redprint routing system that registers endpoints under /v1 and /cms URL prefixes based on module configuration in ALL_RP_API_LIST.

The mini-shop-server repository implements a sophisticated routing architecture that cleanly partitions API endpoints between public client interfaces and back-office management systems. Understanding how endpoints are organized between the v1 and cms modules requires examining the custom abstraction layer built on top of Flask's native blueprint system.

The Redprint Routing Architecture

The foundation of the endpoint organization lies in two core components defined in app/core/redprint.py: the Redprint class and the RedprintAssigner orchestrator.

What Is a Redprint?

A Redprint is a thin wrapper around Flask's native Blueprint class that collects route definitions before registering them with a URL prefix. Each API group (such as user, product, or order) instantiates a Redprint with a specific name and module designation:


# From app/api/v1/user.py

api = Redprint(name='user', module='用户', api_doc=api_doc)

The name parameter determines the second URL segment, while the module context (implied by the file location) determines whether the endpoint serves public or administrative traffic.

Configuration via ALL_RP_API_LIST

The master configuration list ALL_RP_API_LIST in app/config/setting.py (lines 19‑27) enumerates every available API group together with its module assignment:


# Example entries from app/config/setting.py

ALL_RP_API_LIST = [
    'v1-user',
    'cms-user',
    'v1-product', 
    'cms-product'
]

Each string follows the pattern {module_name}-{api_name}, enabling the application to dynamically import the correct Python file and associate it with the proper URL prefix during startup.

Module-Based Route Registration

The RedprintAssigner class handles the actual wiring of routes into the Flask application instance during the bootstrap phase in app/__init__.py.

How RedprintAssigner Works

During the register_blueprint initialization sequence, the assigner iterates through ALL_RP_API_LIST and executes the following workflow:

  1. Splits the configuration string into module_name (e.g., v1 or cms) and api_name (e.g., user)
  2. Dynamically imports the module using import_module (e.g., app.api.v1.user)
  3. Retrieves the Redprint instance (typically named api) defined within that file
  4. Creates a Flask Blueprint for each unique module with the appropriate URL prefix
  5. Registers collected routes from each Redprint onto the module-specific blueprint

The RedprintAssigner.__create_blueprint_list method specifically handles the blueprint instantiation and route mapping logic according to the source code structure.

URL Structure Deep Dive

The final endpoint URL follows a strict hierarchical pattern:


/{module_name}/{redprint_name}{route_rule}

  • First segment: Determined by the module (v1 for public, cms for admin)
  • Second segment: Determined by the Redprint's name attribute
  • Remaining path: Determined by individual route decorators ('', '/list', '/<int:uid>', etc.)

For example, a Redprint named user in the v1 module with a route rule of '' produces the endpoint /v1/user, while the same Redprint name in the cms module with a rule of /list produces /cms/user/list.

Comparing v1 and cms Implementations

The separation between public and administrative endpoints manifests in both URL structure and authorization requirements.

Public API Structure (v1)

Public-facing endpoints reside in app/api/v1/*.py and utilize standard user authentication decorators. The following example from app/api/v1/user.py demonstrates the public profile retrieval endpoint:


# app/api/v1/user.py

api = Redprint(name='user', module='用户', api_doc=api_doc)

@api.route('', methods=['GET'])
@api.doc(auth=True)
@auth.login_required
def get_user():
    """查询自身"""
    user = User.get(id=g.user.id)
    return Success(user)

This configuration produces the endpoint: GET /v1/user

Admin API Structure (cms)

Administrative endpoints reside in app/api/cms/*.py and typically require elevated permissions through group-based authorization. The following example from app/api/cms/user.py demonstrates the user list retrieval endpoint for back-office operations:


# app/api/cms/user.py

api = Redprint(name='user', module='用户管理', api_doc=None, alias='cms_user')

@api.route('/list', methods=['GET'])
@api.route_meta(auth='查询用户列表', module='用户')
@api.doc(args=['g.query.page', 'g.query.size'], auth=True)
@auth.group_required
def get_user_list():
    """查询用户列表(分页)"""
    page, size = paginate()
    rv = UserDao.get_user_list(page, size)
    return Success(rv)

This configuration produces the endpoint: GET /cms/user/list

Summary

  • The Redprint class in app/core/redprint.py wraps Flask blueprints to collect route definitions before registration.
  • ALL_RP_API_LIST in app/config/setting.py drives the dynamic discovery of API modules, distinguishing between v1 and cms prefixes.
  • The RedprintAssigner orchestrates the creation of module-specific blueprints during application startup in app/__init__.py.
  • Public client APIs receive the /v1 prefix, while administrative CMS APIs receive the /cms prefix.
  • Individual route rules append to the Redprint name, creating structured endpoints like /v1/user versus /cms/user/list.

Frequently Asked Questions

What is the difference between a Redprint and a Flask Blueprint?

A Redprint is a custom wrapper class defined in app/core/redprint.py that collects route definitions and metadata before registration, whereas a Flask Blueprint is the native WSGI routing mechanism. The RedprintAssigner converts Redprint instances into standard Flask blueprints during application initialization, applying the appropriate URL prefixes (/v1 or /cms) based on the module configuration in ALL_RP_API_LIST.

How does the system distinguish between public and admin routes?

The system distinguishes routes by the first segment of the configuration string in ALL_RP_API_LIST. Entries prefixed with v1- are imported from app/api/v1/ and registered under the /v1 URL prefix, while entries prefixed with cms- are imported from app/api/cms/ and registered under /cms. Authorization requirements are enforced separately through decorators like @auth.login_required for public APIs and @auth.group_required for admin APIs.

Where are authentication decorators applied in this architecture?

Authentication and authorization decorators are applied directly to view functions within each API module file. In app/api/v1/user.py, the @auth.login_required decorator ensures only authenticated users access public endpoints. In app/api/cms/user.py, the @auth.group_required decorator enforces role-based access control for administrative operations. These decorators operate independently of the Redprint routing mechanism.

Can additional API modules be added beyond v1 and cms?

Yes, the architecture supports additional modules by extending the ALL_RP_API_LIST configuration in app/config/setting.py with new prefix patterns (e.g., v2-product). The RedprintAssigner dynamically imports any module following the app/api/{module_name}/{api_name}.py directory structure and creates the corresponding blueprint with the specified URL prefix. The routing system is fully extensible as long as new modules follow the established file organization pattern.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →