Compare commits

...

2 Commits

Author SHA1 Message Date
91a82b5f48 add httpdata; 2023-10-31 10:21:45 +08:00
c2bf543f0a exegroup/修改HTTPListenAndServe支持tls并删除HTTPServer; 2023-06-28 10:54:39 +08:00
6 changed files with 266 additions and 22 deletions

View File

@@ -15,51 +15,73 @@ const (
)
type Option interface {
apply(server *http.Server)
apply(cfg *config)
}
func WithPort(port int) Option {
return optionFunc(func(server *http.Server) {
server.Addr = net.JoinHostPort("", strconv.Itoa(port))
return optionFunc(func(cfg *config) {
cfg.server.Addr = net.JoinHostPort("", strconv.Itoa(port))
})
}
func WithHandler(handler http.Handler) Option {
return optionFunc(func(server *http.Server) {
server.Handler = handler
return optionFunc(func(cfg *config) {
cfg.server.Handler = handler
})
}
func WithServer(server *http.Server) Option {
return optionFunc(func(cfg *config) {
cfg.server = server
})
}
func WithStartFn(fn func(server *http.Server) error) Option {
return optionFunc(func(cfg *config) {
cfg.startFn = fn
})
}
// WithServerOption 使用 fn 配置 [http.Server];
func WithServerOption(fn func(server *http.Server)) Option {
return optionFunc(fn)
return optionFunc(func(cfg *config) {
fn(cfg.server)
})
}
type optionFunc func(server *http.Server)
type config struct {
server *http.Server
startFn func(server *http.Server) error
}
func (fn optionFunc) apply(server *http.Server) {
fn(server)
func newDefaultConfig() *config {
return &config{
server: &http.Server{
Addr: DefaultAddr,
ReadHeaderTimeout: DefaultReadHeaderTimeout,
},
startFn: func(server *http.Server) error {
return server.ListenAndServe()
},
}
}
type optionFunc func(cfg *config)
func (fn optionFunc) apply(cfg *config) {
fn(cfg)
}
// HTTPListenAndServe 创建 [http.Server] 并提供启动和停止函数;
// opts 按照顺序应用到 [http.Server] 上.
func HTTPListenAndServe(opts ...Option) (func(ctx context.Context) error, func(ctx context.Context)) {
server := &http.Server{
Addr: DefaultAddr,
ReadHeaderTimeout: DefaultReadHeaderTimeout,
}
cfg := newDefaultConfig()
for _, opt := range opts {
opt.apply(server)
opt.apply(cfg)
}
return HTTPServer(server)
}
// HTTPServer 提供 [http.Server] 的启动和停止函数;
func HTTPServer(server *http.Server) (func(ctx context.Context) error, func(ctx context.Context)) {
inShutdown := &atomic.Bool{}
c := make(chan error, 1)
goFunc := func(_ context.Context) error {
err := server.ListenAndServe()
err := cfg.startFn(cfg.server)
if inShutdown.Load() {
err = <-c
}
@@ -67,7 +89,7 @@ func HTTPServer(server *http.Server) (func(ctx context.Context) error, func(ctx
}
stopFunc := func(ctx context.Context) {
inShutdown.Store(true)
c <- server.Shutdown(ctx)
c <- cfg.server.Shutdown(ctx)
}
return goFunc, stopFunc
}

141
httpdata/.golangci.yaml Normal file
View File

@@ -0,0 +1,141 @@
## 基于 golangci-lint@v1.52.2
run:
timeout: 1m
build-tags: [ ]
skip-dirs: [ ]
skip-files: [ ]
linters:
disable-all: true
enable:
- errcheck
- gosimple
- govet
- ineffassign
- staticcheck
- typecheck
- unused
- asasalint
- asciicheck
- bidichk
- bodyclose
- containedctx
- cyclop
- dupl
- durationcheck
- errname
- errorlint
- exhaustive
- exportloopref
- funlen
- gocheckcompilerdirectives
- gochecknoinits
- goconst
- gocritic
- gocyclo
- goimports
- gomnd
- goprintffuncname
- gosec
- lll
- loggercheck
- makezero
- nakedret
- nestif
- nilnil
- noctx
- nolintlint
- prealloc
- predeclared
- promlinter
- reassign
- revive
- rowserrcheck
- stylecheck
- tenv
- testableexamples
- testpackage
- tparallel
- unconvert
- unparam
- usestdlibvars
- wastedassign
- whitespace
linters-settings:
errcheck:
check-type-assertions: true
exclude-functions: [ ]
govet:
enable-all: true
disable: [ ]
cyclop:
max-complexity: 10
package-average: 0.0
dupl:
threshold: 150
exhaustive:
check:
- switch
- map
funlen:
lines: 100
statements: 60
gocritic:
disabled-checks:
- commentFormatting
settings:
captLocal:
paramsOnly: false
underef:
skipRecvDeref: false
gocyclo:
min-complexity: 20
gomnd:
ignored-functions:
- os.Chmod
- os.Mkdir
- os.MkdirAll
- os.OpenFile
- os.WriteFile
- prometheus.ExponentialBuckets
- prometheus.ExponentialBucketsRange
- prometheus.LinearBuckets
lll:
line-length: 240
nakedret:
max-func-lines: 10
nestif:
min-complexity: 5
predeclared:
ignore: ""
q: false
reassign:
patterns:
- ".*"
rowserrcheck:
packages:
- github.com/jmoiron/sqlx
tenv:
all: true
usestdlibvars:
time-month: true
time-layout: true
crypto-hash: true
default-rpc-path: true
os-dev-null: true
sql-isolation-level: true
tls-signature-scheme: true
constant-kind: true
syslog-priority: true
issues:
max-same-issues: 10
exclude-rules:
- source: "//noinspection"
linters: [ gocritic ]
- path: "_test\\.go"
linters:
- bodyclose
- dupl
- funlen
- goconst
- gosec
- noctx

14
httpdata/code.go Normal file
View File

@@ -0,0 +1,14 @@
package httpdata
type Code string
const (
CodeOK Code = "ok"
CodeError Code = "error"
CodeBadRequest Code = "bad_request"
CodeInternal Code = "internal"
CodeInternalUpstream Code = "internal.upstream"
CodeUnexpect Code = "unexpect"
CodeUnexpectPanic Code = "unexpect.panic"
CodeUnknown Code = "unknown"
)

22
httpdata/data.go Normal file
View File

@@ -0,0 +1,22 @@
package httpdata
type Response struct {
Data any `json:"data,omitempty"`
Code Code `json:"code"`
Message string `json:"message,omitempty"`
}
type PageData struct {
List []any `json:"list"`
PageIndex int `json:"pageIndex"` // >=1
PageSize int `json:"pageSize"` // >=1
Total int `json:"total"` // maybe 0
}
func NewOkResponse(data any) Response {
return Response{
Code: CodeOK,
Message: "",
Data: data,
}
}

42
httpdata/error.go Normal file
View File

@@ -0,0 +1,42 @@
package httpdata
import (
"errors"
)
type UniverseError struct {
Code Code
Message string
}
func NewUniverseError(code Code, message string) error {
return UniverseError{
Code: code,
Message: message,
}
}
func NewBadRequestError(message string) error {
return UniverseError{
Code: CodeBadRequest,
Message: message,
}
}
func (err UniverseError) Error() string {
if err.Message == "" {
return string(err.Code)
}
return string(err.Code) + ": " + err.Message
}
func IsUniverseError(err error) bool {
return errors.As(err, &UniverseError{})
}
func ToUniverseError(err error, code Code, message string) error {
if err == nil || IsUniverseError(err) {
return err
}
return NewUniverseError(code, message)
}

3
httpdata/go.mod Normal file
View File

@@ -0,0 +1,3 @@
module git.blauwelle.com/go/crate/httpdata
go 1.21.1