code.vegaprotocol.io/vega@v0.79.0/blockexplorer/api/rest.go (about) 1 // Copyright (C) 2023 Gobalsky Labs Limited 2 // 3 // This program is free software: you can redistribute it and/or modify 4 // it under the terms of the GNU Affero General Public License as 5 // published by the Free Software Foundation, either version 3 of the 6 // License, or (at your option) any later version. 7 // 8 // This program is distributed in the hope that it will be useful, 9 // but WITHOUT ANY WARRANTY; without even the implied warranty of 10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 // GNU Affero General Public License for more details. 12 // 13 // You should have received a copy of the GNU Affero General Public License 14 // along with this program. If not, see <http://www.gnu.org/licenses/>. 15 16 package api 17 18 import ( 19 "context" 20 "net/http" 21 22 datanodeRest "code.vegaprotocol.io/vega/datanode/gateway/rest" 23 "code.vegaprotocol.io/vega/logging" 24 protoapi "code.vegaprotocol.io/vega/protos/blockexplorer/api/v1" 25 26 "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" 27 "google.golang.org/grpc" 28 "google.golang.org/grpc/credentials/insecure" 29 ) 30 31 // Handler implement a rest server acting as a proxy to the grpc api. 32 type RESTHandler struct { 33 RESTConfig 34 log *logging.Logger 35 dialer grpcDialer 36 mux *runtime.ServeMux 37 conn *grpc.ClientConn 38 } 39 40 func NewRESTHandler(log *logging.Logger, dialer grpcDialer, config RESTConfig) *RESTHandler { 41 log = log.Named(restNamedLogger) 42 log.SetLevel(config.Level.Get()) 43 44 return &RESTHandler{ 45 log: log, 46 RESTConfig: config, 47 dialer: dialer, 48 mux: runtime.NewServeMux(restHandlerServeMuxOptions()...), 49 } 50 } 51 52 func (r *RESTHandler) Name() string { return "REST" } 53 54 func (r *RESTHandler) Start(ctx context.Context) error { 55 r.log.Info("Starting REST API", logging.String("endpoint", r.Endpoint)) 56 57 opts := []grpc.DialOption{grpc.WithTransportCredentials(insecure.NewCredentials())} 58 if err := r.registerBlockExplorer(ctx, r.mux, opts); err != nil { 59 r.log.Panic("Failure registering trading handler for REST proxy endpoints", logging.Error(err)) 60 } 61 62 return nil 63 } 64 65 // registerBlockExplorer is a variation of RegisterBlockExplorerHandlerFromEndpoint, which uses our custom dialer. 66 func (r *RESTHandler) registerBlockExplorer(ctx context.Context, mux *runtime.ServeMux, opts []grpc.DialOption) error { 67 conn, err := r.dialer.DialGRPC(ctx, opts...) 68 if err != nil { 69 return err 70 } 71 r.conn = conn 72 return protoapi.RegisterBlockExplorerServiceHandler(ctx, mux, conn) 73 } 74 75 func (r *RESTHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) { 76 r.mux.ServeHTTP(w, req) 77 } 78 79 func (r *RESTHandler) Stop() { 80 if r.conn != nil { 81 r.log.Info("Stopping REST API") 82 _ = r.conn.Close() 83 } 84 } 85 86 func restHandlerServeMuxOptions() []runtime.ServeMuxOption { 87 jsonPB := &datanodeRest.JSONPb{ 88 EmitDefaults: true, 89 Indent: " ", // formatted json output 90 OrigName: false, 91 } 92 93 return []runtime.ServeMuxOption{ 94 runtime.WithMarshalerOption(runtime.MIMEWildcard, jsonPB), 95 } 96 }