152 lines
2.4 KiB
Go
152 lines
2.4 KiB
Go
package serv
|
|
|
|
import (
|
|
"bytes"
|
|
"crypto/sha1"
|
|
"encoding/hex"
|
|
"io"
|
|
"sort"
|
|
"strings"
|
|
|
|
"github.com/cespare/xxhash/v2"
|
|
"github.com/dosco/super-graph/jsn"
|
|
)
|
|
|
|
// nolint: errcheck
|
|
func mkkey(h *xxhash.Digest, k1 string, k2 string) uint64 {
|
|
h.WriteString(k1)
|
|
h.WriteString(k2)
|
|
v := h.Sum64()
|
|
h.Reset()
|
|
|
|
return v
|
|
}
|
|
|
|
// nolint: errcheck
|
|
func gqlHash(b string, vars []byte, role string) string {
|
|
b = strings.TrimSpace(b)
|
|
h := sha1.New()
|
|
query := "query"
|
|
|
|
s, e := 0, 0
|
|
space := []byte{' '}
|
|
starting := true
|
|
|
|
var b0, b1 byte
|
|
|
|
if len(b) == 0 {
|
|
return ""
|
|
}
|
|
|
|
for {
|
|
if starting && b[e] == 'q' {
|
|
n := 0
|
|
se := e
|
|
for e < len(b) && n < len(query) && b[e] == query[n] {
|
|
n++
|
|
e++
|
|
}
|
|
if n != len(query) {
|
|
io.WriteString(h, strings.ToLower(b[se:e]))
|
|
}
|
|
}
|
|
if e >= len(b) {
|
|
break
|
|
}
|
|
if ws(b[e]) {
|
|
for e < len(b) && ws(b[e]) {
|
|
e++
|
|
}
|
|
if e < len(b) {
|
|
b1 = b[e]
|
|
}
|
|
if al(b0) && al(b1) {
|
|
h.Write(space)
|
|
}
|
|
} else {
|
|
starting = false
|
|
s = e
|
|
for e < len(b) && !ws(b[e]) {
|
|
e++
|
|
}
|
|
if e != 0 {
|
|
b0 = b[(e - 1)]
|
|
}
|
|
io.WriteString(h, strings.ToLower(b[s:e]))
|
|
}
|
|
if e >= len(b) {
|
|
break
|
|
}
|
|
}
|
|
|
|
if len(role) != 0 {
|
|
io.WriteString(h, role)
|
|
}
|
|
|
|
if len(vars) == 0 {
|
|
return hex.EncodeToString(h.Sum(nil))
|
|
}
|
|
|
|
fields := jsn.Keys([]byte(vars))
|
|
|
|
sort.Slice(fields, func(i, j int) bool {
|
|
return bytes.Compare(fields[i], fields[j]) == -1
|
|
})
|
|
|
|
for i := range fields {
|
|
h.Write(fields[i])
|
|
}
|
|
|
|
return hex.EncodeToString(h.Sum(nil))
|
|
}
|
|
|
|
func ws(b byte) bool {
|
|
return b == ' ' || b == '\n' || b == '\t' || b == ','
|
|
}
|
|
|
|
func al(b byte) bool {
|
|
return (b >= 'a' && b <= 'z') || (b >= 'A' && b <= 'Z') || (b >= '0' && b <= '9')
|
|
}
|
|
|
|
func gqlName(b string) string {
|
|
state, s := 0, 0
|
|
|
|
for i := 0; i < len(b); i++ {
|
|
switch {
|
|
case state == 2 && b[i] == '{':
|
|
return b[s:i]
|
|
case state == 2 && b[i] == ' ':
|
|
return b[s:i]
|
|
case state == 1 && b[i] == '{':
|
|
return ""
|
|
case state == 1 && b[i] != ' ':
|
|
s = i
|
|
state = 2
|
|
case state == 1 && b[i] == ' ':
|
|
continue
|
|
case i != 0 && b[i] == ' ' && (b[i-1] == 'n' || b[i-1] == 'y'):
|
|
state = 1
|
|
}
|
|
}
|
|
|
|
return ""
|
|
}
|
|
|
|
func findStmt(role string, stmts []stmt) *stmt {
|
|
for i := range stmts {
|
|
if stmts[i].role.Name != role {
|
|
continue
|
|
}
|
|
return &stmts[i]
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func fatalInProd(err error, msg string) {
|
|
if isDev() {
|
|
errlog.Error().Err(err).Msg(msg)
|
|
} else {
|
|
errlog.Fatal().Err(err).Msg(msg)
|
|
}
|
|
}
|