core
coverage: 53.7% of statements
A wrapper on top of github.com/julienschmidt/httprouter which defines working with middleware, token and logrus
Config
Example ./config/core.ini
file:
[http]
;http else https
protocol = https
; addr specifies the TCP address for the server to listen on,in the form "host:port". If empty, ":http" (port 80) is used.
; The service names are defined in RFC 6335 and assigned by IANA.
; See net.Dial for details of the address format.
addr = :81
; Filenames containing a certificate and matching private key for the server must be provided if neither the Server's
; TLSConfig.Certificates nor TLSConfig.GetCertificate are populated.
; If the certificate is signed by a certificate authority, the certFile should be the concatenation of the server's certificate,
; any intermediates, and the CA's certificate.
tls_cert_file = ./config/tls/cert.pem
tls_key_file = ./config/tls/key.pem
; https://golang.org/pkg/net/http/#Server -> ReadTimeout
read_timeout = 60
;https://golang.org/pkg/net/http/#Server -> WriteTimeout
write_timeout = 60
;https://golang.org/pkg/net/http/#Server ->IdleTimeout
idle_timeout = 60
;waiting for the server to shutdown. If the time has expired, then it is forced to complete
stop_server_timeout = 60
[static_file]
http_path_prefix = /file
dir = ./file
[token]
; crypt_aes, jose_sign and jose_crypt
backend = crypt_aes
; Key sizes when using the `crypt_aes` backend:
; The key argument should be the AES key, either 16, 24, or 32 bytes to select
; AES-128, AES-192, or AES-256.
key_previous = qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
key_next = wertyuiopasdfghjwertyuiopasdfghj
; backend jose_sign https://pkgo.dev/github.com/dvsekhvalnov/[email protected]?utm_source=gopls#Sign
jose_signing_alg = HS256
; backend jose_crypt https://pkgo.dev/github.com/dvsekhvalnov/[email protected]?utm_source=gopls#Encrypt
jose_encrypt_alg = dir
jose_encrypt_enc = A128GCM
; global jose backends
jose_compress = true
[sessions]
; ram
backend=ram
; How many seconds the session exists. If 0 then sessions are not deleted
expiries = 60
; Says to take snapshots of sessions from memory to disk
; If TRUE then at startup will try to load all sessions from disk into memory.
; Session expiries time is not saved
ram_is_snapshot = true
ram_snapshot_file = ./storage/sessions.snapshot
[error]
; error output in http.Writer
display = true
[log]
; trace, debug, info, warn, error, fatal, panic
; https://pkgo.dev/github.com/sirupsen/logrus?utm_source=godoc#Level
level = trace
;json else text
format = json
; write log to file
file = ./log/app.log
Token
Token benchmarks:
goos: windows
goarch: amd64
pkg: github.com/v-grabko1999/core/token
BenchmarkMarshalBackendCryptAES-8 299734 3841 ns/op 2232 B/op 17 allocs/op
BenchmarkMarshalBackendJoseSign-8 138805 8748 ns/op 7086 B/op 54 allocs/op
BenchmarkMarshalBackendJoseCrypt-8 6664 164900 ns/op 820620 B/op 87 allocs/op
BenchmarkUnmarshalBackendCryptAES-8 299976 4056 ns/op 1632 B/op 29 allocs/op
BenchmarkUnmarshalBackendJoseSign-8 129220 9435 ns/op 6712 B/op 65 allocs/op
BenchmarkUnmarshalBackendJoseCrypt-8 48314 27235 ns/op 47193 B/op 85 allocs/op
PASS
coverage: 43.6% of statements
ok github.com/v-grabko1999/core/token 9.049s
Example use token:
package main
import (
"log"
"github.com/v-grabko1999/core/token"
)
func main() {
aes, err := NewBackendCryptAES([]byte("qqqqqqqqqqqqqqqq"))
if err != nil {
panic("core init token.NewCryptAES Next error: " + err.Error())
}
enc := token.NewEncoder(aes)
//create new token
tok := enc.NewToken()
//token set string value
if err := tok.SetString("key1", "value1"); err != nil {
log.Fatal("token set string error: ", err)
}
//token encode string
tokenRaw, err := tok.MarshalString()
if err != nil {
log.Fatal("token marshal string error: ", err)
}
log.Println("token raw: ", tokenRaw)
//token decode string
t, err := enc.UnmarshalString(tokenRaw)
if err != nil {
log.Fatal("token unmarshal string error: ", err)
}
//token get string value
val, exist, err := t.GetString("key1")
if err != nil {
log.Fatal("token get string `key1` error: ", err)
}
if !exist {
log.Fatal("token key `key1` not found")
}
log.Println("token string `key1` value: ", val)
//token update value
if err := t.UpString("key1", "value2"); err != nil {
log.Fatal("token update `key1` error: ", err)
}
//token get update value
val, exist, err = t.GetString("key1")
if err != nil {
log.Fatal("token get string `key1` error: ", err)
}
if !exist {
log.Fatal("token key `key1` not found")
}
log.Println("token string `key1` value: ", val)
}
Example base http server and use token, session
package main
import (
"github.com/v-grabko1999/core"
"github.com/v-grabko1999/core/sessions"
"github.com/v-grabko1999/core/token"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
)
func SetBook(p *core.Providers) error {
if err := p.Token.SetString("bookID", p.Param("bookID")); err != nil {
if err == token.ERR_KEY_EXIST {
if err := p.Token.UpString("bookID", p.Param("bookID")); err != nil {
return errors.Wrap(err, "token UpString bookID")
}
} else {
return errors.Wrap(err, "token set string bookID")
}
}
if err := p.Session.SetString("bookID", p.Param("bookID")); err != nil {
if err == sessions.ERR_KEY_EXIST {
if err := p.Session.UpString("bookID", p.Param("bookID")); err != nil {
return errors.Wrap(err, "Session UpString bookID")
}
} else {
return errors.Wrap(err, "Session set string bookID")
}
}
return p.WriteHtml(200, "token write bookID: "+p.Param("bookID"))
}
func GetBook(p *core.Providers) error {
id, exist, err := p.Token.GetString("bookID")
if err != nil {
return errors.Wrap(err, "token get string bookID")
}
if exist {
if err := p.WriteHtml(200, "bookID: "+id); err != nil {
return errors.Wrap(err, "WriteHtml")
}
} else {
if err := p.WriteHtml(200, "book in token not found"); err != nil {
return errors.Wrap(err, "WriteHtml")
}
}
id, exist, err = p.Session.GetString("bookID")
if err != nil {
return errors.Wrap(err, "Session get string bookID")
}
if exist {
if err := p.WriteHtml(200, "<br>Session bookID: "+id); err != nil {
return errors.Wrap(err, "WriteHtml")
}
} else {
if err := p.WriteHtml(200, "<br>book in Session not found"); err != nil {
return errors.Wrap(err, "WriteHtml")
}
}
return nil
}
func main() {
r := core.New()
r.GET("/", GetBook)
r.GET("/book/:bookID", SetBook)
core.StartStop(func() {
r.Start()
}, func() {
if err := r.Stop(); err != nil {
r.Log.WithFields(logrus.Fields{
"module": "main",
"err": err,
}).Error("router stop")
} else {
r.Log.WithFields(logrus.Fields{
"module": "main",
}).Info("router stopped os.Interrupt")
}
})
}