mirror of
https://github.com/superseriousbusiness/gotosocial.git
synced 2025-10-28 16:22:24 -05:00
[performance] faster request id generation (#4405)
This uses a much faster method of generating request IDs using an atomically updated counter instead of a mutex lock and read of /dev/random. Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4405 Co-authored-by: kim <grufwub@gmail.com> Co-committed-by: kim <grufwub@gmail.com>
This commit is contained in:
parent
9cb177cd8a
commit
5a54e7156b
2 changed files with 27 additions and 30 deletions
|
|
@ -53,7 +53,10 @@ func HeaderFilter(state *state.State) gin.HandlerFunc {
|
|||
}
|
||||
|
||||
func headerFilterAllowMode(state *state.State) func(c *gin.Context) {
|
||||
_ = *state //nolint
|
||||
if state == nil {
|
||||
panic(gtserror.New("nil check elimination"))
|
||||
}
|
||||
|
||||
// Allowlist mode: explicit block takes
|
||||
// precedence over explicit allow.
|
||||
//
|
||||
|
|
@ -93,7 +96,10 @@ func headerFilterAllowMode(state *state.State) func(c *gin.Context) {
|
|||
}
|
||||
|
||||
func headerFilterBlockMode(state *state.State) func(c *gin.Context) {
|
||||
_ = *state //nolint
|
||||
if state == nil {
|
||||
panic(gtserror.New("nil check elimination"))
|
||||
}
|
||||
|
||||
// Blocklist/default mode: explicit allow
|
||||
// takes precedence over explicit block.
|
||||
//
|
||||
|
|
|
|||
|
|
@ -18,12 +18,9 @@
|
|||
package middleware
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"crypto/rand"
|
||||
"encoding/base32"
|
||||
"encoding/binary"
|
||||
"io"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"code.superseriousbusiness.org/gotosocial/internal/gtscontext"
|
||||
|
|
@ -31,43 +28,37 @@ import (
|
|||
)
|
||||
|
||||
var (
|
||||
// crand provides buffered reads of random input.
|
||||
crand = bufio.NewReader(rand.Reader)
|
||||
mrand sync.Mutex
|
||||
// request counter.
|
||||
count atomic.Uint32
|
||||
|
||||
// base32enc is a base 32 encoding based on a human-readable character set (no padding).
|
||||
base32enc = base32.NewEncoding("0123456789abcdefghjkmnpqrstvwxyz").WithPadding(-1)
|
||||
// server start time in milliseconds.
|
||||
start = uint64(time.Now().UnixMilli())
|
||||
|
||||
// shorthand to binary.
|
||||
be = binary.BigEndian
|
||||
|
||||
// b32 is a base 32 encoding based on a human-readable character set (no padding).
|
||||
b32 = base32.NewEncoding("0123456789abcdefghjkmnpqrstvwxyz").WithPadding(-1)
|
||||
)
|
||||
|
||||
// NewRequestID generates a new request ID string.
|
||||
func NewRequestID() string {
|
||||
// 0:8 = timestamp
|
||||
// 8:12 = entropy
|
||||
//
|
||||
// inspired by ULID.
|
||||
b := make([]byte, 12)
|
||||
var buf [12]byte
|
||||
|
||||
// Get current time in milliseconds.
|
||||
ms := uint64(time.Now().UnixMilli()) // #nosec G115 -- Pre-1970 clock?
|
||||
|
||||
// Store binary time data in byte buffer.
|
||||
binary.LittleEndian.PutUint64(b[0:8], ms)
|
||||
|
||||
mrand.Lock()
|
||||
// Read random bits into buffer end.
|
||||
_, _ = io.ReadFull(crand, b[8:12])
|
||||
mrand.Unlock()
|
||||
|
||||
// Encode the binary time+entropy ID.
|
||||
return base32enc.EncodeToString(b)
|
||||
// Generate unique request
|
||||
// ID from request count and
|
||||
// time of server initialization.
|
||||
be.PutUint64(buf[0:], start)
|
||||
be.PutUint32(buf[8:], count.Add(1))
|
||||
return b32.EncodeToString(buf[:])
|
||||
}
|
||||
|
||||
// AddRequestID returns a gin middleware which adds a unique ID to each request (both response header and context).
|
||||
func AddRequestID(header string) gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
id := c.GetHeader(header)
|
||||
// Have we found anything?
|
||||
if id == "" {
|
||||
|
||||
// Generate new ID.
|
||||
id = NewRequestID()
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue