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

> Discover how mini-shop-server organizes API endpoints between v1 and cms modules using a custom Redprint routing system for distinct client and admin access.

- Repository: [A粒麦子/mini-shop-server](https://github.com/allen7d/mini-shop-server)
- Tags: architecture
- Published: 2026-02-24

---

**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`](https://github.com/allen7d/mini-shop-server/blob/main/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:

```python

# 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`](https://github.com/allen7d/mini-shop-server/blob/main/app/config/setting.py) (lines 19‑27) enumerates every available API group together with its module assignment:

```python

# 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`](https://github.com/allen7d/mini-shop-server/blob/main/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`](https://github.com/allen7d/mini-shop-server/blob/main/app/api/v1/user.py) demonstrates the public profile retrieval endpoint:

```python

# 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`](https://github.com/allen7d/mini-shop-server/blob/main/app/api/cms/user.py) demonstrates the user list retrieval endpoint for back-office operations:

```python

# 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`](https://github.com/allen7d/mini-shop-server/blob/main/app/core/redprint.py) wraps Flask blueprints to collect route definitions before registration.
- **ALL_RP_API_LIST** in [`app/config/setting.py`](https://github.com/allen7d/mini-shop-server/blob/main/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`](https://github.com/allen7d/mini-shop-server/blob/main/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`](https://github.com/allen7d/mini-shop-server/blob/main/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`](https://github.com/allen7d/mini-shop-server/blob/main/app/api/v1/user.py), the `@auth.login_required` decorator ensures only authenticated users access public endpoints. In [`app/api/cms/user.py`](https://github.com/allen7d/mini-shop-server/blob/main/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`](https://github.com/allen7d/mini-shop-server/blob/main/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.