github.com/core-coin/go-core/v2@v2.1.9/node/endpoints.go (about)

     1  // Copyright 2020 by the Authors
     2  // This file is part of the go-core library.
     3  //
     4  // The go-core library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-core library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-core library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package node
    18  
    19  import (
    20  	"net"
    21  	"net/http"
    22  	"time"
    23  
    24  	"github.com/core-coin/go-core/v2/log"
    25  	"github.com/core-coin/go-core/v2/rpc"
    26  )
    27  
    28  // StartHTTPEndpoint starts the HTTP RPC endpoint.
    29  func StartHTTPEndpoint(endpoint string, timeouts rpc.HTTPTimeouts, handler http.Handler) (*http.Server, net.Addr, error) {
    30  	// start the HTTP listener
    31  	var (
    32  		listener net.Listener
    33  		err      error
    34  	)
    35  	if listener, err = net.Listen("tcp", endpoint); err != nil {
    36  		return nil, nil, err
    37  	}
    38  	// make sure timeout values are meaningful
    39  	CheckTimeouts(&timeouts)
    40  	// Bundle and start the HTTP server
    41  	httpSrv := &http.Server{
    42  		Handler:      handler,
    43  		ReadTimeout:  timeouts.ReadTimeout,
    44  		WriteTimeout: timeouts.WriteTimeout,
    45  		IdleTimeout:  timeouts.IdleTimeout,
    46  	}
    47  	go httpSrv.Serve(listener)
    48  	return httpSrv, listener.Addr(), err
    49  }
    50  
    51  // checkModuleAvailability checks that all names given in modules are actually
    52  // available API services. It assumes that the MetadataApi module ("rpc") is always available;
    53  // the registration of this "rpc" module happens in NewServer() and is thus common to all endpoints.
    54  func checkModuleAvailability(modules []string, apis []rpc.API) (bad, available []string) {
    55  	availableSet := make(map[string]struct{})
    56  	for _, api := range apis {
    57  		if _, ok := availableSet[api.Namespace]; !ok {
    58  			availableSet[api.Namespace] = struct{}{}
    59  			available = append(available, api.Namespace)
    60  		}
    61  	}
    62  	for _, name := range modules {
    63  		if _, ok := availableSet[name]; !ok {
    64  			if name != rpc.MetadataApi && name != rpc.EngineApi {
    65  				bad = append(bad, name)
    66  			}
    67  		}
    68  	}
    69  	return bad, available
    70  }
    71  
    72  // CheckTimeouts ensures that timeout values are meaningful
    73  func CheckTimeouts(timeouts *rpc.HTTPTimeouts) {
    74  	if timeouts.ReadTimeout < time.Second {
    75  		log.Warn("Sanitizing invalid HTTP read timeout", "provided", timeouts.ReadTimeout, "updated", rpc.DefaultHTTPTimeouts.ReadTimeout)
    76  		timeouts.ReadTimeout = rpc.DefaultHTTPTimeouts.ReadTimeout
    77  	}
    78  	if timeouts.WriteTimeout < time.Second {
    79  		log.Warn("Sanitizing invalid HTTP write timeout", "provided", timeouts.WriteTimeout, "updated", rpc.DefaultHTTPTimeouts.WriteTimeout)
    80  		timeouts.WriteTimeout = rpc.DefaultHTTPTimeouts.WriteTimeout
    81  	}
    82  	if timeouts.IdleTimeout < time.Second {
    83  		log.Warn("Sanitizing invalid HTTP idle timeout", "provided", timeouts.IdleTimeout, "updated", rpc.DefaultHTTPTimeouts.IdleTimeout)
    84  		timeouts.IdleTimeout = rpc.DefaultHTTPTimeouts.IdleTimeout
    85  	}
    86  }