Fast and extensible multi-platform HTTP/1-2-3 web server with automatic HTTPS
Mirrored from https://github.com/Slazee/caddy.git
Synced Nov 11, 12:15 UTC
chore: add `AGENTS.md` (#7652)
* chore: add `AGENTS.md` Signed-off-by: Mohammed Al Sahaf <msaa1990@gmail.com> * Apply suggestions from code review Co-authored-by: Francis Lavoie <lavofr@gmail.com> Co-authored-by: Matt Holt <mholt@users.noreply.github.com> * review feedback Signed-off-by: Mohammed Al Sahaf <msaa1990@gmail.com> --------- Signed-off-by: Mohammed Al Sahaf <msaa1990@gmail.com> Co-authored-by: Francis Lavoie <lavofr@gmail.com> Co-authored-by: Matt Holt <mholt@users.noreply.github.com>
Mohammed Al Sahaf committed
Apr 17, 2026 at 23:49 UTC
bd9f1453219a2610c319192f23782abb01b96699
1 file changed
+217
AGENTS.md
new
+217
@@ -0,0 +1,217 @@
1
+# Caddy Project Guidelines
2
+
3
+## Mission
4
+
5
+**Every site on HTTPS.** Caddy is a security-first, modular, extensible server platform.
6
+
7
+## Code Style
8
+
9
+### Go Idioms
10
+
11
+Follow [Go Code Review Comments](https://go.dev/wiki/CodeReviewComments):
12
+
13
+- **Error flow**: Early return, indent error handling—not else blocks
14
+ ```go
15
+ if err != nil {
16
+ return err
17
+ }
18
+ // normal code
19
+ ```
20
+- **Naming**: initialisms (`URL`, `HTTP`, `ID`—not `Url`, `Http`, `Id`)
21
+- **Receiver names**: 1–2 letters reflecting type (`c` for `Client`, `h` for `Handler`)
22
+- **Error strings**: Lowercase, no trailing punctuation (`"something failed"` not `"Something failed."`)
23
+- **Doc comments**: Full sentences starting with the name being documented
24
+ ```go
25
+ // Handler serves HTTP requests for the file server.
26
+ type Handler struct { ... }
27
+ ```
28
+- **Empty slices**: `var t []string` (nil slice), not `t := []string{}` (non-nil zero-length)
29
+- **Don't panic**: Use error returns for normal error handling
30
+
31
+### Caddy Patterns
32
+
33
+**Module registration**:
34
+```go
35
+func init() {
36
+ caddy.RegisterModule(MyModule{})
37
+}
38
+
39
+func (MyModule) CaddyModule() caddy.ModuleInfo {
40
+ return caddy.ModuleInfo{
41
+ ID: "namespace.category.name",
42
+ New: func() caddy.Module { return new(MyModule) },
43
+ }
44
+}
45
+```
46
+
47
+**Module lifecycle**: `New()` → JSON unmarshal → `Provision()` → `Validate()` → use → `Cleanup()`
48
+
49
+**Interface guards** — compile-time verification that modules implement required interfaces:
50
+```go
51
+var (
52
+ _ caddy.Provisioner = (*MyModule)(nil)
53
+ _ caddy.Validator = (*MyModule)(nil)
54
+ _ caddyfile.Unmarshaler = (*MyModule)(nil)
55
+)
56
+```
57
+
58
+**Structured logging** — use the module-scoped logger from context:
59
+```go
60
+func (m *MyModule) Provision(ctx caddy.Context) error {
61
+ m.logger = ctx.Logger()
62
+ m.logger.Debug("provisioning", zap.String("field", m.Field))
63
+ return nil
64
+}
65
+```
66
+
67
+**Caddyfile support** — implement `UnmarshalCaddyfile(*caddyfile.Dispenser)` using the `Dispenser` API:
68
+```go
69
+// UnmarshalCaddyfile sets up the module from Caddyfile tokens. Syntax:
70
+//
71
+// directive [arg1] [arg2] {
72
+// subdir value
73
+// }
74
+func (m *MyModule) UnmarshalCaddyfile(d *caddyfile.Dispenser) error {
75
+ d.Next() // consume directive name
76
+ for d.NextArg() {
77
+ // handle inline arguments
78
+ }
79
+ for nesting := d.Nesting(); d.NextBlock(nesting); {
80
+ switch d.Val() {
81
+ case "subdir":
82
+ if !d.NextArg() {
83
+ return d.ArgErr()
84
+ }
85
+ m.Field = d.Val()
86
+ default:
87
+ return d.Errf("unrecognized subdirective: %s", d.Val())
88
+ }
89
+ }
90
+ return nil
91
+}
92
+```
93
+
94
+**Admin API**: Implement `caddy.AdminRouter` for custom endpoints.
95
+
96
+**Context**: Use `caddy.Context` for accessing other apps/modules and logging—don't store contexts in structs.
97
+
98
+## Architecture
99
+
100
+Caddy is built around a **module system** where everything is a module registered via `caddy.RegisterModule()`:
101
+
102
+- **Apps** (`caddy.App`): Top-level modules like `http`, `tls`, `pki` that Caddy loads and runs
103
+- **Modules** (`caddy.Module`): Extensible components with namespaced IDs (e.g., `http.handlers.file_server`)
104
+- **Configuration**: Native JSON with adapters (Caddyfile → JSON via `caddyconfig/httpcaddyfile`)
105
+
106
+| Directory | Purpose |
107
+|-----------|---------|
108
+| `modules/` | All standard modules (HTTP, TLS, PKI, etc.) |
109
+| `modules/standard/imports.go` | Standard module registry |
110
+| `caddyconfig/httpcaddyfile/` | Caddyfile → JSON adapter for HTTP |
111
+| `caddytest/` | Test utilities and integration tests |
112
+| `cmd/caddy/` | CLI entry point with module imports |
113
+
114
+### Critical Packages
115
+
116
+`caddyhttp` and `caddytls` require **extra scrutiny** in code review—these are security-critical.
117
+
118
+## Quality Gates
119
+
120
+
121
+**All required before PR is merge-ready:**
122
+
123
+| Gate | Command | Notes |
124
+|------|---------|-------|
125
+| Tests pass | `go test -race -short ./...` | Race detection enabled |
126
+| Lint clean | `golangci-lint run --timeout 10m` | No warnings in changed files |
127
+| Builds | `go build ./...` | Must compile |
128
+| Benchmarks | `go test -bench=. -benchmem` | Required for optimizations |
129
+
130
+CI runs tests on **Linux, macOS, and Windows**—ensure cross-platform compatibility.
131
+
132
+### Build & Test
133
+
134
+```bash
135
+# Build
136
+cd cmd/caddy && go build
137
+
138
+# Tests with race detection (matches CI)
139
+go test -race -short ./...
140
+
141
+# Integration tests
142
+go test ./caddytest/integration/...
143
+
144
+# Lint (matches CI)
145
+golangci-lint run --timeout 10m
146
+```
147
+
148
+## Testing Conventions
149
+
150
+**Table-driven tests** (preferred pattern):
151
+```go
152
+func TestFeature(t *testing.T) {
153
+ for i, tc := range []struct {
154
+ input string
155
+ expected string
156
+ wantErr bool
157
+ }{
158
+ {input: "valid", expected: "result", wantErr: false},
159
+ {input: "invalid", expected: "", wantErr: true},
160
+ } {
161
+ actual, err := Function(tc.input)
162
+ if tc.wantErr && err == nil {
163
+ t.Errorf("Test %d: expected error but got none", i)
164
+ }
165
+ if !tc.wantErr && err != nil {
166
+ t.Errorf("Test %d: unexpected error: %v", i, err)
167
+ }
168
+ if actual != tc.expected {
169
+ t.Errorf("Test %d: expected %q, got %q", i, tc.expected, actual)
170
+ }
171
+ }
172
+}
173
+```
174
+
175
+**Integration tests** use `caddytest.Tester`:
176
+```go
177
+func TestHTTPFeature(t *testing.T) {
178
+ tester := caddytest.NewTester(t)
179
+ tester.InitServer(`
180
+ {
181
+ admin localhost:2999
182
+ http_port 9080
183
+ }
184
+ localhost:9080 {
185
+ respond "hello"
186
+ }`, "caddyfile")
187
+
188
+ tester.AssertGetResponse("http://localhost:9080/", 200, "hello")
189
+}
190
+```
191
+
192
+Use non-standard ports (9080, 9443, 2999) to avoid conflicts with running servers.
193
+
194
+## AI Contribution Policy
195
+
196
+Per [CONTRIBUTING.md](.github/CONTRIBUTING.md), AI-assisted code **MUST** be:
197
+
198
+1. **Disclosed** — Tell reviewers when code was AI-generated or AI-assisted, mentioning which agent/model is used
199
+2. **Fully comprehended** — You must be able to explain every line
200
+3. **Tested** — Automated tests when feasible, thorough manual tests otherwise
201
+4. **Licensed** — Verify AI output doesn't include plagiarized or incompatibly-licensed code
202
+5. **Contributor License Agreement (CLA)** — The CLA must be signed by the human user
203
+
204
+**Do NOT submit code you cannot fully explain.** Contributors are responsible for their submissions.
205
+
206
+## Dependencies
207
+
208
+- **Avoid new dependencies** — Justify any additions; tiny deps can be inlined
209
+- **No exported dependency types** — Caddy must not export types defined by external packages
210
+- Use Go modules; check with `go mod tidy`
211
+
212
+## Further Reading
213
+
214
+- [CONTRIBUTING.md](.github/CONTRIBUTING.md) — Full PR process and expectations
215
+- [Extending Caddy](https://caddyserver.com/docs/extending-caddy) — Module development guide
216
+- [JSON Config](https://caddyserver.com/docs/json/) — Native configuration reference
217
+- [Caddyfile](https://caddyserver.com/docs/caddyfile/concepts) — Caddyfile syntax guide