Библиотека golang
Микро сборка для создания управляемого веб сервера на основе net/http.
web — это обёртка над пакетами net, net/http и github.com/webnice/net для создания управляемого
веб сервера. Открытие адресов и сокетов, TLS, прокси-протокол, работа с сокетами службы systemd и корректное
завершение работы выполняются библиотекой github.com/webnice/net; обработка HTTP запросов выполняется
стандартным сервером net/http; в качестве мультиплексора запросов может использоваться любой обработчик,
рекомендуется github.com/go-chi/chi.
- Запуск сервера на
tcp,tcp4,tcp6,unix,unixpacketсокетах, на UNIX сокете файловой системы и на сокетах, открытых службой systemd; - TLS из коробки, протокол HTTP/2 включён по умолчанию для TLS соединений, поддержка h2c (незашифрованный HTTP/2, prior knowledge), настройка лимита потоков;
- Ограничение максимального размера тела запроса с ответом 413 Request Entity Too Large;
- Ограничение списка доменов, на которые отвечает сервер, с фильтрацией по SNI и заголовку Host (статус 434 Requested Host Unavailable);
- Поддержка прокси-протокола версии 1 и 2, реализованного в HAProxy, nginx и других балансировщиках;
- Корректное завершение работы сервера с учётом значения ShutdownTimeout;
- Справочники MIME типов, HTTP методов, заголовков и статусов ответов;
- Справочник ошибок на основе библиотеки
github.com/webnice/dic, сравнение ошибок функциейerrors.Is(); - Покрытие кода тестами 100%.
- Go 1.27 или новее (используются
http.Protocols,http.HTTP2Config,http.MaxHeaderValueCount,errors.AsType).
go get -u github.com/webnice/web/v4
Подключение:
import "github.com/webnice/web/v4"
github.com/webnice/dic
github.com/webnice/net
golang.org/x/net (преобразование доменов в punycode)
github.com/go-chi/chi/v5 (используется в тестах)
github.com/google/uuid (используется в тестах)
github.com/pires/go-proxyproto (косвенная зависимость)
mux := chi.NewMux()
mux.Get("/", func(w http.ResponseWriter, r *http.Request) {
_, _ = w.Write([]byte("привет"))
})
if err := web.New().Handler(mux).ListenAndServe(":8080").Error(); err != nil {
log.Fatalf("запуск веб сервера прерван ошибкой: %s", err)
}
Адрес можно указывать в любом формате, понятном пакету net: :8080, 127.0.0.1:8080,
localhost:http, [::1]:443, а также путь к UNIX сокету.
srv := web.New().Handler(mux)
srv.ListenAndServeWithConfig(&web.Configuration{
Configuration: wnet.Configuration{
Host: "0.0.0.0",
Port: 8080,
Mode: "tcp",
},
ReadTimeout: time.Second * 5,
WriteTimeout: time.Second * 10,
ShutdownTimeout: time.Second * 30,
MaxBodyBytes: 1 << 20, // 1 MB, ответ 413 при превышении
})
Полный список полей конфигурации с описанием находится в документации пакета (https://pkg.go.dev/github.com/webnice/web/v4#Configuration), пример YAML конфигурации приведён в исходном коде файла types_configuration.go.
if err := web.New().Handler(mux).
ListenAndServeTLS(":8443", "/etc/application/certificate.pub", "/etc/application/certificate.key", nil).
Error(); err != nil {
log.Fatalf("запуск веб сервера прерван ошибкой: %s", err)
}
Для TLS соединений протокол HTTP/2 включён по умолчанию, как в net/http. Отключение HTTP/2, поддержка
h2c и ограничение количества потоков настраиваются полями HTTP2Disable, HTTP2UnencryptedEnable и
HTTP2MaxConcurrentStreams конфигурации.
Сервер отвечает только на домены из списка Domain конфигурации. Фильтрация выполняется дважды: на этапе TLS handshake по SNI и по заголовку Host запроса. Домены указываются в человекочитаемом виде, сравнение выполняется в punycode, поддерживаются wildcard-шаблоны:
srv := web.New().Handler(mux)
srv.ListenAndServeWithConfig(&web.Configuration{
Configuration: wnet.Configuration{
Host: "0.0.0.0",
Port: 8443,
TLSPublicKeyPEM: "/etc/application/certificate.pub",
TLSPrivateKeyPEM: "/etc/application/certificate.key",
},
Domain: []string{"example.com", "*.example.org", "домен.рф"},
})
Домен с портом сравнивается с портом, домен без порта - без порта. Для не разрешённых доменов сервер отвечает статусом 434 Requested Host Unavailable и закрывает соединение.
Произвольная конфигурация TLS передаётся полем TLSConfig, требование клиентского сертификата (mTLS) настраивается полями TLSClientAuth и TLSClientCAs. Приоритет источников конфигурации TLS: аргумент функции запуска, затем поле TLSConfig, затем ключи PEM:
srv := web.New().Handler(mux)
srv.ListenAndServeTLSWithConfig(&web.Configuration{
Configuration: wnet.Configuration{Host: "0.0.0.0", Port: 8443},
TLSConfig: &tls.Config{GetCertificate: certBySNI},
}, nil)
srv := web.New().Handler(mux).ListenAndServe(":8080")
// ...в другой горутине, например по сигналу операционной системы:
srv.Stop() // корректное завершение с учётом ShutdownTimeout
srv.Wait() // ожидание завершения работы сервера
listener, err := net.Listen("tcp", ":8080")
if err != nil {
log.Fatalf("открытие адреса прервано ошибкой: %s", err)
}
if err = web.New().Handler(mux).Serve(listener).Error(); err != nil {
log.Fatalf("запуск веб сервера прерван ошибкой: %s", err)
}
Готовые TLS слушатели можно получить из функций NewListenerTLS(), ListenersSystemdTLSWithoutNames(),
ListenersSystemdTLSWithNames() — повторное TLS оборачивание выполняться не будет.
srv := web.New().Handler(mux).ListenAndServe(":8080")
srv.ListenAndServe(":8081")
if errors.Is(srv.Error(), srv.Errors().AlreadyRunning.Bind()) {
log.Printf("сервер уже запущен")
}
srv.Clean() // очистка последней ошибки
Ошибки библиотеки github.com/webnice/net приводятся к справочнику ошибок пакета, поэтому сравнение
функцией errors.Is() работает в обе стороны.
web.Mime.TextHtml.String() // справочник MIME типов: "text/html;charset=UTF-8"
web.Method.Get.String() // справочник HTTP методов запросов: "GET"
web.Header.ContentType.String() // справочник заголовков: "Content-Type"
web.Status.NotFound.String() // справочник статусов HTTP ответов: "Not Found"
web.File.MimeByExtension(".png").String() // справочник MIME типов файлов: "image/png"
web.File.MimeByFilename("example.txt").String() // "text/plain"
Справочники дополняются пользовательскими данными через встраивание, например собственный справочник заголовков:
// myHeaders Структура справочника заголовков с пользовательскими заголовками.
type myHeaders struct {
dic.Headers
XRequestID dic.IHeader // Заголовок X-Request-Id.
}
var myHeader = &myHeaders{
Headers: dic.Header(),
XRequestID: dic.NewHeader("X-Request-Id"),
}
Конструктор New() возвращает объект удовлетворяющий интерфейсу web.Interface:
ID— уникальный идентификатор сервера;Handler— назначение обработчика запросов, обязательно до запуска сервера;ListenAndServe,ListenAndServeWithConfig— запуск сервера на адресе или сокете;ListenAndServeTLS,ListenAndServeTLSWithConfig— запуск сервера в режиме TLS;ListenersSystemdWithoutNames,ListenersSystemdWithNames— получение сокетов, переданных службой systemd;ListenersSystemdTLSWithoutNames,ListenersSystemdTLSWithNames— то же самое в режиме TLS;NewListener,NewListenerTLS— создание слушателя по конфигурации без запуска сервера;Serve,ServeWithId,ServeTLS,ServeTLSWithId— запуск сервера на готовом слушателе;Stop,Wait— прерывание и ожидание завершения работы сервера;Clean— очистка последней ошибки;Errors— справочник ошибок;Error— последняя ошибка веб сервера или библиотекиgithub.com/webnice/net.
Полное описание методов интерфейса доступно в документации пакета: https://pkg.go.dev/github.com/webnice/web/v4.
# Стандартный прогон с покрытием.
go test -cover ./...
# Прогон через Makefile (агрегированный профиль покрытия в coverage.log).
make test
© WEB NICE, распространяется под лицензией MIT.