kopia lustrzana https://github.com/bugout-dev/moonstream
84 wiersze
2.4 KiB
Go
84 wiersze
2.4 KiB
Go
/*
|
|
Handle routes for load balancer API.
|
|
*/
|
|
package cmd
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"log"
|
|
"net/http"
|
|
"strings"
|
|
|
|
configs "github.com/bugout-dev/moonstream/nodes/node_balancer/configs"
|
|
)
|
|
|
|
// pingRoute response with status of load balancer server itself
|
|
func pingRoute(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Content-Type", "application/json")
|
|
response := PingResponse{Status: "ok"}
|
|
json.NewEncoder(w).Encode(response)
|
|
}
|
|
|
|
// lbHandler load balances the incoming requests to nodes
|
|
func lbHandler(w http.ResponseWriter, r *http.Request) {
|
|
attempts := GetAttemptsFromContext(r)
|
|
if attempts > configs.NB_CONNECTION_RETRIES {
|
|
log.Printf("Max attempts reached from %s %s, terminating\n", r.RemoteAddr, r.URL.Path)
|
|
http.Error(w, "Service not available", http.StatusServiceUnavailable)
|
|
return
|
|
}
|
|
|
|
var blockchain string
|
|
switch {
|
|
case strings.HasPrefix(r.URL.Path, "/nb/ethereum"):
|
|
blockchain = "ethereum"
|
|
case strings.HasPrefix(r.URL.Path, "/nb/polygon"):
|
|
blockchain = "polygon"
|
|
default:
|
|
http.Error(w, fmt.Sprintf("Unacceptable blockchain provided %s", blockchain), http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
clientId := w.Header().Get(configs.MOONSTREAM_CLIENT_ID_HEADER)
|
|
if clientId == "" {
|
|
// TODO(kompotkot): After all internal crawlers and services start
|
|
// providing client id header, then replace to http.Error
|
|
clientId = "none"
|
|
}
|
|
|
|
// Chose one node
|
|
var node *Node
|
|
cpool, err := GetClientPool(blockchain)
|
|
if err != nil {
|
|
http.Error(w, fmt.Sprintf("Unacceptable blockchain provided %s", blockchain), http.StatusBadRequest)
|
|
return
|
|
}
|
|
node = cpool.GetClientNode(clientId)
|
|
if node == nil {
|
|
node = blockchainPool.GetNextNode(blockchain)
|
|
if node == nil {
|
|
http.Error(w, "There are no nodes available", http.StatusServiceUnavailable)
|
|
return
|
|
}
|
|
cpool.AddClientNode(clientId, node)
|
|
}
|
|
|
|
// Save origin path, to use in proxyErrorHandler if node will not response
|
|
r.Header.Add("X-Origin-Path", r.URL.Path)
|
|
|
|
switch {
|
|
case strings.HasPrefix(r.URL.Path, fmt.Sprintf("/nb/%s/ping", blockchain)):
|
|
r.URL.Path = "/ping"
|
|
node.StatusReverseProxy.ServeHTTP(w, r)
|
|
return
|
|
case strings.HasPrefix(r.URL.Path, fmt.Sprintf("/nb/%s/jsonrpc", blockchain)):
|
|
r.URL.Path = "/"
|
|
node.GethReverseProxy.ServeHTTP(w, r)
|
|
return
|
|
default:
|
|
http.Error(w, fmt.Sprintf("Unacceptable path for %s blockchain %s", blockchain, r.URL.Path), http.StatusBadRequest)
|
|
return
|
|
}
|
|
}
|