# Purpose of the Gitea Web Package: Core HTTP Routing and Middleware Architecture

> Discover the purpose of the Gitea web package, its core HTTP routing, and middleware architecture. Understand how it handles requests and integrates with Gitea's business logic.

- Repository: [Gitea/gitea](https://github.com/go-gitea/gitea)
- Tags: architecture
- Published: 2026-03-07

---

**The Gitea `web` package functions as the central HTTP routing and request-handling layer, wrapping the chi router to provide middleware orchestration, custom regex-based path groups, handler conversion utilities, and test-friendly mocking hooks that bridge incoming HTTP traffic to Gitea's business logic.**

The `web` package in the `go-gitea/gitea` repository serves as the foundational infrastructure that transforms raw HTTP requests into structured, context-rich interactions with the Git service. Located primarily in `modules/web/`, this package abstracts the standard Go HTTP stack by handling URL normalization, route matching, and middleware injection before requests reach Gitea's business logic controllers.

## Core Responsibilities of the Gitea Web Package

The `web` package consolidates several critical responsibilities that would otherwise be scattered across the codebase. According to the Gitea source code, these capabilities work together to create a testable, extensible routing layer.

### Router Abstraction Around Chi

At its core, the package wraps the **chi** router to add Gitea-specific features such as middleware stacking, route groups, and path normalization. In [`modules/web/router.go`](https://github.com/go-gitea/gitea/blob/main/modules/web/router.go), the `Router` type provides familiar methods like `Get()`, `Post()`, `Any()`, and `Group()` that forward to chi's underlying implementations after applying Gitea middleware patterns. The `NewRouter()` function creates isolated router instances, while `Routes()` returns the global router used for mounting sub-routers throughout the application.

### Custom Path Groups for Complex Routing

Standard chi routing cannot express certain URL patterns required by Gitea, such as repository names with special characters. The [`modules/web/router_path.go`](https://github.com/go-gitea/gitea/blob/main/modules/web/router_path.go) file implements **path groups** via the `PathGroup()` method, which supports regex-based placeholders like `<name>`. The internal `patternRegexp` parser processes these custom syntaxes, enabling routes such as `/repo/<owner>/<name>` where segments match complex validation rules before hitting handlers.

### Handler Conversion and Context Injection

The [`modules/web/handler.go`](https://github.com/go-gitea/gitea/blob/main/modules/web/handler.go) file converts ordinary Go functions into "handler providers" compatible with Gitea's middleware expectations. This conversion injects a `ResponseStatusProvider` interface that allows the framework to detect whether a handler has already written a response, preventing duplicate writes. The package also exposes `SetForm()` and `GetForm()` utilities in [`modules/web/router.go`](https://github.com/go-gitea/gitea/blob/main/modules/web/router.go) that bind incoming request data to structs and store them in the request context for downstream handlers.

### Test Mocking and Global Route Registration

To support unit testing without modifying production code, [`modules/web/routemock.go`](https://github.com/go-gitea/gitea/blob/main/modules/web/routemock.go) exposes `RouterMockPoint` hooks that tests can replace or extend. Meanwhile, [`routers/web/web.go`](https://github.com/go-gitea/gitea/blob/main/routers/web/web.go) serves as the top-level registry, assembling the complete web-router tree (static assets, API, UI, auth, admin) and wiring it with Gitea-wide middlewares including gzip, CORS, authentication, and locale handling.

## Practical Code Examples

The following examples demonstrate how to interact with the Gitea `web` package for common routing scenarios.

### Registering a Simple Route

Use `web.NewRouter()` to create a router instance and `web.Routes()` to access the global registry for mounting:

```go
package myplugin

import (
	"net/http"

	"code.gitea.io/gitea/modules/web"
)

func MyHandler(resp http.ResponseWriter, req *http.Request) {
	_, _ = resp.Write([]byte("hello from my plugin"))
}

func Register() {
	r := web.NewRouter()
	r.Get("/myplugin/hello", MyHandler)
	web.Routes().Mount("", r)
}

```

*Source reference*: The `Get` method is defined in [`modules/web/router.go`](https://github.com/go-gitea/gitea/blob/main/modules/web/router.go) and forwards to chi's `Method("GET", …)` after applying middleware.

### Implementing Regex-Based Path Groups

For routes requiring custom parameter validation, use `PathGroup()` with regex capture groups:

```go
func RegisterCustomGroup() {
	r := web.NewRouter()
	r.Group("/repo", func() {
		r.PathGroup("/<owner>/<name>", func(g *web.RouterPathGroup) {
			g.MatchPath("GET", "/info", repoInfoHandler)
		})
	}, nil)
	web.Routes().Mount("", r)
}

```

*Source reference*: The `PathGroup` helper is implemented in [`modules/web/router_path.go`](https://github.com/go-gitea/gitea/blob/main/modules/web/router_path.go); the `<name>` pattern syntax is parsed by `patternRegexp`.

### Creating Custom Middleware with Form Binding

Middleware can inject parsed form data into the request context using `SetForm()`:

```go
func BindFormMiddleware(next http.Handler) http.Handler {
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		var payload MyForm
		if err := json.NewDecoder(r.Body).Decode(&payload); err == nil {
			web.SetForm(reqctx.GetData(r.Context()), &payload)
		}
		next.ServeHTTP(w, r)
	})
}

// Register with the router:
router.Use(BindFormMiddleware)

```

*Source reference*: `SetForm` and context management utilities live in [`modules/web/router.go`](https://github.com/go-gitea/gitea/blob/main/modules/web/router.go) and are consumed by the core `web.Bind` helper.

## Key Source Files and Architecture

Understanding the file structure within the Gitea `web` package clarifies how requests flow from the HTTP server to business logic:

- **[`modules/web/router.go`](https://github.com/go-gitea/gitea/blob/main/modules/web/router.go)** – Defines the main `Router` type, route registration helpers (`Get`, `Post`, `Any`, `Group`), and context utilities (`SetForm`, `GetForm`).
- **[`modules/web/handler.go`](https://github.com/go-gitea/gitea/blob/main/modules/web/handler.go)** – Converts ordinary functions to handler providers and manages the `ResponseStatusProvider` interface for response tracking.
- **[`modules/web/router_path.go`](https://github.com/go-gitea/gitea/blob/main/modules/web/router_path.go)** – Implements the regex-based `PathGroup` functionality for advanced URL matching.
- **[`modules/web/routemock.go`](https://github.com/go-gitea/gitea/blob/main/modules/web/routemock.go)** – Exposes `RouterMockPoint` and related structures for test-time middleware manipulation.
- **[`routers/web/web.go`](https://github.com/go-gitea/gitea/blob/main/routers/web/web.go)** – Assembles the complete Gitea web router, attaches global middlewares, and mounts all feature-specific sub-routers.
- **`modules/web/middleware/*`** – Contains various middleware implementations (locale, flash messages, data binding, cookies) that the router orchestrates.

## Summary

The Gitea `web` package serves as the critical bridge between raw HTTP requests and the application's domain logic:

- **Wraps the chi router** in [`modules/web/router.go`](https://github.com/go-gitea/gitea/blob/main/modules/web/router.go) to add middleware stacking and Gitea-specific route handling.
- **Supports complex URL patterns** via `PathGroup()` and regex parsing in [`modules/web/router_path.go`](https://github.com/go-gitea/gitea/blob/main/modules/web/router_path.go).
- **Converts handlers** and tracks response status through [`modules/web/handler.go`](https://github.com/go-gitea/gitea/blob/main/modules/web/handler.go) to ensure proper request lifecycle management.
- **Enables testability** through mock points in [`modules/web/routemock.go`](https://github.com/go-gitea/gitea/blob/main/modules/web/routemock.go) without requiring production code changes.
- **Aggregates all routes** in [`routers/web/web.go`](https://github.com/go-gitea/gitea/blob/main/routers/web/web.go) with global middlewares like authentication, gzip, and CORS.

## Frequently Asked Questions

### What underlying router does the Gitea web package use?

The Gitea `web` package wraps the **chi** router, as implemented in [`modules/web/router.go`](https://github.com/go-gitea/gitea/blob/main/modules/web/router.go). It forwards standard HTTP methods to chi after applying Gitea-specific middleware chains and path normalization.

### How does the Gitea web package handle URL patterns that chi cannot express?

Through the `PathGroup()` method in [`modules/web/router_path.go`](https://github.com/go-gitea/gitea/blob/main/modules/web/router_path.go), the package supports custom regex-based placeholders such as `<name>`. The internal `patternRegexp` parser processes these patterns, enabling complex routing rules for repository names and other variable segments.

### Can developers use the Gitea web package for custom plugins or extensions?

Yes. Developers can call `web.NewRouter()` to create isolated router instances, register handlers using methods like `Get()` or `Post()`, and mount them into the global router via `web.Routes().Mount()`. This pattern allows plugins to integrate with Gitea's HTTP layer while leveraging its middleware infrastructure.

### Where does Gitea register all its application routes?

The main route registration occurs in [`routers/web/web.go`](https://github.com/go-gitea/gitea/blob/main/routers/web/web.go), which imports the `modules/web` package to build the complete router tree. This file wires together static asset serving, API endpoints, UI routes, and administrative interfaces while attaching global middlewares such as session handling, locale detection, and CSRF protection.