mirror of
https://gitlab.com/pulsechaincom/prysm-pulse.git
synced 2025-01-10 03:31:20 +00:00
7dd99de69f
* Restructure API Middleware * fix package name in tests * build file * gzl * fix one more test
109 lines
2.8 KiB
Go
109 lines
2.8 KiB
Go
package apimiddleware
|
|
|
|
import (
|
|
"encoding/base64"
|
|
"fmt"
|
|
"reflect"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
|
"github.com/pkg/errors"
|
|
"github.com/wealdtech/go-bytesutil"
|
|
)
|
|
|
|
// processField calls each processor function on any field that has the matching tag set.
|
|
// It is a recursive function.
|
|
func processField(s interface{}, processors []fieldProcessor) error {
|
|
kind := reflect.TypeOf(s).Kind()
|
|
if kind != reflect.Ptr && kind != reflect.Slice && kind != reflect.Array {
|
|
return fmt.Errorf("processing fields of kind '%v' is unsupported", kind)
|
|
}
|
|
|
|
t := reflect.TypeOf(s).Elem()
|
|
v := reflect.Indirect(reflect.ValueOf(s))
|
|
|
|
for i := 0; i < t.NumField(); i++ {
|
|
switch v.Field(i).Kind() {
|
|
case reflect.Slice:
|
|
sliceElem := t.Field(i).Type.Elem()
|
|
kind := sliceElem.Kind()
|
|
// Recursively process slices to struct pointers.
|
|
if kind == reflect.Ptr && sliceElem.Elem().Kind() == reflect.Struct {
|
|
for j := 0; j < v.Field(i).Len(); j++ {
|
|
if err := processField(v.Field(i).Index(j).Interface(), processors); err != nil {
|
|
return errors.Wrapf(err, "could not process field '%s'", t.Field(i).Name)
|
|
}
|
|
}
|
|
}
|
|
// Process each string in string slices.
|
|
if kind == reflect.String {
|
|
for _, proc := range processors {
|
|
_, hasTag := t.Field(i).Tag.Lookup(proc.tag)
|
|
if hasTag {
|
|
for j := 0; j < v.Field(i).Len(); j++ {
|
|
if err := proc.f(v.Field(i).Index(j)); err != nil {
|
|
return errors.Wrapf(err, "could not process field '%s'", t.Field(i).Name)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
// Recursively process struct pointers.
|
|
case reflect.Ptr:
|
|
if v.Field(i).Elem().Kind() == reflect.Struct {
|
|
if err := processField(v.Field(i).Interface(), processors); err != nil {
|
|
return errors.Wrapf(err, "could not process field '%s'", t.Field(i).Name)
|
|
}
|
|
}
|
|
default:
|
|
field := t.Field(i)
|
|
for _, proc := range processors {
|
|
if _, hasTag := field.Tag.Lookup(proc.tag); hasTag {
|
|
if err := proc.f(v.Field(i)); err != nil {
|
|
return errors.Wrapf(err, "could not process field '%s'", t.Field(i).Name)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func hexToBase64Processor(v reflect.Value) error {
|
|
b, err := bytesutil.FromHexString(v.String())
|
|
if err != nil {
|
|
return err
|
|
}
|
|
v.SetString(base64.StdEncoding.EncodeToString(b))
|
|
return nil
|
|
}
|
|
|
|
func base64ToHexProcessor(v reflect.Value) error {
|
|
if v.String() == "" {
|
|
return nil
|
|
}
|
|
b, err := base64.StdEncoding.DecodeString(v.String())
|
|
if err != nil {
|
|
return err
|
|
}
|
|
v.SetString(hexutil.Encode(b))
|
|
return nil
|
|
}
|
|
|
|
func enumToLowercaseProcessor(v reflect.Value) error {
|
|
v.SetString(strings.ToLower(v.String()))
|
|
return nil
|
|
}
|
|
|
|
func timeToUnixProcessor(v reflect.Value) error {
|
|
t, err := time.Parse(time.RFC3339, v.String())
|
|
if err != nil {
|
|
return err
|
|
}
|
|
v.SetString(strconv.FormatUint(uint64(t.Unix()), 10))
|
|
return nil
|
|
}
|