mirror of
https://gitlab.com/pulsechaincom/prysm-pulse.git
synced 2025-01-03 08:37:37 +00:00
d17996f8b0
* Update V3 from V4 * Fix build v3 -> v4 * Update ssz * Update beacon_chain.pb.go * Fix formatter import * Update update-mockgen.sh comment to v4 * Fix conflicts. Pass build and tests * Fix test
104 lines
2.9 KiB
Go
104 lines
2.9 KiB
Go
package apimiddleware
|
|
|
|
import (
|
|
"encoding/base64"
|
|
"net/http"
|
|
"net/url"
|
|
"strings"
|
|
|
|
"github.com/gorilla/mux"
|
|
butil "github.com/prysmaticlabs/prysm/v4/encoding/bytesutil"
|
|
"github.com/wealdtech/go-bytesutil"
|
|
)
|
|
|
|
// HandleURLParameters processes URL parameters, allowing parameterized URLs to be safely and correctly proxied to grpc-gateway.
|
|
func HandleURLParameters(url string, req *http.Request, literals []string) ErrorJson {
|
|
segments := strings.Split(url, "/")
|
|
|
|
segmentsLoop:
|
|
for i, s := range segments {
|
|
// We only care about segments which are parameterized.
|
|
if isRequestParam(s) {
|
|
// Don't do anything with parameters which should be forwarded literally to gRPC.
|
|
for _, l := range literals {
|
|
if s == "{"+l+"}" {
|
|
continue segmentsLoop
|
|
}
|
|
}
|
|
|
|
routeVar := mux.Vars(req)[s[1:len(s)-1]]
|
|
bRouteVar := []byte(routeVar)
|
|
if butil.IsHex(bRouteVar) {
|
|
var err error
|
|
bRouteVar, err = bytesutil.FromHexString(string(bRouteVar))
|
|
if err != nil {
|
|
return InternalServerErrorWithMessage(err, "could not process URL parameter")
|
|
}
|
|
}
|
|
// Converting hex to base64 may result in a value which malforms the URL.
|
|
// We use URLEncoding to safely escape such values.
|
|
base64RouteVar := base64.URLEncoding.EncodeToString(bRouteVar)
|
|
|
|
// Merge segments back into the full URL.
|
|
splitPath := strings.Split(req.URL.Path, "/")
|
|
splitPath[i] = base64RouteVar
|
|
req.URL.Path = strings.Join(splitPath, "/")
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// HandleQueryParameters processes query parameters, allowing them to be safely and correctly proxied to grpc-gateway.
|
|
func HandleQueryParameters(req *http.Request, params []QueryParam) ErrorJson {
|
|
queryParams := req.URL.Query()
|
|
|
|
normalizeQueryValues(queryParams)
|
|
|
|
for key, vals := range queryParams {
|
|
for _, p := range params {
|
|
if key == p.Name {
|
|
if p.Hex {
|
|
queryParams.Del(key)
|
|
for _, v := range vals {
|
|
b := []byte(v)
|
|
if butil.IsHex(b) {
|
|
var err error
|
|
b, err = bytesutil.FromHexString(v)
|
|
if err != nil {
|
|
return InternalServerErrorWithMessage(err, "could not process query parameter")
|
|
}
|
|
}
|
|
queryParams.Add(key, base64.URLEncoding.EncodeToString(b))
|
|
}
|
|
}
|
|
if p.Enum {
|
|
queryParams.Del(key)
|
|
for _, v := range vals {
|
|
// gRPC expects uppercase enum values.
|
|
queryParams.Add(key, strings.ToUpper(v))
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
req.URL.RawQuery = queryParams.Encode()
|
|
return nil
|
|
}
|
|
|
|
// isRequestParam verifies whether the passed string is a request parameter.
|
|
// Request parameters are enclosed in { and }.
|
|
func isRequestParam(s string) bool {
|
|
return len(s) > 2 && s[0] == '{' && s[len(s)-1] == '}'
|
|
}
|
|
|
|
func normalizeQueryValues(queryParams url.Values) {
|
|
// Replace comma-separated values with individual values.
|
|
for key, vals := range queryParams {
|
|
splitVals := make([]string, 0)
|
|
for _, v := range vals {
|
|
splitVals = append(splitVals, strings.Split(v, ",")...)
|
|
}
|
|
queryParams[key] = splitVals
|
|
}
|
|
}
|