@@ -17,6 +17,7 @@ import (
1717 "github.com/rs/cors"
1818 "go.uber.org/zap"
1919 "golang.org/x/net/http2"
20+ "golang.org/x/net/http2/h2c"
2021
2122 "github.com/ava-labs/avalanchego/api"
2223 "github.com/ava-labs/avalanchego/ids"
@@ -88,7 +89,8 @@ type server struct {
8889 metrics * metrics
8990
9091 // Maps endpoints to handlers
91- router * router
92+ router * router
93+ http2Router * http2Router
9294
9395 srv * http.Server
9496
@@ -115,33 +117,30 @@ func New(
115117 }
116118
117119 router := newRouter ()
118- allowedHostsHandler := filterInvalidHosts (router , allowedHosts )
119- corsHandler := cors .New (cors.Options {
120- AllowedOrigins : allowedOrigins ,
121- AllowCredentials : true ,
122- }).Handler (allowedHostsHandler )
123- gzipHandler := gziphandler .GzipHandler (corsHandler )
124- var handler http.Handler = http .HandlerFunc (
125- func (w http.ResponseWriter , r * http.Request ) {
126- // Attach this node's ID as a header
127- w .Header ().Set ("node-id" , nodeID .String ())
128- gzipHandler .ServeHTTP (w , r )
129- },
130- )
120+ handler := wrapHandler (router , nodeID , allowedOrigins , allowedHosts , true )
121+
122+ http2Router := newHTTP2Router ()
123+ // Do not use gzip middleware because it breaks the grpc spec
124+ http2Handler := wrapHandler (http2Router , nodeID , allowedOrigins , allowedHosts , false )
131125
132126 httpServer := & http.Server {
133- Handler : handler ,
127+ Handler : h2c .NewHandler (
128+ http .HandlerFunc (func (w http.ResponseWriter , r * http.Request ) {
129+ if r .ProtoMajor == 2 {
130+ http2Handler .ServeHTTP (w , r )
131+ return
132+ }
133+
134+ handler .ServeHTTP (w , r )
135+ }),
136+ & http2.Server {
137+ MaxConcurrentStreams : maxConcurrentStreams ,
138+ }),
134139 ReadTimeout : httpConfig .ReadTimeout ,
135140 ReadHeaderTimeout : httpConfig .ReadHeaderTimeout ,
136141 WriteTimeout : httpConfig .WriteTimeout ,
137142 IdleTimeout : httpConfig .IdleTimeout ,
138143 }
139- err = http2 .ConfigureServer (httpServer , & http2.Server {
140- MaxConcurrentStreams : maxConcurrentStreams ,
141- })
142- if err != nil {
143- return nil , err
144- }
145144
146145 log .Info ("API created" ,
147146 zap .Strings ("allowedOrigins" , allowedOrigins ),
@@ -154,6 +153,7 @@ func New(
154153 tracer : tracer ,
155154 metrics : m ,
156155 router : router ,
156+ http2Router : http2Router ,
157157 srv : httpServer ,
158158 listener : listener ,
159159 }, nil
@@ -199,6 +199,30 @@ func (s *server) RegisterChain(chainName string, ctx *snow.ConsensusContext, vm
199199 )
200200 }
201201 }
202+
203+ ctx .Lock .Lock ()
204+ http2Handler , err := vm .CreateHTTP2Handler (context .TODO ())
205+ ctx .Lock .Unlock ()
206+ if err != nil {
207+ s .log .Error ("failed to create http2 handler" ,
208+ zap .String ("chainName" , chainName ),
209+ zap .Error (err ),
210+ )
211+ return
212+ }
213+
214+ if http2Handler == nil {
215+ return
216+ }
217+
218+ http2Handler = s .wrapMiddleware (chainName , http2Handler , ctx )
219+ if ! s .http2Router .Add (ctx .ChainID , http2Handler ) {
220+ s .log .Error (
221+ "failed to add route to http2 handler" ,
222+ zap .String ("chainName" , chainName ),
223+ zap .Error (err ),
224+ )
225+ }
202226}
203227
204228func (s * server ) addChainRoute (chainName string , handler http.Handler , ctx * snow.ConsensusContext , base , endpoint string ) error {
@@ -207,13 +231,17 @@ func (s *server) addChainRoute(chainName string, handler http.Handler, ctx *snow
207231 zap .String ("url" , url ),
208232 zap .String ("endpoint" , endpoint ),
209233 )
234+ handler = s .wrapMiddleware (chainName , handler , ctx )
235+ return s .router .AddRouter (url , endpoint , handler )
236+ }
237+
238+ func (s * server ) wrapMiddleware (chainName string , handler http.Handler , ctx * snow.ConsensusContext ) http.Handler {
210239 if s .tracingEnabled {
211240 handler = api .TraceHandler (handler , chainName , s .tracer )
212241 }
213242 // Apply middleware to reject calls to the handler before the chain finishes bootstrapping
214243 handler = rejectMiddleware (handler , ctx )
215- handler = s .metrics .wrapHandler (chainName , handler )
216- return s .router .AddRouter (url , endpoint , handler )
244+ return s .metrics .wrapHandler (chainName , handler )
217245}
218246
219247func (s * server ) AddRoute (handler http.Handler , base , endpoint string ) error {
@@ -299,3 +327,27 @@ func (a readPathAdder) AddRoute(handler http.Handler, base, endpoint string) err
299327func (a readPathAdder ) AddAliases (endpoint string , aliases ... string ) error {
300328 return a .pather .AddAliasesWithReadLock (endpoint , aliases ... )
301329}
330+
331+ func wrapHandler (
332+ handler http.Handler ,
333+ nodeID ids.NodeID ,
334+ allowedOrigins []string ,
335+ allowedHosts []string ,
336+ gzip bool ,
337+ ) http.Handler {
338+ h := filterInvalidHosts (handler , allowedHosts )
339+ h = cors .New (cors.Options {
340+ AllowedOrigins : allowedOrigins ,
341+ AllowCredentials : true ,
342+ }).Handler (h )
343+ if gzip {
344+ h = gziphandler .GzipHandler (h )
345+ }
346+ return http .HandlerFunc (
347+ func (w http.ResponseWriter , r * http.Request ) {
348+ // Attach this node's ID as a header
349+ w .Header ().Set ("node-id" , nodeID .String ())
350+ h .ServeHTTP (w , r )
351+ },
352+ )
353+ }
0 commit comments