mirror of
https://gitlab.com/pulsechaincom/prysm-pulse.git
synced 2024-12-22 19:40:37 +00:00
Restructure API Middleware (#9663)
* Restructure API Middleware * fix package name in tests * build file * gzl * fix one more test
This commit is contained in:
parent
a9a4bb9163
commit
7dd99de69f
@ -3,12 +3,8 @@ load("@prysm//tools/go:def.bzl", "go_library", "go_test")
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"api_middleware.go",
|
||||
"api_middleware_processing.go",
|
||||
"api_middleware_structs.go",
|
||||
"gateway.go",
|
||||
"log.go",
|
||||
"param_handling.go",
|
||||
],
|
||||
importpath = "github.com/prysmaticlabs/prysm/api/gateway",
|
||||
visibility = [
|
||||
@ -16,16 +12,13 @@ go_library(
|
||||
"//validator:__subpackages__",
|
||||
],
|
||||
deps = [
|
||||
"//api/grpc:go_default_library",
|
||||
"//encoding/bytesutil:go_default_library",
|
||||
"//api/gateway/apimiddleware:go_default_library",
|
||||
"//runtime:go_default_library",
|
||||
"@com_github_ethereum_go_ethereum//common/hexutil:go_default_library",
|
||||
"@com_github_gorilla_mux//:go_default_library",
|
||||
"@com_github_grpc_ecosystem_grpc_gateway_v2//runtime:go_default_library",
|
||||
"@com_github_pkg_errors//:go_default_library",
|
||||
"@com_github_rs_cors//:go_default_library",
|
||||
"@com_github_sirupsen_logrus//:go_default_library",
|
||||
"@com_github_wealdtech_go_bytesutil//:go_default_library",
|
||||
"@org_golang_google_grpc//:go_default_library",
|
||||
"@org_golang_google_grpc//connectivity:go_default_library",
|
||||
"@org_golang_google_grpc//credentials:go_default_library",
|
||||
@ -34,14 +27,10 @@ go_library(
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = [
|
||||
"api_middleware_processing_test.go",
|
||||
"gateway_test.go",
|
||||
"param_handling_test.go",
|
||||
],
|
||||
srcs = ["gateway_test.go"],
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//api/grpc:go_default_library",
|
||||
"//api/gateway/apimiddleware:go_default_library",
|
||||
"//cmd/beacon-chain/flags:go_default_library",
|
||||
"//testing/assert:go_default_library",
|
||||
"//testing/require:go_default_library",
|
||||
|
40
api/gateway/apimiddleware/BUILD.bazel
Normal file
40
api/gateway/apimiddleware/BUILD.bazel
Normal file
@ -0,0 +1,40 @@
|
||||
load("@prysm//tools/go:def.bzl", "go_library", "go_test")
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"api_middleware.go",
|
||||
"log.go",
|
||||
"param_handling.go",
|
||||
"process_field.go",
|
||||
"process_request.go",
|
||||
"structs.go",
|
||||
],
|
||||
importpath = "github.com/prysmaticlabs/prysm/api/gateway/apimiddleware",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//api/grpc:go_default_library",
|
||||
"//encoding/bytesutil:go_default_library",
|
||||
"@com_github_ethereum_go_ethereum//common/hexutil:go_default_library",
|
||||
"@com_github_gorilla_mux//:go_default_library",
|
||||
"@com_github_pkg_errors//:go_default_library",
|
||||
"@com_github_sirupsen_logrus//:go_default_library",
|
||||
"@com_github_wealdtech_go_bytesutil//:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = [
|
||||
"param_handling_test.go",
|
||||
"process_request_test.go",
|
||||
],
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//api/grpc:go_default_library",
|
||||
"//testing/assert:go_default_library",
|
||||
"//testing/require:go_default_library",
|
||||
"@com_github_gorilla_mux//:go_default_library",
|
||||
"@com_github_sirupsen_logrus//hooks/test:go_default_library",
|
||||
],
|
||||
)
|
@ -1,4 +1,4 @@
|
||||
package gateway
|
||||
package apimiddleware
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
@ -50,19 +50,16 @@ type QueryParam struct {
|
||||
Enum bool
|
||||
}
|
||||
|
||||
// Hook is a function that can be invoked at various stages of the request/response cycle, leading to custom behaviour for a specific endpoint.
|
||||
type Hook = func(endpoint Endpoint, w http.ResponseWriter, req *http.Request) ErrorJson
|
||||
|
||||
// CustomHandler is a function that can be invoked at the very beginning of the request,
|
||||
// essentially replacing the whole default request/response logic with custom logic for a specific endpoint.
|
||||
type CustomHandler = func(m *ApiProxyMiddleware, endpoint Endpoint, w http.ResponseWriter, req *http.Request) (handled bool)
|
||||
|
||||
// HookCollection contains hooks that can be used to amend the default request/response cycle with custom logic for a specific endpoint.
|
||||
type HookCollection struct {
|
||||
OnPreDeserializeRequestBodyIntoContainer []Hook
|
||||
OnPostDeserializeRequestBodyIntoContainer []Hook
|
||||
OnPreDeserializeGrpcResponseBodyIntoContainer []func([]byte, interface{}) (bool, ErrorJson)
|
||||
OnPreSerializeMiddlewareResponseIntoJson []func(interface{}) (bool, []byte, ErrorJson)
|
||||
OnPreDeserializeRequestBodyIntoContainer func(endpoint Endpoint, w http.ResponseWriter, req *http.Request) ErrorJson
|
||||
OnPostDeserializeRequestBodyIntoContainer func(endpoint Endpoint, w http.ResponseWriter, req *http.Request) ErrorJson
|
||||
OnPreDeserializeGrpcResponseBodyIntoContainer func([]byte, interface{}) (bool, ErrorJson)
|
||||
OnPreSerializeMiddlewareResponseIntoJson func(interface{}) (bool, []byte, ErrorJson)
|
||||
}
|
||||
|
||||
// fieldProcessor applies the processing function f to a value when the tag is present on the field.
|
||||
@ -93,23 +90,10 @@ func (m *ApiProxyMiddleware) handleApiPath(gatewayRouter *mux.Router, path strin
|
||||
}
|
||||
|
||||
if req.Method == "POST" {
|
||||
for _, hook := range endpoint.Hooks.OnPreDeserializeRequestBodyIntoContainer {
|
||||
if errJson := hook(*endpoint, w, req); errJson != nil {
|
||||
WriteError(w, errJson, nil)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if errJson := DeserializeRequestBodyIntoContainer(req.Body, endpoint.PostRequest); errJson != nil {
|
||||
if errJson := deserializeRequestBodyIntoContainerWrapped(endpoint, req, w); errJson != nil {
|
||||
WriteError(w, errJson, nil)
|
||||
return
|
||||
}
|
||||
for _, hook := range endpoint.Hooks.OnPostDeserializeRequestBodyIntoContainer {
|
||||
if errJson := hook(*endpoint, w, req); errJson != nil {
|
||||
WriteError(w, errJson, nil)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if errJson := ProcessRequestContainerFields(endpoint.PostRequest); errJson != nil {
|
||||
WriteError(w, errJson, nil)
|
||||
@ -125,87 +109,116 @@ func (m *ApiProxyMiddleware) handleApiPath(gatewayRouter *mux.Router, path strin
|
||||
WriteError(w, errJson, nil)
|
||||
return
|
||||
}
|
||||
grpcResponse, errJson := ProxyRequest(req)
|
||||
grpcResp, errJson := ProxyRequest(req)
|
||||
if errJson != nil {
|
||||
WriteError(w, errJson, nil)
|
||||
return
|
||||
}
|
||||
grpcResponseBody, errJson := ReadGrpcResponseBody(grpcResponse.Body)
|
||||
grpcRespBody, errJson := ReadGrpcResponseBody(grpcResp.Body)
|
||||
if errJson != nil {
|
||||
WriteError(w, errJson, nil)
|
||||
return
|
||||
}
|
||||
|
||||
var responseJson []byte
|
||||
if !GrpcResponseIsEmpty(grpcResponseBody) {
|
||||
if errJson := DeserializeGrpcResponseBodyIntoErrorJson(endpoint.Err, grpcResponseBody); errJson != nil {
|
||||
var respJson []byte
|
||||
if !GrpcResponseIsEmpty(grpcRespBody) {
|
||||
if errJson := DeserializeGrpcResponseBodyIntoErrorJson(endpoint.Err, grpcRespBody); errJson != nil {
|
||||
WriteError(w, errJson, nil)
|
||||
return
|
||||
}
|
||||
if endpoint.Err.Msg() != "" {
|
||||
HandleGrpcResponseError(endpoint.Err, grpcResponse, w)
|
||||
HandleGrpcResponseError(endpoint.Err, grpcResp, w)
|
||||
return
|
||||
}
|
||||
var response interface{}
|
||||
|
||||
var resp interface{}
|
||||
if req.Method == "GET" {
|
||||
response = endpoint.GetResponse
|
||||
resp = endpoint.GetResponse
|
||||
} else {
|
||||
response = endpoint.PostResponse
|
||||
resp = endpoint.PostResponse
|
||||
}
|
||||
|
||||
runDefault := true
|
||||
for _, hook := range endpoint.Hooks.OnPreDeserializeGrpcResponseBodyIntoContainer {
|
||||
ok, errJson := hook(grpcResponseBody, response)
|
||||
if errJson != nil {
|
||||
WriteError(w, errJson, nil)
|
||||
return
|
||||
}
|
||||
if ok {
|
||||
runDefault = false
|
||||
break
|
||||
}
|
||||
if errJson := deserializeGrpcResponseBodyIntoContainerWrapped(endpoint, grpcRespBody, resp); errJson != nil {
|
||||
WriteError(w, errJson, nil)
|
||||
return
|
||||
}
|
||||
if runDefault {
|
||||
if errJson := DeserializeGrpcResponseBodyIntoContainer(grpcResponseBody, response); errJson != nil {
|
||||
WriteError(w, errJson, nil)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if errJson := ProcessMiddlewareResponseFields(response); errJson != nil {
|
||||
if errJson := ProcessMiddlewareResponseFields(resp); errJson != nil {
|
||||
WriteError(w, errJson, nil)
|
||||
return
|
||||
}
|
||||
|
||||
var ok bool
|
||||
runDefault = true
|
||||
for _, hook := range endpoint.Hooks.OnPreSerializeMiddlewareResponseIntoJson {
|
||||
ok, responseJson, errJson = hook(response)
|
||||
if errJson != nil {
|
||||
WriteError(w, errJson, nil)
|
||||
return
|
||||
}
|
||||
if ok {
|
||||
runDefault = false
|
||||
break
|
||||
}
|
||||
}
|
||||
if runDefault {
|
||||
responseJson, errJson = SerializeMiddlewareResponseIntoJson(response)
|
||||
if errJson != nil {
|
||||
WriteError(w, errJson, nil)
|
||||
return
|
||||
}
|
||||
respJson, errJson = serializeMiddlewareResponseIntoJsonWrapped(endpoint, respJson, resp)
|
||||
if errJson != nil {
|
||||
WriteError(w, errJson, nil)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if errJson := WriteMiddlewareResponseHeadersAndBody(grpcResponse, responseJson, w); errJson != nil {
|
||||
if errJson := WriteMiddlewareResponseHeadersAndBody(grpcResp, respJson, w); errJson != nil {
|
||||
WriteError(w, errJson, nil)
|
||||
return
|
||||
}
|
||||
if errJson := Cleanup(grpcResponse.Body); errJson != nil {
|
||||
if errJson := Cleanup(grpcResp.Body); errJson != nil {
|
||||
WriteError(w, errJson, nil)
|
||||
return
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func deserializeRequestBodyIntoContainerWrapped(endpoint *Endpoint, req *http.Request, w http.ResponseWriter) ErrorJson {
|
||||
if endpoint.Hooks.OnPreDeserializeRequestBodyIntoContainer != nil {
|
||||
if errJson := endpoint.Hooks.OnPreDeserializeRequestBodyIntoContainer(*endpoint, w, req); errJson != nil {
|
||||
return errJson
|
||||
}
|
||||
}
|
||||
if errJson := DeserializeRequestBodyIntoContainer(req.Body, endpoint.PostRequest); errJson != nil {
|
||||
WriteError(w, errJson, nil)
|
||||
return errJson
|
||||
}
|
||||
if endpoint.Hooks.OnPostDeserializeRequestBodyIntoContainer != nil {
|
||||
if errJson := endpoint.Hooks.OnPostDeserializeRequestBodyIntoContainer(*endpoint, w, req); errJson != nil {
|
||||
return errJson
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func deserializeGrpcResponseBodyIntoContainerWrapped(endpoint *Endpoint, grpcResponseBody []byte, resp interface{}) ErrorJson {
|
||||
runDefault := true
|
||||
if endpoint.Hooks.OnPreDeserializeGrpcResponseBodyIntoContainer != nil {
|
||||
ok, errJson := endpoint.Hooks.OnPreDeserializeGrpcResponseBodyIntoContainer(grpcResponseBody, resp)
|
||||
if errJson != nil {
|
||||
return errJson
|
||||
}
|
||||
if ok {
|
||||
runDefault = false
|
||||
}
|
||||
}
|
||||
if runDefault {
|
||||
if errJson := DeserializeGrpcResponseBodyIntoContainer(grpcResponseBody, resp); errJson != nil {
|
||||
return errJson
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func serializeMiddlewareResponseIntoJsonWrapped(endpoint *Endpoint, respJson []byte, resp interface{}) ([]byte, ErrorJson) {
|
||||
runDefault := true
|
||||
var errJson ErrorJson
|
||||
if endpoint.Hooks.OnPreSerializeMiddlewareResponseIntoJson != nil {
|
||||
var ok bool
|
||||
ok, respJson, errJson = endpoint.Hooks.OnPreSerializeMiddlewareResponseIntoJson(resp)
|
||||
if errJson != nil {
|
||||
return nil, errJson
|
||||
}
|
||||
if ok {
|
||||
runDefault = false
|
||||
}
|
||||
}
|
||||
if runDefault {
|
||||
respJson, errJson = SerializeMiddlewareResponseIntoJson(resp)
|
||||
if errJson != nil {
|
||||
return nil, errJson
|
||||
}
|
||||
}
|
||||
return respJson, nil
|
||||
}
|
5
api/gateway/apimiddleware/log.go
Normal file
5
api/gateway/apimiddleware/log.go
Normal file
@ -0,0 +1,5 @@
|
||||
package apimiddleware
|
||||
|
||||
import "github.com/sirupsen/logrus"
|
||||
|
||||
var log = logrus.WithField("prefix", "apimiddleware")
|
@ -1,4 +1,4 @@
|
||||
package gateway
|
||||
package apimiddleware
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
@ -1,4 +1,4 @@
|
||||
package gateway
|
||||
package apimiddleware
|
||||
|
||||
import (
|
||||
"bytes"
|
108
api/gateway/apimiddleware/process_field.go
Normal file
108
api/gateway/apimiddleware/process_field.go
Normal file
@ -0,0 +1,108 @@
|
||||
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
|
||||
}
|
@ -1,22 +1,16 @@
|
||||
package gateway
|
||||
package apimiddleware
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/api/grpc"
|
||||
"github.com/wealdtech/go-bytesutil"
|
||||
)
|
||||
|
||||
// DeserializeRequestBodyIntoContainer deserializes the request's body into an endpoint-specific struct.
|
||||
@ -229,97 +223,3 @@ func Cleanup(grpcResponseBody io.ReadCloser) ErrorJson {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package gateway
|
||||
package apimiddleware
|
||||
|
||||
import (
|
||||
"bytes"
|
@ -1,4 +1,4 @@
|
||||
package gateway
|
||||
package apimiddleware
|
||||
|
||||
import (
|
||||
"net/http"
|
@ -13,6 +13,7 @@ import (
|
||||
"github.com/gorilla/mux"
|
||||
gwruntime "github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/api/gateway/apimiddleware"
|
||||
"github.com/prysmaticlabs/prysm/runtime"
|
||||
"github.com/rs/cors"
|
||||
"google.golang.org/grpc"
|
||||
@ -46,7 +47,7 @@ type Gateway struct {
|
||||
cancel context.CancelFunc
|
||||
remoteCert string
|
||||
gatewayAddr string
|
||||
apiMiddlewareEndpointFactory EndpointFactory
|
||||
apiMiddlewareEndpointFactory apimiddleware.EndpointFactory
|
||||
ctx context.Context
|
||||
startFailure error
|
||||
remoteAddr string
|
||||
@ -98,7 +99,7 @@ func (g *Gateway) WithMaxCallRecvMsgSize(size uint64) *Gateway {
|
||||
}
|
||||
|
||||
// WithApiMiddleware allows adding API Middleware proxy to the gateway.
|
||||
func (g *Gateway) WithApiMiddleware(endpointFactory EndpointFactory) *Gateway {
|
||||
func (g *Gateway) WithApiMiddleware(endpointFactory apimiddleware.EndpointFactory) *Gateway {
|
||||
g.apiMiddlewareEndpointFactory = endpointFactory
|
||||
return g
|
||||
}
|
||||
@ -271,7 +272,7 @@ func (g *Gateway) dialUnix(ctx context.Context, addr string) (*grpc.ClientConn,
|
||||
}
|
||||
|
||||
func (g *Gateway) registerApiMiddleware() {
|
||||
proxy := &ApiProxyMiddleware{
|
||||
proxy := &apimiddleware.ApiProxyMiddleware{
|
||||
GatewayAddress: g.gatewayAddr,
|
||||
EndpointCreator: g.apiMiddlewareEndpointFactory,
|
||||
}
|
||||
|
@ -10,6 +10,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/prysmaticlabs/prysm/api/gateway/apimiddleware"
|
||||
"github.com/prysmaticlabs/prysm/cmd/beacon-chain/flags"
|
||||
"github.com/prysmaticlabs/prysm/testing/assert"
|
||||
"github.com/prysmaticlabs/prysm/testing/require"
|
||||
@ -24,7 +25,7 @@ func (*mockEndpointFactory) Paths() []string {
|
||||
return []string{}
|
||||
}
|
||||
|
||||
func (*mockEndpointFactory) Create(_ string) (*Endpoint, error) {
|
||||
func (*mockEndpointFactory) Create(_ string) (*apimiddleware.Endpoint, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
|
@ -12,7 +12,7 @@ go_library(
|
||||
importpath = "github.com/prysmaticlabs/prysm/beacon-chain/rpc/apimiddleware",
|
||||
visibility = ["//beacon-chain:__subpackages__"],
|
||||
deps = [
|
||||
"//api/gateway:go_default_library",
|
||||
"//api/gateway/apimiddleware:go_default_library",
|
||||
"//api/grpc:go_default_library",
|
||||
"//beacon-chain/rpc/eth/events:go_default_library",
|
||||
"//encoding/bytesutil:go_default_library",
|
||||
@ -32,7 +32,7 @@ go_test(
|
||||
],
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//api/gateway:go_default_library",
|
||||
"//api/gateway/apimiddleware:go_default_library",
|
||||
"//api/grpc:go_default_library",
|
||||
"//beacon-chain/rpc/eth/events:go_default_library",
|
||||
"//encoding/bytesutil:go_default_library",
|
||||
|
@ -11,7 +11,7 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/api/gateway"
|
||||
"github.com/prysmaticlabs/prysm/api/gateway/apimiddleware"
|
||||
"github.com/prysmaticlabs/prysm/api/grpc"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/rpc/eth/events"
|
||||
"github.com/r3labs/sse"
|
||||
@ -23,7 +23,7 @@ type sszConfig struct {
|
||||
responseJson sszResponseJson
|
||||
}
|
||||
|
||||
func handleGetBeaconStateSSZ(m *gateway.ApiProxyMiddleware, endpoint gateway.Endpoint, w http.ResponseWriter, req *http.Request) (handled bool) {
|
||||
func handleGetBeaconStateSSZ(m *apimiddleware.ApiProxyMiddleware, endpoint apimiddleware.Endpoint, w http.ResponseWriter, req *http.Request) (handled bool) {
|
||||
config := sszConfig{
|
||||
sszPath: "/eth/v1/debug/beacon/states/{state_id}/ssz",
|
||||
fileName: "beacon_state.ssz",
|
||||
@ -32,7 +32,7 @@ func handleGetBeaconStateSSZ(m *gateway.ApiProxyMiddleware, endpoint gateway.End
|
||||
return handleGetSSZ(m, endpoint, w, req, config)
|
||||
}
|
||||
|
||||
func handleGetBeaconBlockSSZ(m *gateway.ApiProxyMiddleware, endpoint gateway.Endpoint, w http.ResponseWriter, req *http.Request) (handled bool) {
|
||||
func handleGetBeaconBlockSSZ(m *apimiddleware.ApiProxyMiddleware, endpoint apimiddleware.Endpoint, w http.ResponseWriter, req *http.Request) (handled bool) {
|
||||
config := sszConfig{
|
||||
sszPath: "/eth/v1/beacon/blocks/{block_id}/ssz",
|
||||
fileName: "beacon_block.ssz",
|
||||
@ -41,7 +41,7 @@ func handleGetBeaconBlockSSZ(m *gateway.ApiProxyMiddleware, endpoint gateway.End
|
||||
return handleGetSSZ(m, endpoint, w, req, config)
|
||||
}
|
||||
|
||||
func handleGetBeaconStateSSZV2(m *gateway.ApiProxyMiddleware, endpoint gateway.Endpoint, w http.ResponseWriter, req *http.Request) (handled bool) {
|
||||
func handleGetBeaconStateSSZV2(m *apimiddleware.ApiProxyMiddleware, endpoint apimiddleware.Endpoint, w http.ResponseWriter, req *http.Request) (handled bool) {
|
||||
config := sszConfig{
|
||||
sszPath: "/eth/v2/debug/beacon/states/{state_id}/ssz",
|
||||
fileName: "beacon_state.ssz",
|
||||
@ -50,7 +50,7 @@ func handleGetBeaconStateSSZV2(m *gateway.ApiProxyMiddleware, endpoint gateway.E
|
||||
return handleGetSSZ(m, endpoint, w, req, config)
|
||||
}
|
||||
|
||||
func handleGetBeaconBlockSSZV2(m *gateway.ApiProxyMiddleware, endpoint gateway.Endpoint, w http.ResponseWriter, req *http.Request) (handled bool) {
|
||||
func handleGetBeaconBlockSSZV2(m *apimiddleware.ApiProxyMiddleware, endpoint apimiddleware.Endpoint, w http.ResponseWriter, req *http.Request) (handled bool) {
|
||||
config := sszConfig{
|
||||
sszPath: "/eth/v2/beacon/blocks/{block_id}/ssz",
|
||||
fileName: "beacon_block.ssz",
|
||||
@ -60,8 +60,8 @@ func handleGetBeaconBlockSSZV2(m *gateway.ApiProxyMiddleware, endpoint gateway.E
|
||||
}
|
||||
|
||||
func handleGetSSZ(
|
||||
m *gateway.ApiProxyMiddleware,
|
||||
endpoint gateway.Endpoint,
|
||||
m *apimiddleware.ApiProxyMiddleware,
|
||||
endpoint apimiddleware.Endpoint,
|
||||
w http.ResponseWriter,
|
||||
req *http.Request,
|
||||
config sszConfig,
|
||||
@ -71,42 +71,42 @@ func handleGetSSZ(
|
||||
}
|
||||
|
||||
if errJson := prepareSSZRequestForProxying(m, endpoint, req, config.sszPath); errJson != nil {
|
||||
gateway.WriteError(w, errJson, nil)
|
||||
apimiddleware.WriteError(w, errJson, nil)
|
||||
return true
|
||||
}
|
||||
grpcResponse, errJson := gateway.ProxyRequest(req)
|
||||
grpcResponse, errJson := apimiddleware.ProxyRequest(req)
|
||||
if errJson != nil {
|
||||
gateway.WriteError(w, errJson, nil)
|
||||
apimiddleware.WriteError(w, errJson, nil)
|
||||
return true
|
||||
}
|
||||
grpcResponseBody, errJson := gateway.ReadGrpcResponseBody(grpcResponse.Body)
|
||||
grpcResponseBody, errJson := apimiddleware.ReadGrpcResponseBody(grpcResponse.Body)
|
||||
if errJson != nil {
|
||||
gateway.WriteError(w, errJson, nil)
|
||||
apimiddleware.WriteError(w, errJson, nil)
|
||||
return true
|
||||
}
|
||||
if errJson := gateway.DeserializeGrpcResponseBodyIntoErrorJson(endpoint.Err, grpcResponseBody); errJson != nil {
|
||||
gateway.WriteError(w, errJson, nil)
|
||||
if errJson := apimiddleware.DeserializeGrpcResponseBodyIntoErrorJson(endpoint.Err, grpcResponseBody); errJson != nil {
|
||||
apimiddleware.WriteError(w, errJson, nil)
|
||||
return true
|
||||
}
|
||||
if endpoint.Err.Msg() != "" {
|
||||
gateway.HandleGrpcResponseError(endpoint.Err, grpcResponse, w)
|
||||
apimiddleware.HandleGrpcResponseError(endpoint.Err, grpcResponse, w)
|
||||
return true
|
||||
}
|
||||
if errJson := gateway.DeserializeGrpcResponseBodyIntoContainer(grpcResponseBody, config.responseJson); errJson != nil {
|
||||
gateway.WriteError(w, errJson, nil)
|
||||
if errJson := apimiddleware.DeserializeGrpcResponseBodyIntoContainer(grpcResponseBody, config.responseJson); errJson != nil {
|
||||
apimiddleware.WriteError(w, errJson, nil)
|
||||
return true
|
||||
}
|
||||
responseSsz, errJson := serializeMiddlewareResponseIntoSSZ(config.responseJson.SSZData())
|
||||
if errJson != nil {
|
||||
gateway.WriteError(w, errJson, nil)
|
||||
apimiddleware.WriteError(w, errJson, nil)
|
||||
return true
|
||||
}
|
||||
if errJson := writeSSZResponseHeaderAndBody(grpcResponse, w, responseSsz, config.fileName); errJson != nil {
|
||||
gateway.WriteError(w, errJson, nil)
|
||||
apimiddleware.WriteError(w, errJson, nil)
|
||||
return true
|
||||
}
|
||||
if errJson := gateway.Cleanup(grpcResponse.Body); errJson != nil {
|
||||
gateway.WriteError(w, errJson, nil)
|
||||
if errJson := apimiddleware.Cleanup(grpcResponse.Body); errJson != nil {
|
||||
apimiddleware.WriteError(w, errJson, nil)
|
||||
return true
|
||||
}
|
||||
|
||||
@ -126,12 +126,16 @@ func sszRequested(req *http.Request) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func prepareSSZRequestForProxying(m *gateway.ApiProxyMiddleware, endpoint gateway.Endpoint, req *http.Request, sszPath string) gateway.ErrorJson {
|
||||
func prepareSSZRequestForProxying(
|
||||
m *apimiddleware.ApiProxyMiddleware,
|
||||
endpoint apimiddleware.Endpoint,
|
||||
req *http.Request, sszPath string,
|
||||
) apimiddleware.ErrorJson {
|
||||
req.URL.Scheme = "http"
|
||||
req.URL.Host = m.GatewayAddress
|
||||
req.RequestURI = ""
|
||||
req.URL.Path = sszPath
|
||||
if errJson := gateway.HandleURLParameters(endpoint.Path, req, []string{}); errJson != nil {
|
||||
if errJson := apimiddleware.HandleURLParameters(endpoint.Path, req, []string{}); errJson != nil {
|
||||
return errJson
|
||||
}
|
||||
// We have to add the prefix after handling parameters because adding the prefix changes URL segment indexing.
|
||||
@ -139,16 +143,16 @@ func prepareSSZRequestForProxying(m *gateway.ApiProxyMiddleware, endpoint gatewa
|
||||
return nil
|
||||
}
|
||||
|
||||
func serializeMiddlewareResponseIntoSSZ(data string) (sszResponse []byte, errJson gateway.ErrorJson) {
|
||||
func serializeMiddlewareResponseIntoSSZ(data string) (sszResponse []byte, errJson apimiddleware.ErrorJson) {
|
||||
// Serialize the SSZ part of the deserialized value.
|
||||
b, err := base64.StdEncoding.DecodeString(data)
|
||||
if err != nil {
|
||||
return nil, gateway.InternalServerErrorWithMessage(err, "could not decode response body into base64")
|
||||
return nil, apimiddleware.InternalServerErrorWithMessage(err, "could not decode response body into base64")
|
||||
}
|
||||
return b, nil
|
||||
}
|
||||
|
||||
func writeSSZResponseHeaderAndBody(grpcResp *http.Response, w http.ResponseWriter, responseSsz []byte, fileName string) gateway.ErrorJson {
|
||||
func writeSSZResponseHeaderAndBody(grpcResp *http.Response, w http.ResponseWriter, responseSsz []byte, fileName string) apimiddleware.ErrorJson {
|
||||
var statusCodeHeader string
|
||||
for h, vs := range grpcResp.Header {
|
||||
// We don't want to expose any gRPC metadata in the HTTP response, so we skip forwarding metadata headers.
|
||||
@ -165,7 +169,7 @@ func writeSSZResponseHeaderAndBody(grpcResp *http.Response, w http.ResponseWrite
|
||||
if statusCodeHeader != "" {
|
||||
code, err := strconv.Atoi(statusCodeHeader)
|
||||
if err != nil {
|
||||
return gateway.InternalServerErrorWithMessage(err, "could not parse status code")
|
||||
return apimiddleware.InternalServerErrorWithMessage(err, "could not parse status code")
|
||||
}
|
||||
w.WriteHeader(code)
|
||||
} else {
|
||||
@ -175,12 +179,12 @@ func writeSSZResponseHeaderAndBody(grpcResp *http.Response, w http.ResponseWrite
|
||||
w.Header().Set("Content-Type", "application/octet-stream")
|
||||
w.Header().Set("Content-Disposition", "attachment; filename="+fileName)
|
||||
if _, err := io.Copy(w, ioutil.NopCloser(bytes.NewReader(responseSsz))); err != nil {
|
||||
return gateway.InternalServerErrorWithMessage(err, "could not write response message")
|
||||
return apimiddleware.InternalServerErrorWithMessage(err, "could not write response message")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func handleEvents(m *gateway.ApiProxyMiddleware, _ gateway.Endpoint, w http.ResponseWriter, req *http.Request) (handled bool) {
|
||||
func handleEvents(m *apimiddleware.ApiProxyMiddleware, _ apimiddleware.Endpoint, w http.ResponseWriter, req *http.Request) (handled bool) {
|
||||
sseClient := sse.NewClient("http://" + m.GatewayAddress + "/internal" + req.URL.RequestURI())
|
||||
eventChan := make(chan *sse.Event)
|
||||
|
||||
@ -188,21 +192,21 @@ func handleEvents(m *gateway.ApiProxyMiddleware, _ gateway.Endpoint, w http.Resp
|
||||
// Because of this subscribing to streams doesn't work as intended, resulting in each event being handled by all subscriptions.
|
||||
// To handle events properly, we subscribe just once using a placeholder value ('events') and handle all topics inside this subscription.
|
||||
if err := sseClient.SubscribeChan("events", eventChan); err != nil {
|
||||
gateway.WriteError(w, gateway.InternalServerError(err), nil)
|
||||
apimiddleware.WriteError(w, apimiddleware.InternalServerError(err), nil)
|
||||
sseClient.Unsubscribe(eventChan)
|
||||
return
|
||||
}
|
||||
|
||||
errJson := receiveEvents(eventChan, w, req)
|
||||
if errJson != nil {
|
||||
gateway.WriteError(w, errJson, nil)
|
||||
apimiddleware.WriteError(w, errJson, nil)
|
||||
}
|
||||
|
||||
sseClient.Unsubscribe(eventChan)
|
||||
return true
|
||||
}
|
||||
|
||||
func receiveEvents(eventChan <-chan *sse.Event, w http.ResponseWriter, req *http.Request) gateway.ErrorJson {
|
||||
func receiveEvents(eventChan <-chan *sse.Event, w http.ResponseWriter, req *http.Request) apimiddleware.ErrorJson {
|
||||
for {
|
||||
select {
|
||||
case msg := <-eventChan:
|
||||
@ -225,11 +229,11 @@ func receiveEvents(eventChan <-chan *sse.Event, w http.ResponseWriter, req *http
|
||||
// and assign the attestation back to event data for further processing.
|
||||
eventData := &aggregatedAttReceivedDataJson{}
|
||||
if err := json.Unmarshal(msg.Data, eventData); err != nil {
|
||||
return gateway.InternalServerError(err)
|
||||
return apimiddleware.InternalServerError(err)
|
||||
}
|
||||
attData, err := json.Marshal(eventData.Aggregate)
|
||||
if err != nil {
|
||||
return gateway.InternalServerError(err)
|
||||
return apimiddleware.InternalServerError(err)
|
||||
}
|
||||
msg.Data = attData
|
||||
case events.VoluntaryExitTopic:
|
||||
@ -241,7 +245,7 @@ func receiveEvents(eventChan <-chan *sse.Event, w http.ResponseWriter, req *http
|
||||
case "error":
|
||||
data = &eventErrorJson{}
|
||||
default:
|
||||
return &gateway.DefaultErrorJson{
|
||||
return &apimiddleware.DefaultErrorJson{
|
||||
Message: fmt.Sprintf("Event type '%s' not supported", string(msg.Event)),
|
||||
Code: http.StatusInternalServerError,
|
||||
}
|
||||
@ -259,14 +263,14 @@ func receiveEvents(eventChan <-chan *sse.Event, w http.ResponseWriter, req *http
|
||||
}
|
||||
}
|
||||
|
||||
func writeEvent(msg *sse.Event, w http.ResponseWriter, data interface{}) gateway.ErrorJson {
|
||||
func writeEvent(msg *sse.Event, w http.ResponseWriter, data interface{}) apimiddleware.ErrorJson {
|
||||
if err := json.Unmarshal(msg.Data, data); err != nil {
|
||||
return gateway.InternalServerError(err)
|
||||
return apimiddleware.InternalServerError(err)
|
||||
}
|
||||
if errJson := gateway.ProcessMiddlewareResponseFields(data); errJson != nil {
|
||||
if errJson := apimiddleware.ProcessMiddlewareResponseFields(data); errJson != nil {
|
||||
return errJson
|
||||
}
|
||||
dataJson, errJson := gateway.SerializeMiddlewareResponseIntoJson(data)
|
||||
dataJson, errJson := apimiddleware.SerializeMiddlewareResponseIntoJson(data)
|
||||
if errJson != nil {
|
||||
return errJson
|
||||
}
|
||||
@ -274,28 +278,28 @@ func writeEvent(msg *sse.Event, w http.ResponseWriter, data interface{}) gateway
|
||||
w.Header().Set("Content-Type", "text/event-stream")
|
||||
|
||||
if _, err := w.Write([]byte("event: ")); err != nil {
|
||||
return gateway.InternalServerError(err)
|
||||
return apimiddleware.InternalServerError(err)
|
||||
}
|
||||
if _, err := w.Write(msg.Event); err != nil {
|
||||
return gateway.InternalServerError(err)
|
||||
return apimiddleware.InternalServerError(err)
|
||||
}
|
||||
if _, err := w.Write([]byte("\ndata: ")); err != nil {
|
||||
return gateway.InternalServerError(err)
|
||||
return apimiddleware.InternalServerError(err)
|
||||
}
|
||||
if _, err := w.Write(dataJson); err != nil {
|
||||
return gateway.InternalServerError(err)
|
||||
return apimiddleware.InternalServerError(err)
|
||||
}
|
||||
if _, err := w.Write([]byte("\n\n")); err != nil {
|
||||
return gateway.InternalServerError(err)
|
||||
return apimiddleware.InternalServerError(err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func flushEvent(w http.ResponseWriter) gateway.ErrorJson {
|
||||
func flushEvent(w http.ResponseWriter) apimiddleware.ErrorJson {
|
||||
flusher, ok := w.(http.Flusher)
|
||||
if !ok {
|
||||
return &gateway.DefaultErrorJson{Message: fmt.Sprintf("Flush not supported in %T", w), Code: http.StatusInternalServerError}
|
||||
return &apimiddleware.DefaultErrorJson{Message: fmt.Sprintf("Flush not supported in %T", w), Code: http.StatusInternalServerError}
|
||||
}
|
||||
flusher.Flush()
|
||||
return nil
|
||||
|
@ -10,7 +10,7 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/api/gateway"
|
||||
"github.com/prysmaticlabs/prysm/api/gateway/apimiddleware"
|
||||
"github.com/prysmaticlabs/prysm/api/grpc"
|
||||
"github.com/prysmaticlabs/prysm/beacon-chain/rpc/eth/events"
|
||||
"github.com/prysmaticlabs/prysm/testing/assert"
|
||||
@ -48,10 +48,10 @@ func TestSSZRequested(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestPrepareSSZRequestForProxying(t *testing.T) {
|
||||
middleware := &gateway.ApiProxyMiddleware{
|
||||
GatewayAddress: "http://gateway.example",
|
||||
middleware := &apimiddleware.ApiProxyMiddleware{
|
||||
GatewayAddress: "http://apimiddleware.example",
|
||||
}
|
||||
endpoint := gateway.Endpoint{
|
||||
endpoint := apimiddleware.Endpoint{
|
||||
Path: "http://foo.example",
|
||||
}
|
||||
var body bytes.Buffer
|
||||
|
@ -9,23 +9,23 @@ import (
|
||||
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/api/gateway"
|
||||
"github.com/prysmaticlabs/prysm/api/gateway/apimiddleware"
|
||||
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
|
||||
ethpbv2 "github.com/prysmaticlabs/prysm/proto/eth/v2"
|
||||
)
|
||||
|
||||
// https://ethereum.github.io/beacon-apis/#/Beacon/submitPoolAttestations expects posting a top-level array.
|
||||
// We make it more proto-friendly by wrapping it in a struct with a 'data' field.
|
||||
func wrapAttestationsArray(endpoint gateway.Endpoint, _ http.ResponseWriter, req *http.Request) gateway.ErrorJson {
|
||||
func wrapAttestationsArray(endpoint apimiddleware.Endpoint, _ http.ResponseWriter, req *http.Request) apimiddleware.ErrorJson {
|
||||
if _, ok := endpoint.PostRequest.(*submitAttestationRequestJson); ok {
|
||||
atts := make([]*attestationJson, 0)
|
||||
if err := json.NewDecoder(req.Body).Decode(&atts); err != nil {
|
||||
return gateway.InternalServerErrorWithMessage(err, "could not decode body")
|
||||
return apimiddleware.InternalServerErrorWithMessage(err, "could not decode body")
|
||||
}
|
||||
j := &submitAttestationRequestJson{Data: atts}
|
||||
b, err := json.Marshal(j)
|
||||
if err != nil {
|
||||
return gateway.InternalServerErrorWithMessage(err, "could not marshal wrapped body")
|
||||
return apimiddleware.InternalServerErrorWithMessage(err, "could not marshal wrapped body")
|
||||
}
|
||||
req.Body = ioutil.NopCloser(bytes.NewReader(b))
|
||||
}
|
||||
@ -34,16 +34,16 @@ func wrapAttestationsArray(endpoint gateway.Endpoint, _ http.ResponseWriter, req
|
||||
|
||||
// Some endpoints e.g. https://ethereum.github.io/beacon-apis/#/Validator/getAttesterDuties expect posting a top-level array.
|
||||
// We make it more proto-friendly by wrapping it in a struct with an 'Index' field.
|
||||
func wrapValidatorIndicesArray(endpoint gateway.Endpoint, _ http.ResponseWriter, req *http.Request) gateway.ErrorJson {
|
||||
func wrapValidatorIndicesArray(endpoint apimiddleware.Endpoint, _ http.ResponseWriter, req *http.Request) apimiddleware.ErrorJson {
|
||||
if _, ok := endpoint.PostRequest.(*dutiesRequestJson); ok {
|
||||
indices := make([]string, 0)
|
||||
if err := json.NewDecoder(req.Body).Decode(&indices); err != nil {
|
||||
return gateway.InternalServerErrorWithMessage(err, "could not decode body")
|
||||
return apimiddleware.InternalServerErrorWithMessage(err, "could not decode body")
|
||||
}
|
||||
j := &dutiesRequestJson{Index: indices}
|
||||
b, err := json.Marshal(j)
|
||||
if err != nil {
|
||||
return gateway.InternalServerErrorWithMessage(err, "could not marshal wrapped body")
|
||||
return apimiddleware.InternalServerErrorWithMessage(err, "could not marshal wrapped body")
|
||||
}
|
||||
req.Body = ioutil.NopCloser(bytes.NewReader(b))
|
||||
}
|
||||
@ -52,16 +52,16 @@ func wrapValidatorIndicesArray(endpoint gateway.Endpoint, _ http.ResponseWriter,
|
||||
|
||||
// https://ethereum.github.io/beacon-apis/#/Validator/publishAggregateAndProofs expects posting a top-level array.
|
||||
// We make it more proto-friendly by wrapping it in a struct with a 'data' field.
|
||||
func wrapSignedAggregateAndProofArray(endpoint gateway.Endpoint, _ http.ResponseWriter, req *http.Request) gateway.ErrorJson {
|
||||
func wrapSignedAggregateAndProofArray(endpoint apimiddleware.Endpoint, _ http.ResponseWriter, req *http.Request) apimiddleware.ErrorJson {
|
||||
if _, ok := endpoint.PostRequest.(*submitAggregateAndProofsRequestJson); ok {
|
||||
data := make([]*signedAggregateAttestationAndProofJson, 0)
|
||||
if err := json.NewDecoder(req.Body).Decode(&data); err != nil {
|
||||
return gateway.InternalServerErrorWithMessage(err, "could not decode body")
|
||||
return apimiddleware.InternalServerErrorWithMessage(err, "could not decode body")
|
||||
}
|
||||
j := &submitAggregateAndProofsRequestJson{Data: data}
|
||||
b, err := json.Marshal(j)
|
||||
if err != nil {
|
||||
return gateway.InternalServerErrorWithMessage(err, "could not marshal wrapped body")
|
||||
return apimiddleware.InternalServerErrorWithMessage(err, "could not marshal wrapped body")
|
||||
}
|
||||
req.Body = ioutil.NopCloser(bytes.NewReader(b))
|
||||
}
|
||||
@ -70,16 +70,16 @@ func wrapSignedAggregateAndProofArray(endpoint gateway.Endpoint, _ http.Response
|
||||
|
||||
// https://ethereum.github.io/beacon-apis/#/Validator/prepareBeaconCommitteeSubnet expects posting a top-level array.
|
||||
// We make it more proto-friendly by wrapping it in a struct with a 'data' field.
|
||||
func wrapBeaconCommitteeSubscriptionsArray(endpoint gateway.Endpoint, _ http.ResponseWriter, req *http.Request) gateway.ErrorJson {
|
||||
func wrapBeaconCommitteeSubscriptionsArray(endpoint apimiddleware.Endpoint, _ http.ResponseWriter, req *http.Request) apimiddleware.ErrorJson {
|
||||
if _, ok := endpoint.PostRequest.(*submitBeaconCommitteeSubscriptionsRequestJson); ok {
|
||||
data := make([]*beaconCommitteeSubscribeJson, 0)
|
||||
if err := json.NewDecoder(req.Body).Decode(&data); err != nil {
|
||||
return gateway.InternalServerErrorWithMessage(err, "could not decode body")
|
||||
return apimiddleware.InternalServerErrorWithMessage(err, "could not decode body")
|
||||
}
|
||||
j := &submitBeaconCommitteeSubscriptionsRequestJson{Data: data}
|
||||
b, err := json.Marshal(j)
|
||||
if err != nil {
|
||||
return gateway.InternalServerErrorWithMessage(err, "could not marshal wrapped body")
|
||||
return apimiddleware.InternalServerErrorWithMessage(err, "could not marshal wrapped body")
|
||||
}
|
||||
req.Body = ioutil.NopCloser(bytes.NewReader(b))
|
||||
}
|
||||
@ -88,16 +88,16 @@ func wrapBeaconCommitteeSubscriptionsArray(endpoint gateway.Endpoint, _ http.Res
|
||||
|
||||
// https://ethereum.github.io/beacon-APIs/#/Validator/prepareSyncCommitteeSubnets expects posting a top-level array.
|
||||
// We make it more proto-friendly by wrapping it in a struct with a 'data' field.
|
||||
func wrapSyncCommitteeSubscriptionsArray(endpoint gateway.Endpoint, _ http.ResponseWriter, req *http.Request) gateway.ErrorJson {
|
||||
func wrapSyncCommitteeSubscriptionsArray(endpoint apimiddleware.Endpoint, _ http.ResponseWriter, req *http.Request) apimiddleware.ErrorJson {
|
||||
if _, ok := endpoint.PostRequest.(*submitSyncCommitteeSubscriptionRequestJson); ok {
|
||||
data := make([]*syncCommitteeSubscriptionJson, 0)
|
||||
if err := json.NewDecoder(req.Body).Decode(&data); err != nil {
|
||||
return gateway.InternalServerErrorWithMessage(err, "could not decode body")
|
||||
return apimiddleware.InternalServerErrorWithMessage(err, "could not decode body")
|
||||
}
|
||||
j := &submitSyncCommitteeSubscriptionRequestJson{Data: data}
|
||||
b, err := json.Marshal(j)
|
||||
if err != nil {
|
||||
return gateway.InternalServerErrorWithMessage(err, "could not marshal wrapped body")
|
||||
return apimiddleware.InternalServerErrorWithMessage(err, "could not marshal wrapped body")
|
||||
}
|
||||
req.Body = ioutil.NopCloser(bytes.NewReader(b))
|
||||
}
|
||||
@ -106,16 +106,16 @@ func wrapSyncCommitteeSubscriptionsArray(endpoint gateway.Endpoint, _ http.Respo
|
||||
|
||||
// https://ethereum.github.io/beacon-APIs/#/Beacon/submitPoolSyncCommitteeSignatures expects posting a top-level array.
|
||||
// We make it more proto-friendly by wrapping it in a struct with a 'data' field.
|
||||
func wrapSyncCommitteeSignaturesArray(endpoint gateway.Endpoint, _ http.ResponseWriter, req *http.Request) gateway.ErrorJson {
|
||||
func wrapSyncCommitteeSignaturesArray(endpoint apimiddleware.Endpoint, _ http.ResponseWriter, req *http.Request) apimiddleware.ErrorJson {
|
||||
if _, ok := endpoint.PostRequest.(*submitSyncCommitteeSignaturesRequestJson); ok {
|
||||
data := make([]*syncCommitteeMessageJson, 0)
|
||||
if err := json.NewDecoder(req.Body).Decode(&data); err != nil {
|
||||
return gateway.InternalServerErrorWithMessage(err, "could not decode body")
|
||||
return apimiddleware.InternalServerErrorWithMessage(err, "could not decode body")
|
||||
}
|
||||
j := &submitSyncCommitteeSignaturesRequestJson{Data: data}
|
||||
b, err := json.Marshal(j)
|
||||
if err != nil {
|
||||
return gateway.InternalServerErrorWithMessage(err, "could not marshal wrapped body")
|
||||
return apimiddleware.InternalServerErrorWithMessage(err, "could not marshal wrapped body")
|
||||
}
|
||||
req.Body = ioutil.NopCloser(bytes.NewReader(b))
|
||||
}
|
||||
@ -124,16 +124,16 @@ func wrapSyncCommitteeSignaturesArray(endpoint gateway.Endpoint, _ http.Response
|
||||
|
||||
// https://ethereum.github.io/beacon-APIs/#/Validator/publishContributionAndProofs expects posting a top-level array.
|
||||
// We make it more proto-friendly by wrapping it in a struct with a 'data' field.
|
||||
func wrapSignedContributionAndProofsArray(endpoint gateway.Endpoint, _ http.ResponseWriter, req *http.Request) gateway.ErrorJson {
|
||||
func wrapSignedContributionAndProofsArray(endpoint apimiddleware.Endpoint, _ http.ResponseWriter, req *http.Request) apimiddleware.ErrorJson {
|
||||
if _, ok := endpoint.PostRequest.(*submitContributionAndProofsRequestJson); ok {
|
||||
data := make([]*signedContributionAndProofJson, 0)
|
||||
if err := json.NewDecoder(req.Body).Decode(&data); err != nil {
|
||||
return gateway.InternalServerErrorWithMessage(err, "could not decode body")
|
||||
return apimiddleware.InternalServerErrorWithMessage(err, "could not decode body")
|
||||
}
|
||||
j := &submitContributionAndProofsRequestJson{Data: data}
|
||||
b, err := json.Marshal(j)
|
||||
if err != nil {
|
||||
return gateway.InternalServerErrorWithMessage(err, "could not marshal wrapped body")
|
||||
return apimiddleware.InternalServerErrorWithMessage(err, "could not marshal wrapped body")
|
||||
}
|
||||
req.Body = ioutil.NopCloser(bytes.NewReader(b))
|
||||
}
|
||||
@ -141,7 +141,7 @@ func wrapSignedContributionAndProofsArray(endpoint gateway.Endpoint, _ http.Resp
|
||||
}
|
||||
|
||||
// Posted graffiti needs to have length of 32 bytes, but client is allowed to send data of any length.
|
||||
func prepareGraffiti(endpoint gateway.Endpoint, _ http.ResponseWriter, _ *http.Request) gateway.ErrorJson {
|
||||
func prepareGraffiti(endpoint apimiddleware.Endpoint, _ http.ResponseWriter, _ *http.Request) apimiddleware.ErrorJson {
|
||||
if block, ok := endpoint.PostRequest.(*signedBeaconBlockContainerJson); ok {
|
||||
b := bytesutil.ToBytes32([]byte(block.Message.Body.Graffiti))
|
||||
block.Message.Body.Graffiti = hexutil.Encode(b[:])
|
||||
@ -164,14 +164,14 @@ type tempSyncSubcommitteeValidatorsJson struct {
|
||||
|
||||
// https://ethereum.github.io/beacon-APIs/?urls.primaryName=v2.0.0#/Beacon/getEpochSyncCommittees returns validator_aggregates as a nested array.
|
||||
// grpc-gateway returns a struct with nested fields which we have to transform into a plain 2D array.
|
||||
func prepareValidatorAggregates(body []byte, responseContainer interface{}) (bool, gateway.ErrorJson) {
|
||||
func prepareValidatorAggregates(body []byte, responseContainer interface{}) (bool, apimiddleware.ErrorJson) {
|
||||
tempContainer := &tempSyncCommitteesResponseJson{}
|
||||
if err := json.Unmarshal(body, tempContainer); err != nil {
|
||||
return false, gateway.InternalServerErrorWithMessage(err, "could not unmarshal response into temp container")
|
||||
return false, apimiddleware.InternalServerErrorWithMessage(err, "could not unmarshal response into temp container")
|
||||
}
|
||||
container, ok := responseContainer.(*syncCommitteesResponseJson)
|
||||
if !ok {
|
||||
return false, gateway.InternalServerError(errors.New("container is not of the correct type"))
|
||||
return false, apimiddleware.InternalServerError(errors.New("container is not of the correct type"))
|
||||
}
|
||||
|
||||
container.Data = &syncCommitteeValidatorsJson{}
|
||||
@ -196,10 +196,10 @@ type altairBlockResponseJson struct {
|
||||
Data *signedBeaconBlockAltairContainerJson `json:"data"`
|
||||
}
|
||||
|
||||
func serializeV2Block(response interface{}) (bool, []byte, gateway.ErrorJson) {
|
||||
func serializeV2Block(response interface{}) (bool, []byte, apimiddleware.ErrorJson) {
|
||||
respContainer, ok := response.(*blockV2ResponseJson)
|
||||
if !ok {
|
||||
return false, nil, gateway.InternalServerError(errors.New("container is not of the correct type"))
|
||||
return false, nil, apimiddleware.InternalServerError(errors.New("container is not of the correct type"))
|
||||
}
|
||||
|
||||
var actualRespContainer interface{}
|
||||
@ -223,7 +223,7 @@ func serializeV2Block(response interface{}) (bool, []byte, gateway.ErrorJson) {
|
||||
|
||||
j, err := json.Marshal(actualRespContainer)
|
||||
if err != nil {
|
||||
return false, nil, gateway.InternalServerErrorWithMessage(err, "could not marshal response")
|
||||
return false, nil, apimiddleware.InternalServerErrorWithMessage(err, "could not marshal response")
|
||||
}
|
||||
return true, j, nil
|
||||
}
|
||||
@ -238,10 +238,10 @@ type altairStateResponseJson struct {
|
||||
Data *beaconStateV2Json `json:"data"`
|
||||
}
|
||||
|
||||
func serializeV2State(response interface{}) (bool, []byte, gateway.ErrorJson) {
|
||||
func serializeV2State(response interface{}) (bool, []byte, apimiddleware.ErrorJson) {
|
||||
respContainer, ok := response.(*beaconStateV2ResponseJson)
|
||||
if !ok {
|
||||
return false, nil, gateway.InternalServerError(errors.New("container is not of the correct type"))
|
||||
return false, nil, apimiddleware.InternalServerError(errors.New("container is not of the correct type"))
|
||||
}
|
||||
|
||||
var actualRespContainer interface{}
|
||||
@ -259,7 +259,7 @@ func serializeV2State(response interface{}) (bool, []byte, gateway.ErrorJson) {
|
||||
|
||||
j, err := json.Marshal(actualRespContainer)
|
||||
if err != nil {
|
||||
return false, nil, gateway.InternalServerErrorWithMessage(err, "could not marshal response")
|
||||
return false, nil, apimiddleware.InternalServerErrorWithMessage(err, "could not marshal response")
|
||||
}
|
||||
return true, j, nil
|
||||
}
|
||||
@ -274,10 +274,10 @@ type altairProduceBlockResponseJson struct {
|
||||
Data *beaconBlockAltairJson `json:"data"`
|
||||
}
|
||||
|
||||
func serializeProducedV2Block(response interface{}) (bool, []byte, gateway.ErrorJson) {
|
||||
func serializeProducedV2Block(response interface{}) (bool, []byte, apimiddleware.ErrorJson) {
|
||||
respContainer, ok := response.(*produceBlockResponseV2Json)
|
||||
if !ok {
|
||||
return false, nil, gateway.InternalServerError(errors.New("container is not of the correct type"))
|
||||
return false, nil, apimiddleware.InternalServerError(errors.New("container is not of the correct type"))
|
||||
}
|
||||
|
||||
var actualRespContainer interface{}
|
||||
@ -295,7 +295,7 @@ func serializeProducedV2Block(response interface{}) (bool, []byte, gateway.Error
|
||||
|
||||
j, err := json.Marshal(actualRespContainer)
|
||||
if err != nil {
|
||||
return false, nil, gateway.InternalServerErrorWithMessage(err, "could not marshal response")
|
||||
return false, nil, apimiddleware.InternalServerErrorWithMessage(err, "could not marshal response")
|
||||
}
|
||||
return true, j, nil
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/gogo/protobuf/types"
|
||||
"github.com/prysmaticlabs/prysm/api/gateway"
|
||||
"github.com/prysmaticlabs/prysm/api/gateway/apimiddleware"
|
||||
"github.com/prysmaticlabs/prysm/encoding/bytesutil"
|
||||
ethpbv2 "github.com/prysmaticlabs/prysm/proto/eth/v2"
|
||||
"github.com/prysmaticlabs/prysm/testing/assert"
|
||||
@ -18,7 +18,7 @@ import (
|
||||
|
||||
func TestWrapAttestationArray(t *testing.T) {
|
||||
t.Run("ok", func(t *testing.T) {
|
||||
endpoint := gateway.Endpoint{
|
||||
endpoint := apimiddleware.Endpoint{
|
||||
PostRequest: &submitAttestationRequestJson{},
|
||||
}
|
||||
unwrappedAtts := []*attestationJson{{AggregationBits: "1010"}}
|
||||
@ -39,7 +39,7 @@ func TestWrapAttestationArray(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("invalid_body", func(t *testing.T) {
|
||||
endpoint := gateway.Endpoint{
|
||||
endpoint := apimiddleware.Endpoint{
|
||||
PostRequest: &submitAttestationRequestJson{},
|
||||
}
|
||||
var body bytes.Buffer
|
||||
@ -56,7 +56,7 @@ func TestWrapAttestationArray(t *testing.T) {
|
||||
|
||||
func TestWrapValidatorIndicesArray(t *testing.T) {
|
||||
t.Run("ok", func(t *testing.T) {
|
||||
endpoint := gateway.Endpoint{
|
||||
endpoint := apimiddleware.Endpoint{
|
||||
PostRequest: &dutiesRequestJson{},
|
||||
}
|
||||
unwrappedIndices := []string{"1", "2"}
|
||||
@ -80,7 +80,7 @@ func TestWrapValidatorIndicesArray(t *testing.T) {
|
||||
|
||||
func TestWrapSignedAggregateAndProofArray(t *testing.T) {
|
||||
t.Run("ok", func(t *testing.T) {
|
||||
endpoint := gateway.Endpoint{
|
||||
endpoint := apimiddleware.Endpoint{
|
||||
PostRequest: &submitAggregateAndProofsRequestJson{},
|
||||
}
|
||||
unwrappedAggs := []*signedAggregateAttestationAndProofJson{{Signature: "sig"}}
|
||||
@ -101,7 +101,7 @@ func TestWrapSignedAggregateAndProofArray(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("invalid_body", func(t *testing.T) {
|
||||
endpoint := gateway.Endpoint{
|
||||
endpoint := apimiddleware.Endpoint{
|
||||
PostRequest: &submitAggregateAndProofsRequestJson{},
|
||||
}
|
||||
var body bytes.Buffer
|
||||
@ -118,7 +118,7 @@ func TestWrapSignedAggregateAndProofArray(t *testing.T) {
|
||||
|
||||
func TestWrapBeaconCommitteeSubscriptionsArray(t *testing.T) {
|
||||
t.Run("ok", func(t *testing.T) {
|
||||
endpoint := gateway.Endpoint{
|
||||
endpoint := apimiddleware.Endpoint{
|
||||
PostRequest: &submitBeaconCommitteeSubscriptionsRequestJson{},
|
||||
}
|
||||
unwrappedSubs := []*beaconCommitteeSubscribeJson{{
|
||||
@ -149,7 +149,7 @@ func TestWrapBeaconCommitteeSubscriptionsArray(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("invalid_body", func(t *testing.T) {
|
||||
endpoint := gateway.Endpoint{
|
||||
endpoint := apimiddleware.Endpoint{
|
||||
PostRequest: &submitBeaconCommitteeSubscriptionsRequestJson{},
|
||||
}
|
||||
var body bytes.Buffer
|
||||
@ -166,7 +166,7 @@ func TestWrapBeaconCommitteeSubscriptionsArray(t *testing.T) {
|
||||
|
||||
func TestWrapSyncCommitteeSubscriptionsArray(t *testing.T) {
|
||||
t.Run("ok", func(t *testing.T) {
|
||||
endpoint := gateway.Endpoint{
|
||||
endpoint := apimiddleware.Endpoint{
|
||||
PostRequest: &submitSyncCommitteeSubscriptionRequestJson{},
|
||||
}
|
||||
unwrappedSubs := []*syncCommitteeSubscriptionJson{
|
||||
@ -202,7 +202,7 @@ func TestWrapSyncCommitteeSubscriptionsArray(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("invalid_body", func(t *testing.T) {
|
||||
endpoint := gateway.Endpoint{
|
||||
endpoint := apimiddleware.Endpoint{
|
||||
PostRequest: &submitSyncCommitteeSubscriptionRequestJson{},
|
||||
}
|
||||
var body bytes.Buffer
|
||||
@ -219,7 +219,7 @@ func TestWrapSyncCommitteeSubscriptionsArray(t *testing.T) {
|
||||
|
||||
func TestWrapSyncCommitteeSignaturesArray(t *testing.T) {
|
||||
t.Run("ok", func(t *testing.T) {
|
||||
endpoint := gateway.Endpoint{
|
||||
endpoint := apimiddleware.Endpoint{
|
||||
PostRequest: &submitSyncCommitteeSignaturesRequestJson{},
|
||||
}
|
||||
unwrappedSigs := []*syncCommitteeMessageJson{{
|
||||
@ -248,7 +248,7 @@ func TestWrapSyncCommitteeSignaturesArray(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("invalid_body", func(t *testing.T) {
|
||||
endpoint := gateway.Endpoint{
|
||||
endpoint := apimiddleware.Endpoint{
|
||||
PostRequest: &submitSyncCommitteeSignaturesRequestJson{},
|
||||
}
|
||||
var body bytes.Buffer
|
||||
@ -265,7 +265,7 @@ func TestWrapSyncCommitteeSignaturesArray(t *testing.T) {
|
||||
|
||||
func TestWrapSignedContributionAndProofsArray(t *testing.T) {
|
||||
t.Run("ok", func(t *testing.T) {
|
||||
endpoint := gateway.Endpoint{
|
||||
endpoint := apimiddleware.Endpoint{
|
||||
PostRequest: &submitContributionAndProofsRequestJson{},
|
||||
}
|
||||
unwrapped := []*signedContributionAndProofJson{
|
||||
@ -315,7 +315,7 @@ func TestWrapSignedContributionAndProofsArray(t *testing.T) {
|
||||
})
|
||||
|
||||
t.Run("invalid_body", func(t *testing.T) {
|
||||
endpoint := gateway.Endpoint{
|
||||
endpoint := apimiddleware.Endpoint{
|
||||
PostRequest: &submitContributionAndProofsRequestJson{},
|
||||
}
|
||||
var body bytes.Buffer
|
||||
@ -331,7 +331,7 @@ func TestWrapSignedContributionAndProofsArray(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestPrepareGraffiti(t *testing.T) {
|
||||
endpoint := gateway.Endpoint{
|
||||
endpoint := apimiddleware.Endpoint{
|
||||
PostRequest: &signedBeaconBlockContainerJson{
|
||||
Message: &beaconBlockJson{
|
||||
Body: &beaconBlockBodyJson{},
|
||||
|
@ -2,7 +2,7 @@ package apimiddleware
|
||||
|
||||
import (
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/api/gateway"
|
||||
"github.com/prysmaticlabs/prysm/api/gateway/apimiddleware"
|
||||
)
|
||||
|
||||
// BeaconEndpointFactory creates endpoints used for running beacon chain API calls through the API Middleware.
|
||||
@ -67,8 +67,8 @@ func (f *BeaconEndpointFactory) Paths() []string {
|
||||
}
|
||||
|
||||
// Create returns a new endpoint for the provided API path.
|
||||
func (f *BeaconEndpointFactory) Create(path string) (*gateway.Endpoint, error) {
|
||||
endpoint := gateway.DefaultEndpoint()
|
||||
func (f *BeaconEndpointFactory) Create(path string) (*apimiddleware.Endpoint, error) {
|
||||
endpoint := apimiddleware.DefaultEndpoint()
|
||||
switch path {
|
||||
case "/eth/v1/beacon/genesis":
|
||||
endpoint.GetResponse = &genesisResponseJson{}
|
||||
@ -79,52 +79,52 @@ func (f *BeaconEndpointFactory) Create(path string) (*gateway.Endpoint, error) {
|
||||
case "/eth/v1/beacon/states/{state_id}/finality_checkpoints":
|
||||
endpoint.GetResponse = &stateFinalityCheckpointResponseJson{}
|
||||
case "/eth/v1/beacon/states/{state_id}/validators":
|
||||
endpoint.RequestQueryParams = []gateway.QueryParam{{Name: "id", Hex: true}, {Name: "status", Enum: true}}
|
||||
endpoint.RequestQueryParams = []apimiddleware.QueryParam{{Name: "id", Hex: true}, {Name: "status", Enum: true}}
|
||||
endpoint.GetResponse = &stateValidatorsResponseJson{}
|
||||
case "/eth/v1/beacon/states/{state_id}/validators/{validator_id}":
|
||||
endpoint.GetResponse = &stateValidatorResponseJson{}
|
||||
case "/eth/v1/beacon/states/{state_id}/validator_balances":
|
||||
endpoint.RequestQueryParams = []gateway.QueryParam{{Name: "id", Hex: true}}
|
||||
endpoint.RequestQueryParams = []apimiddleware.QueryParam{{Name: "id", Hex: true}}
|
||||
endpoint.GetResponse = &validatorBalancesResponseJson{}
|
||||
case "/eth/v1/beacon/states/{state_id}/committees":
|
||||
endpoint.RequestQueryParams = []gateway.QueryParam{{Name: "epoch"}, {Name: "index"}, {Name: "slot"}}
|
||||
endpoint.RequestQueryParams = []apimiddleware.QueryParam{{Name: "epoch"}, {Name: "index"}, {Name: "slot"}}
|
||||
endpoint.GetResponse = &stateCommitteesResponseJson{}
|
||||
case "/eth/v1/beacon/states/{state_id}/sync_committees":
|
||||
endpoint.RequestQueryParams = []gateway.QueryParam{{Name: "epoch"}}
|
||||
endpoint.RequestQueryParams = []apimiddleware.QueryParam{{Name: "epoch"}}
|
||||
endpoint.GetResponse = &syncCommitteesResponseJson{}
|
||||
endpoint.Hooks = gateway.HookCollection{
|
||||
OnPreDeserializeGrpcResponseBodyIntoContainer: []func([]byte, interface{}) (bool, gateway.ErrorJson){prepareValidatorAggregates},
|
||||
endpoint.Hooks = apimiddleware.HookCollection{
|
||||
OnPreDeserializeGrpcResponseBodyIntoContainer: prepareValidatorAggregates,
|
||||
}
|
||||
case "/eth/v1/beacon/headers":
|
||||
endpoint.RequestQueryParams = []gateway.QueryParam{{Name: "slot"}, {Name: "parent_root", Hex: true}}
|
||||
endpoint.RequestQueryParams = []apimiddleware.QueryParam{{Name: "slot"}, {Name: "parent_root", Hex: true}}
|
||||
endpoint.GetResponse = &blockHeadersResponseJson{}
|
||||
case "/eth/v1/beacon/headers/{block_id}":
|
||||
endpoint.GetResponse = &blockHeaderResponseJson{}
|
||||
case "/eth/v1/beacon/blocks":
|
||||
endpoint.PostRequest = &signedBeaconBlockContainerJson{}
|
||||
endpoint.Hooks = gateway.HookCollection{
|
||||
OnPostDeserializeRequestBodyIntoContainer: []gateway.Hook{prepareGraffiti},
|
||||
endpoint.Hooks = apimiddleware.HookCollection{
|
||||
OnPostDeserializeRequestBodyIntoContainer: prepareGraffiti,
|
||||
}
|
||||
case "/eth/v1/beacon/blocks/{block_id}":
|
||||
endpoint.GetResponse = &blockResponseJson{}
|
||||
endpoint.CustomHandlers = []gateway.CustomHandler{handleGetBeaconBlockSSZ}
|
||||
endpoint.CustomHandlers = []apimiddleware.CustomHandler{handleGetBeaconBlockSSZ}
|
||||
case "/eth/v2/beacon/blocks/{block_id}":
|
||||
endpoint.GetResponse = &blockV2ResponseJson{}
|
||||
endpoint.Hooks = gateway.HookCollection{
|
||||
OnPreSerializeMiddlewareResponseIntoJson: []func(interface{}) (bool, []byte, gateway.ErrorJson){serializeV2Block},
|
||||
endpoint.Hooks = apimiddleware.HookCollection{
|
||||
OnPreSerializeMiddlewareResponseIntoJson: serializeV2Block,
|
||||
}
|
||||
endpoint.CustomHandlers = []gateway.CustomHandler{handleGetBeaconBlockSSZV2}
|
||||
endpoint.CustomHandlers = []apimiddleware.CustomHandler{handleGetBeaconBlockSSZV2}
|
||||
case "/eth/v1/beacon/blocks/{block_id}/root":
|
||||
endpoint.GetResponse = &blockRootResponseJson{}
|
||||
case "/eth/v1/beacon/blocks/{block_id}/attestations":
|
||||
endpoint.GetResponse = &blockAttestationsResponseJson{}
|
||||
case "/eth/v1/beacon/pool/attestations":
|
||||
endpoint.RequestQueryParams = []gateway.QueryParam{{Name: "slot"}, {Name: "committee_index"}}
|
||||
endpoint.RequestQueryParams = []apimiddleware.QueryParam{{Name: "slot"}, {Name: "committee_index"}}
|
||||
endpoint.GetResponse = &attestationsPoolResponseJson{}
|
||||
endpoint.PostRequest = &submitAttestationRequestJson{}
|
||||
endpoint.Err = &indexedVerificationFailureErrorJson{}
|
||||
endpoint.Hooks = gateway.HookCollection{
|
||||
OnPreDeserializeRequestBodyIntoContainer: []gateway.Hook{wrapAttestationsArray},
|
||||
endpoint.Hooks = apimiddleware.HookCollection{
|
||||
OnPreDeserializeRequestBodyIntoContainer: wrapAttestationsArray,
|
||||
}
|
||||
case "/eth/v1/beacon/pool/attester_slashings":
|
||||
endpoint.PostRequest = &attesterSlashingJson{}
|
||||
@ -138,13 +138,13 @@ func (f *BeaconEndpointFactory) Create(path string) (*gateway.Endpoint, error) {
|
||||
case "/eth/v1/beacon/pool/sync_committees":
|
||||
endpoint.PostRequest = &submitSyncCommitteeSignaturesRequestJson{}
|
||||
endpoint.Err = &indexedVerificationFailureErrorJson{}
|
||||
endpoint.Hooks = gateway.HookCollection{
|
||||
OnPreDeserializeRequestBodyIntoContainer: []gateway.Hook{wrapSyncCommitteeSignaturesArray},
|
||||
endpoint.Hooks = apimiddleware.HookCollection{
|
||||
OnPreDeserializeRequestBodyIntoContainer: wrapSyncCommitteeSignaturesArray,
|
||||
}
|
||||
case "/eth/v1/node/identity":
|
||||
endpoint.GetResponse = &identityResponseJson{}
|
||||
case "/eth/v1/node/peers":
|
||||
endpoint.RequestQueryParams = []gateway.QueryParam{{Name: "state", Enum: true}, {Name: "direction", Enum: true}}
|
||||
endpoint.RequestQueryParams = []apimiddleware.QueryParam{{Name: "state", Enum: true}, {Name: "direction", Enum: true}}
|
||||
endpoint.GetResponse = &peersResponseJson{}
|
||||
case "/eth/v1/node/peers/{peer_id}":
|
||||
endpoint.RequestURLLiterals = []string{"peer_id"}
|
||||
@ -159,13 +159,13 @@ func (f *BeaconEndpointFactory) Create(path string) (*gateway.Endpoint, error) {
|
||||
// Use default endpoint
|
||||
case "/eth/v1/debug/beacon/states/{state_id}":
|
||||
endpoint.GetResponse = &beaconStateResponseJson{}
|
||||
endpoint.CustomHandlers = []gateway.CustomHandler{handleGetBeaconStateSSZ}
|
||||
endpoint.CustomHandlers = []apimiddleware.CustomHandler{handleGetBeaconStateSSZ}
|
||||
case "/eth/v2/debug/beacon/states/{state_id}":
|
||||
endpoint.GetResponse = &beaconStateV2ResponseJson{}
|
||||
endpoint.Hooks = gateway.HookCollection{
|
||||
OnPreSerializeMiddlewareResponseIntoJson: []func(interface{}) (bool, []byte, gateway.ErrorJson){serializeV2State},
|
||||
endpoint.Hooks = apimiddleware.HookCollection{
|
||||
OnPreSerializeMiddlewareResponseIntoJson: serializeV2State,
|
||||
}
|
||||
endpoint.CustomHandlers = []gateway.CustomHandler{handleGetBeaconStateSSZV2}
|
||||
endpoint.CustomHandlers = []apimiddleware.CustomHandler{handleGetBeaconStateSSZV2}
|
||||
case "/eth/v1/debug/beacon/heads":
|
||||
endpoint.GetResponse = &forkChoiceHeadsResponseJson{}
|
||||
case "/eth/v1/config/fork_schedule":
|
||||
@ -175,13 +175,13 @@ func (f *BeaconEndpointFactory) Create(path string) (*gateway.Endpoint, error) {
|
||||
case "/eth/v1/config/spec":
|
||||
endpoint.GetResponse = &specResponseJson{}
|
||||
case "/eth/v1/events":
|
||||
endpoint.CustomHandlers = []gateway.CustomHandler{handleEvents}
|
||||
endpoint.CustomHandlers = []apimiddleware.CustomHandler{handleEvents}
|
||||
case "/eth/v1/validator/duties/attester/{epoch}":
|
||||
endpoint.PostRequest = &dutiesRequestJson{}
|
||||
endpoint.PostResponse = &attesterDutiesResponseJson{}
|
||||
endpoint.RequestURLLiterals = []string{"epoch"}
|
||||
endpoint.Hooks = gateway.HookCollection{
|
||||
OnPreDeserializeRequestBodyIntoContainer: []gateway.Hook{wrapValidatorIndicesArray},
|
||||
endpoint.Hooks = apimiddleware.HookCollection{
|
||||
OnPreDeserializeRequestBodyIntoContainer: wrapValidatorIndicesArray,
|
||||
}
|
||||
case "/eth/v1/validator/duties/proposer/{epoch}":
|
||||
endpoint.GetResponse = &proposerDutiesResponseJson{}
|
||||
@ -190,48 +190,48 @@ func (f *BeaconEndpointFactory) Create(path string) (*gateway.Endpoint, error) {
|
||||
endpoint.PostRequest = &dutiesRequestJson{}
|
||||
endpoint.PostResponse = &syncCommitteeDutiesResponseJson{}
|
||||
endpoint.RequestURLLiterals = []string{"epoch"}
|
||||
endpoint.Hooks = gateway.HookCollection{
|
||||
OnPreDeserializeRequestBodyIntoContainer: []gateway.Hook{wrapValidatorIndicesArray},
|
||||
endpoint.Hooks = apimiddleware.HookCollection{
|
||||
OnPreDeserializeRequestBodyIntoContainer: wrapValidatorIndicesArray,
|
||||
}
|
||||
case "/eth/v1/validator/blocks/{slot}":
|
||||
endpoint.GetResponse = &produceBlockResponseJson{}
|
||||
endpoint.RequestURLLiterals = []string{"slot"}
|
||||
endpoint.RequestQueryParams = []gateway.QueryParam{{Name: "randao_reveal", Hex: true}, {Name: "graffiti", Hex: true}}
|
||||
endpoint.RequestQueryParams = []apimiddleware.QueryParam{{Name: "randao_reveal", Hex: true}, {Name: "graffiti", Hex: true}}
|
||||
case "/eth/v2/validator/blocks/{slot}":
|
||||
endpoint.GetResponse = &produceBlockResponseV2Json{}
|
||||
endpoint.RequestURLLiterals = []string{"slot"}
|
||||
endpoint.RequestQueryParams = []gateway.QueryParam{{Name: "randao_reveal", Hex: true}, {Name: "graffiti", Hex: true}}
|
||||
endpoint.Hooks = gateway.HookCollection{
|
||||
OnPreSerializeMiddlewareResponseIntoJson: []func(interface{}) (bool, []byte, gateway.ErrorJson){serializeProducedV2Block},
|
||||
endpoint.RequestQueryParams = []apimiddleware.QueryParam{{Name: "randao_reveal", Hex: true}, {Name: "graffiti", Hex: true}}
|
||||
endpoint.Hooks = apimiddleware.HookCollection{
|
||||
OnPreSerializeMiddlewareResponseIntoJson: serializeProducedV2Block,
|
||||
}
|
||||
case "/eth/v1/validator/attestation_data":
|
||||
endpoint.GetResponse = &produceAttestationDataResponseJson{}
|
||||
endpoint.RequestQueryParams = []gateway.QueryParam{{Name: "slot"}, {Name: "committee_index"}}
|
||||
endpoint.RequestQueryParams = []apimiddleware.QueryParam{{Name: "slot"}, {Name: "committee_index"}}
|
||||
case "/eth/v1/validator/aggregate_attestation":
|
||||
endpoint.GetResponse = &aggregateAttestationResponseJson{}
|
||||
endpoint.RequestQueryParams = []gateway.QueryParam{{Name: "attestation_data_root", Hex: true}, {Name: "slot"}}
|
||||
endpoint.RequestQueryParams = []apimiddleware.QueryParam{{Name: "attestation_data_root", Hex: true}, {Name: "slot"}}
|
||||
case "/eth/v1/validator/beacon_committee_subscriptions":
|
||||
endpoint.PostRequest = &submitBeaconCommitteeSubscriptionsRequestJson{}
|
||||
endpoint.Hooks = gateway.HookCollection{
|
||||
OnPreDeserializeRequestBodyIntoContainer: []gateway.Hook{wrapBeaconCommitteeSubscriptionsArray},
|
||||
endpoint.Hooks = apimiddleware.HookCollection{
|
||||
OnPreDeserializeRequestBodyIntoContainer: wrapBeaconCommitteeSubscriptionsArray,
|
||||
}
|
||||
case "/eth/v1/validator/sync_committee_subscriptions":
|
||||
endpoint.PostRequest = &submitSyncCommitteeSubscriptionRequestJson{}
|
||||
endpoint.Hooks = gateway.HookCollection{
|
||||
OnPreDeserializeRequestBodyIntoContainer: []gateway.Hook{wrapSyncCommitteeSubscriptionsArray},
|
||||
endpoint.Hooks = apimiddleware.HookCollection{
|
||||
OnPreDeserializeRequestBodyIntoContainer: wrapSyncCommitteeSubscriptionsArray,
|
||||
}
|
||||
case "/eth/v1/validator/aggregate_and_proofs":
|
||||
endpoint.PostRequest = &submitAggregateAndProofsRequestJson{}
|
||||
endpoint.Hooks = gateway.HookCollection{
|
||||
OnPreDeserializeRequestBodyIntoContainer: []gateway.Hook{wrapSignedAggregateAndProofArray},
|
||||
endpoint.Hooks = apimiddleware.HookCollection{
|
||||
OnPreDeserializeRequestBodyIntoContainer: wrapSignedAggregateAndProofArray,
|
||||
}
|
||||
case "/eth/v1/validator/sync_committee_contribution":
|
||||
endpoint.GetResponse = &produceSyncCommitteeContributionResponseJson{}
|
||||
endpoint.RequestQueryParams = []gateway.QueryParam{{Name: "slot"}, {Name: "subcommittee_index"}, {Name: "beacon_block_root", Hex: true}}
|
||||
endpoint.RequestQueryParams = []apimiddleware.QueryParam{{Name: "slot"}, {Name: "subcommittee_index"}, {Name: "beacon_block_root", Hex: true}}
|
||||
case "/eth/v1/validator/contribution_and_proofs":
|
||||
endpoint.PostRequest = &submitContributionAndProofsRequestJson{}
|
||||
endpoint.Hooks = gateway.HookCollection{
|
||||
OnPreDeserializeRequestBodyIntoContainer: []gateway.Hook{wrapSignedContributionAndProofsArray},
|
||||
endpoint.Hooks = apimiddleware.HookCollection{
|
||||
OnPreDeserializeRequestBodyIntoContainer: wrapSignedContributionAndProofsArray,
|
||||
}
|
||||
default:
|
||||
return nil, errors.New("invalid path")
|
||||
|
@ -1,6 +1,8 @@
|
||||
package apimiddleware
|
||||
|
||||
import "github.com/prysmaticlabs/prysm/api/gateway"
|
||||
import (
|
||||
"github.com/prysmaticlabs/prysm/api/gateway/apimiddleware"
|
||||
)
|
||||
|
||||
// genesisResponseJson is used in /beacon/genesis API endpoint.
|
||||
type genesisResponseJson struct {
|
||||
@ -739,7 +741,7 @@ type eventChainReorgJson struct {
|
||||
|
||||
// indexedVerificationFailureErrorJson is a JSON representation of the error returned when verifying an indexed object.
|
||||
type indexedVerificationFailureErrorJson struct {
|
||||
gateway.DefaultErrorJson
|
||||
apimiddleware.DefaultErrorJson
|
||||
Failures []*singleIndexedVerificationFailureJson `json:"failures"`
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user