comparison README.md @ 1:3e7247db5c6e

show index.html
author Atarwn Gard <a@qwa.su>
date Mon, 09 Mar 2026 01:04:16 +0500
parents
children
comparison
equal deleted inserted replaced
0:48bdab3eec8a 1:3e7247db5c6e
1 # d2o
2
3 Минималистичный веб-сервер на Go с конфигурацией в формате ICF.
4
5 ## Структура проекта
6
7 ```
8 d2o/
9 go.mod
10 cmd/d2o/
11 main.go — точка входа, HTTP-обработчик, сборка листеров
12 icf/
13 icf.go — парсер формата ICF (переиспользуемая библиотека)
14 fcgi/
15 fcgi.go — минимальный FastCGI-клиент
16 ```
17
18 ## Сборка и запуск
19
20 ```sh
21 go build -o d2o ./cmd/d2o/
22 ./d2o # читает /etc/d2obase
23 ./d2o /path/to/config # альтернативный путь
24 ```
25
26 ---
27
28 ## Формат конфигурации ICF
29
30 **ICF (Inherited Configuration Format)** — текстовый формат правил вида «паттерн → директивы».
31 Вдохновлён синтаксисом bash и базами данных CoreDNS.
32
33 ### Основные правила синтаксиса
34
35 ```
36 ; Это комментарий
37
38 ; Переменная (без пробелов вокруг =)
39 KEY=value
40
41 ; Абстрактный блок (миксин)
42 @name
43 |> directive arg1 arg2
44
45 ; Конкретный блок с наследованием миксина
46 block.id @mixin
47 |> directive arg1 arg2
48
49 ; Блок с именованным capture-группой
50 <sub>.example.com
51 |> root /srv/$sub
52 ```
53
54 ### Переменные
55
56 Объявляются как `KEY=value` на уровне файла. Подставляются через `$KEY` в аргументах директив.
57
58 ```
59 WWW=/srv/www
60 CERT=/etc/acme/example.com
61
62 example.com
63 |> root $WWW/root
64 |> tls $CERT.{crt,key}
65 ```
66
67 ### Brace expansion
68
69 Аргумент `prefix.{a,b,c}` раскрывается в три отдельных аргумента: `prefix.a`, `prefix.b`, `prefix.c`.
70 Порядок важен — используется для `tls`, где первый аргумент сертификат, второй ключ.
71
72 ```
73 |> tls /etc/acme/example.com.{crt,key}
74 ; эквивалентно:
75 |> tls /etc/acme/example.com.crt /etc/acme/example.com.key
76 ```
77
78 ### Capture-группы
79
80 В идентификаторе блока `<name>` захватывает любую подстроку до следующего литерала.
81 `<_>` — анонимный wildcard, ничего не сохраняет.
82
83 ```
84 <sub>.example.com
85 |> root /srv/$sub ; $sub подставляется из захваченного значения
86
87 <_>.static.example.com
88 |> root /srv/static ; совпадает с чем угодно, capture не нужен
89 ```
90
91 Capture жадный слева: `<sub>.example.com` на запрос `a.b.example.com` даст `sub=a.b`.
92
93 ### Кавычки в аргументах
94
95 Аргументы с пробелами берутся в двойные кавычки:
96
97 ```
98 |> fcgi unix:/run/php-fpm.sock "*.php"
99 ```
100
101 ### Абстрактные блоки и наследование
102
103 `@name` задаёт набор директив без привязки к паттерну.
104 Конкретный блок наследует их через `block.id @name` — директивы миксина идут первыми, директивы блока их перекрывают.
105
106 ```
107 @base
108 |> port 80
109 |> port+tls 443
110
111 example.com @base
112 |> root /srv/www ; наследует port 80 и port+tls 443
113
114 other.com @base
115 |> root /srv/other ; то же самое
116 ```
117
118 ### Матчинг блоков
119
120 - Домен матчится точно (с учётом capture-групп).
121 - Путь матчится как префикс: блок `example.com/api` сработает на `/api/users`.
122 - При нескольких совпадениях выигрывает наиболее специфичный (больше совпавших литеральных символов).
123 - Сначала проверяется `host/path`, потом `host`.
124
125 ```
126 example.com
127 |> root /srv/www
128
129 example.com/api
130 |> rprx 127.0.0.1:8080 ; перекрывает блок выше для /api/*
131 ```
132
133 ---
134
135 ## Конфигурация d2o
136
137 Файл по умолчанию: `/etc/d2obase`
138
139 ### @d2o — настройки сервера
140
141 ```
142 @d2o
143 |> threads 512 ; GOMAXPROCS
144 ```
145
146 | Директива | Аргументы | Описание |
147 |------------|-----------|----------|
148 | `threads` | N | Количество потоков ОС (GOMAXPROCS) |
149
150 ### port — HTTP-листенер
151
152 ```
153 |> port 80
154 ```
155
156 | # | Тип | Описание |
157 |---|-------|--------------|
158 | 1 | `int` | Номер порта |
159
160 ### port+tls — HTTPS-листенер
161
162 ```
163 |> port+tls 443
164 ; сертификат берётся из директивы tls того же блока
165 ```
166
167 Знак `+` в имени директивы — обычный символ, не оператор.
168
169 | # | Тип | Описание |
170 |---|--------|-----------------------------------------------|
171 | 1 | `int` | Номер порта |
172 | 2 | `path` | Путь к сертификату (необязателен, если есть `tls`) |
173 | 3 | `path` | Путь к ключу (необязателен, если есть `tls`) |
174
175 ### tls — пути к сертификату и ключу
176
177 ```
178 |> tls /etc/acme/example.com.{crt,key}
179 ```
180
181 Используется как источник сертификата для `port+tls` в том же блоке, если пути не указаны явно.
182
183 | # | Тип | Описание |
184 |---|--------|-------------------|
185 | 1 | `path` | Путь к сертификату |
186 | 2 | `path` | Путь к ключу |
187
188 ### root — отдача статики
189
190 ```
191 |> root /srv/www/example.com
192 |> root /srv/www/example.com hide ; листинг запрещён (по умолчанию)
193 |> root /srv/www/example.com show ; листинг разрешён, index-файл index.html
194 |> root /srv/www/example.com show index.php index.html ; свои index-файлы
195 ```
196
197 | # | Тип | Описание |
198 |---|--------|---------------------------------|
199 | 1 | `path` | Корневая директория |
200 | 2 | `show\|hide` | Режим директорий (по умолчанию `hide`) |
201 | 3–14 | `filename` | Index-файлы (только с `show`), проверяются по порядку |
202
203 При `show`: сначала ищутся index-файлы по списку, если ни один не найден — отдаётся листинг директории.
204 При `hide` или без аргумента: запрос к директории возвращает 403.
205
206 ### fcgi — FastCGI
207
208 ```
209 |> fcgi unix:/run/php-fpm.sock
210 |> fcgi unix:/run/php-fpm.sock "*.php" ; только .php файлы
211 |> fcgi 127.0.0.1:9000 "*.php"
212 ```
213
214 | # | Тип | Описание |
215 |---|---------|----------------------------------------------------|
216 | 1 | `addr` | Адрес сокета: `unix:/path` или `host:port` |
217 | 2 | `glob` | Паттерн файлов (по умолчанию `*`, все запросы) |
218
219 Если glob не совпадает, запрос падает в `root` (если задан).
220
221 ### rprx — обратный прокси
222
223 ```
224 |> rprx 127.0.0.1:3000
225 |> rprx http://127.0.0.1:3000
226 ```
227
228 | # | Тип | Описание |
229 |---|-------|---------------------------------|
230 | 1 | `url` | Адрес backend (схема необязательна, по умолчанию `http://`) |
231
232 ### Приоритет директив
233
234 При одновременном наличии нескольких директив порядок обработки: **rprx > fcgi > root**.
235
236 ---
237
238 ## Пример полного конфига
239
240 ```
241 ; /etc/d2obase
242
243 ACME=/etc/acme/qwaderton.org
244 WWW=/srv/www/qwaderton.org
245
246 @d2o
247 |> threads 512
248
249 @ports
250 |> tls $ACME.{crt,key}
251 |> port 80
252 |> port+tls 443
253
254 qwaderton.org @ports
255 |> root $WWW/root show index.php index.html
256
257 qwaderton.org/webfeather @ports
258 |> root $WWW/root/webfeather
259 |> fcgi unix:/run/php-fpm.sock *.php
260
261 <sub>.qwaderton.org @ports
262 |> root $WWW/$sub
263 ```
264
265 ---
266
267 ## Известные ограничения
268
269 - **Один миксин на блок.** Множественное наследование не поддерживается.
270 - **Brace expansion без вложенности.** `{a,{b,c}}` не работает.
271 - **FastCGI — один запрос на соединение.** Keep-alive с FPM не реализован.
272 - **Нет HTTP→HTTPS редиректа** из коробки — нужно реализовывать отдельным блоком на порту 80.
273 - **Нет hot reload** конфига — требуется перезапуск процесса.