github.com/iotexproject/iotex-core@v1.14.1-rc1/api/http.go (about)

     1  package api
     2  
     3  import (
     4  	"context"
     5  	"encoding/json"
     6  	"net/http"
     7  	"strconv"
     8  	"time"
     9  
    10  	"go.uber.org/zap"
    11  
    12  	apitypes "github.com/iotexproject/iotex-core/api/types"
    13  	"github.com/iotexproject/iotex-core/pkg/log"
    14  	"github.com/iotexproject/iotex-core/pkg/util/httputil"
    15  )
    16  
    17  type (
    18  	// HTTPServer crates a http server
    19  	HTTPServer struct {
    20  		svr *http.Server
    21  	}
    22  
    23  	// hTTPHandler handles requests from http protocol
    24  	hTTPHandler struct {
    25  		msgHandler Web3Handler
    26  	}
    27  )
    28  
    29  // NewHTTPServer creates a new http server
    30  func NewHTTPServer(route string, port int, handler http.Handler) *HTTPServer {
    31  	if port == 0 {
    32  		return nil
    33  	}
    34  	mux := http.NewServeMux()
    35  	mux.Handle("/"+route, handler)
    36  
    37  	svr := httputil.NewServer(":"+strconv.Itoa(port), mux, httputil.ReadHeaderTimeout(10*time.Second))
    38  	return &HTTPServer{
    39  		svr: &svr,
    40  	}
    41  }
    42  
    43  // Start starts the http server
    44  func (hSvr *HTTPServer) Start(_ context.Context) error {
    45  	go func() {
    46  		if err := hSvr.svr.ListenAndServe(); err != nil && err != http.ErrServerClosed {
    47  			log.L().Fatal("Node failed to serve.", zap.Error(err))
    48  		}
    49  	}()
    50  	return nil
    51  }
    52  
    53  // Stop stops the http server
    54  func (hSvr *HTTPServer) Stop(ctx context.Context) error {
    55  	return hSvr.svr.Shutdown(ctx)
    56  }
    57  
    58  // newHTTPHandler creates a new http handler
    59  func newHTTPHandler(web3Handler Web3Handler) *hTTPHandler {
    60  	return &hTTPHandler{
    61  		msgHandler: web3Handler,
    62  	}
    63  }
    64  
    65  func (handler *hTTPHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
    66  	if req.Method != "POST" {
    67  		w.Write([]byte("IoTeX RPC endpoint is ready."))
    68  		return
    69  	}
    70  
    71  	if err := handler.msgHandler.HandlePOSTReq(req.Context(), req.Body,
    72  		apitypes.NewResponseWriter(
    73  			func(resp interface{}) (int, error) {
    74  				w.Header().Set("Access-Control-Allow-Origin", "*")
    75  				w.Header().Set("Content-Type", "application/json; charset=UTF-8")
    76  				raw, err := json.Marshal(resp)
    77  				if err != nil {
    78  					return 0, err
    79  				}
    80  				return w.Write(raw)
    81  			}),
    82  	); err != nil {
    83  		log.Logger("api").Warn("fail to respond request.", zap.Error(err))
    84  	}
    85  }