# How CasaOS Multiplexes API Versions Using HandlerMultiplexer

> Discover how CasaOS multiplexes API versions using HandlerMultiplexer. Learn how requests are routed to specific Echo routers based on URL path segments for efficient API management.

- Repository: [IceWhale/CasaOS](https://github.com/IceWhaleTech/CasaOS)
- Tags: internals
- Published: 2026-06-26

---

**CasaOS routes requests for multiple API versions (v1, v2, v3) and documentation through a single HTTP server by using the `util_http.HandlerMultiplexer` type from the CasaOS-Common library, which inspects the first URL path segment and dispatches to version-specific Echo routers.**

CasaOS serves its REST API across three major versions from one HTTP server without URL conflicts. The system achieves this through a centralized multiplexing pattern implemented in the shared CasaOS-Common repository. By using the `HandlerMultiplexer` type, CasaOS cleanly separates version-specific routing logic while maintaining a concise server configuration in [`main.go`](https://github.com/IceWhaleTech/CasaOS/blob/main/main.go).

## HandlerMultiplexer Architecture

The multiplexing strategy centers on a map that associates URL prefixes with concrete `http.Handler` implementations. In [`main.go`](https://github.com/IceWhaleTech/CasaOS/blob/main/main.go), the server initializes separate Echo routers for each API version and registers them under distinct keys.

### Building the Handler Map

The server constructs the multiplexer by mapping path prefixes to their respective routers:

```go
// main.go – HTTP server setup
v1Router := route.InitV1Router()
v2Router := route.InitV2Router()
v2DocRouter := route.InitV2DocRouter(_docHTML, _docYAML)
v3File := route.InitFile()

mux := &util_http.HandlerMultiplexer{
    HandlerMap: map[string]http.Handler{
        "v1":  v1Router,    // Handles /v1/... routes
        "v2":  v2Router,    // Handles /v2/... routes
        "v3":  v3File,      // Handles /v3/... routes (file API)
        "doc": v2DocRouter, // Handles /doc/... routes (OpenAPI UI)
    },
}

s := &http.Server{
    Handler:           mux,
    ReadHeaderTimeout: 5 * time.Second,
}

```

This configuration makes the `HandlerMultiplexer` the sole entry point for all incoming HTTP requests.

## Request Dispatch and Path Rewriting

The `HandlerMultiplexer` processes each request by extracting the first path segment to determine the target version. According to the CasaOS-Common source code, the implementation resides in [`util_http/handler_multiplexer.go`](https://github.com/IceWhaleTech/CasaOS/blob/main/util_http/handler_multiplexer.go).

### Core ServeHTTP Logic

When a request arrives, the multiplexer performs three operations:

- **Extracts the prefix** by splitting the URL path
- **Looks up the handler** in the configured map
- **Rewrites the path** to remove the version prefix before forwarding

```go
func (h *HandlerMultiplexer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    // Split "/v1/..." → ["v1", "…"]
    parts := strings.SplitN(strings.TrimPrefix(r.URL.Path, "/"), "/", 2)
    if len(parts) == 0 {
        http.NotFound(w, r)
        return
    }
    prefix := parts[0]

    // Find the appropriate handler
    handler, ok := h.HandlerMap[prefix]
    if !ok {
        http.NotFound(w, r)
        return
    }

    // Rewrite path for downstream router
    if len(parts) > 1 {
        r.URL.Path = "/" + parts[1]
    } else {
        r.URL.Path = "/"
    }
    handler.ServeHTTP(w, r)
}

```

This path stripping ensures that version-specific Echo routers receive URLs without the version prefix, allowing routes to be defined cleanly (e.g., `/sys/info` rather than `/v1/sys/info`).

## Version-Specific Route Configuration

Each API version maintains its own routing logic in dedicated packages. The **v1** routes live in `route/v1/*`, while **v2** routes reside in `route/v2/*`. The documentation endpoint uses [`route/v2/doc.go`](https://github.com/IceWhaleTech/CasaOS/blob/main/route/v2/doc.go).

Because the `HandlerMultiplexer` removes the version prefix before dispatch, the Echo routers define their routes relative to the root:

- `GET /v1/sys/info` → v1 router handles `/sys/info`
- `GET /v2/port/list` → v2 router handles `/port/list`
- `GET /doc/openapi.yaml` → doc router handles [`/openapi.yaml`](https://github.com/IceWhaleTech/CasaOS/blob/main//openapi.yaml)

## Practical API Request Examples

The following `curl` commands demonstrate how the multiplexer routes requests to different handlers.

**Accessing the v1 system API:**

```bash
curl http://localhost:80/v1/sys/info

```

The multiplexer extracts `"v1"`, strips the prefix, and forwards the request to `v1Router` with the path `/sys/info`.

**Accessing the v2 port management API:**

```bash
curl http://localhost:80/v2/port/list

```

This routes to `v2Router`, which processes the request as `/port/list`.

**Accessing the OpenAPI documentation:**

```bash
curl http://localhost:80/doc/openapi.yaml

```

The request dispatches to `v2DocRouter`, serving the OpenAPI specification.

## Summary

- The `util_http.HandlerMultiplexer` from CasaOS-Common enables CasaOS to serve multiple API versions from a single HTTP server.
- Configuration occurs in [`main.go`](https://github.com/IceWhaleTech/CasaOS/blob/main/main.go), where version-specific Echo routers register under keys like `"v1"`, `"v2"`, and `"doc"`.
- The multiplexer extracts the first URL path segment, looks up the corresponding handler, and strips the prefix before forwarding.
- Each version maintains isolated route definitions in `route/v1/*` and `route/v2/*`, receiving paths without version prefixes.
- Unmatched prefixes return **404 Not Found** immediately.

## Frequently Asked Questions

### What is the HandlerMultiplexer in CasaOS?

The `HandlerMultiplexer` is a Go type defined in the CasaOS-Common library at [`util_http/handler_multiplexer.go`](https://github.com/IceWhaleTech/CasaOS/blob/main/util_http/handler_multiplexer.go). It implements the `http.Handler` interface to route incoming requests to different sub-handlers based on the first path segment, enabling a single server to host multiple API versions.

### How does CasaOS handle API versioning?

CasaOS handles API versioning through URL path prefixes (e.g., `/v1/`, `/v2/`) processed by the `HandlerMultiplexer`. Each version has its own Echo router initialized in [`main.go`](https://github.com/IceWhaleTech/CasaOS/blob/main/main.go), and the multiplexer dispatches requests to the appropriate router while stripping the version prefix so that routes can be defined independently of the version string.

### Where is the HandlerMultiplexer defined?

The `HandlerMultiplexer` struct and its `ServeHTTP` method are defined in the CasaOS-Common repository within the file [`util_http/handler_multiplexer.go`](https://github.com/IceWhaleTech/CasaOS/blob/main/util_http/handler_multiplexer.go). CasaOS imports this shared library to handle request multiplexing in its main application.

### Why does CasaOS strip the version prefix from the URL?

CasaOS strips the version prefix to keep route definitions clean and maintainable. By removing `/v1` or `/v2` before dispatch, the Echo routers can define routes like `/sys/info` instead of `/v1/sys/info`, preventing tight coupling between the version identifier and the business logic of each API endpoint.