174 lines
4.6 KiB
Go
174 lines
4.6 KiB
Go
// Package api wires the monitoring endpoints onto an HTTP router.
|
|
//
|
|
// api.RegisterRoutes(http.NewServeMux(), p)
|
|
package api
|
|
|
|
import (
|
|
"encoding/json"
|
|
"net/http"
|
|
"strings"
|
|
|
|
"dappco.re/go/core/proxy"
|
|
)
|
|
|
|
// Router is the minimal route-registration surface used by RegisterRoutes.
|
|
//
|
|
// mux := http.NewServeMux()
|
|
// api.RegisterRoutes(mux, p)
|
|
type Router interface {
|
|
HandleFunc(pattern string, handler func(http.ResponseWriter, *http.Request))
|
|
}
|
|
|
|
type SummaryResponse = proxy.SummaryResponse
|
|
type HashrateResponse = proxy.HashrateResponse
|
|
type MinersCountResponse = proxy.MinersCountResponse
|
|
type UpstreamResponse = proxy.UpstreamResponse
|
|
type ResultsResponse = proxy.ResultsResponse
|
|
|
|
// RegisterRoutes mounts the monitoring endpoints on any router with HandleFunc.
|
|
//
|
|
// mux := http.NewServeMux()
|
|
// api.RegisterRoutes(mux, p)
|
|
func RegisterRoutes(router Router, proxyValue *proxy.Proxy) {
|
|
if router == nil || proxyValue == nil {
|
|
return
|
|
}
|
|
|
|
router.HandleFunc("/1/summary", func(writer http.ResponseWriter, request *http.Request) {
|
|
if !allowRequest(writer, request, proxyValue.HTTPConfig()) {
|
|
return
|
|
}
|
|
summary := proxyValue.Summary()
|
|
response := SummaryResponse{
|
|
Version: "1.0.0",
|
|
Mode: proxyValue.Mode(),
|
|
Hashrate: HashrateResponse{
|
|
Total: summary.Hashrate,
|
|
},
|
|
Miners: MinersCountResponse{
|
|
Now: proxyValue.CurrentMiners(),
|
|
Max: proxyValue.MaxMiners(),
|
|
},
|
|
Workers: uint64(len(proxyValue.Workers())),
|
|
Upstreams: func() UpstreamResponse {
|
|
upstreams := proxyValue.Upstreams()
|
|
ratio := 0.0
|
|
if upstreams.Total > 0 {
|
|
ratio = float64(proxyValue.CurrentMiners()) / float64(upstreams.Total)
|
|
}
|
|
return UpstreamResponse{
|
|
Active: upstreams.Active,
|
|
Sleep: upstreams.Sleep,
|
|
Error: upstreams.Error,
|
|
Total: upstreams.Total,
|
|
Ratio: ratio,
|
|
}
|
|
}(),
|
|
Results: ResultsResponse{
|
|
Accepted: summary.Accepted,
|
|
Rejected: summary.Rejected,
|
|
Invalid: summary.Invalid,
|
|
Expired: summary.Expired,
|
|
AvgTime: summary.AvgTime,
|
|
Latency: summary.AvgLatency,
|
|
HashesTotal: summary.Hashes,
|
|
Best: summary.TopDiff,
|
|
},
|
|
}
|
|
writeJSON(writer, response)
|
|
})
|
|
|
|
router.HandleFunc("/1/workers", func(writer http.ResponseWriter, request *http.Request) {
|
|
if !allowRequest(writer, request, proxyValue.HTTPConfig()) {
|
|
return
|
|
}
|
|
type responseBody struct {
|
|
Mode string `json:"mode"`
|
|
Workers [][]interface{} `json:"workers"`
|
|
}
|
|
|
|
records := proxyValue.Workers()
|
|
rows := make([][]interface{}, 0, len(records))
|
|
for _, record := range records {
|
|
rows = append(rows, []interface{}{
|
|
record.Name,
|
|
record.LastIP,
|
|
record.Connections,
|
|
record.Accepted,
|
|
record.Rejected,
|
|
record.Invalid,
|
|
record.Hashes,
|
|
record.LastHashAt.Unix(),
|
|
record.Hashrate(60),
|
|
record.Hashrate(600),
|
|
record.Hashrate(3600),
|
|
record.Hashrate(43200),
|
|
record.Hashrate(86400),
|
|
})
|
|
}
|
|
|
|
writeJSON(writer, responseBody{
|
|
Mode: proxyValue.WorkersMode(),
|
|
Workers: rows,
|
|
})
|
|
})
|
|
|
|
router.HandleFunc("/1/miners", func(writer http.ResponseWriter, request *http.Request) {
|
|
if !allowRequest(writer, request, proxyValue.HTTPConfig()) {
|
|
return
|
|
}
|
|
miners := proxyValue.Miners()
|
|
rows := make([][]interface{}, 0, len(miners))
|
|
for _, miner := range miners {
|
|
ip := ""
|
|
if remote := miner.RemoteAddr(); remote != nil {
|
|
ip = remote.String()
|
|
}
|
|
rows = append(rows, []interface{}{
|
|
miner.ID(),
|
|
ip,
|
|
miner.TX(),
|
|
miner.RX(),
|
|
miner.State(),
|
|
miner.Diff(),
|
|
miner.User(),
|
|
"********",
|
|
miner.RigID(),
|
|
miner.Agent(),
|
|
})
|
|
}
|
|
|
|
writeJSON(writer, map[string]interface{}{
|
|
"format": []string{"id", "ip", "tx", "rx", "state", "diff", "user", "password", "rig_id", "agent"},
|
|
"miners": rows,
|
|
})
|
|
})
|
|
}
|
|
|
|
func allowRequest(writer http.ResponseWriter, request *http.Request, config proxy.HTTPConfig) bool {
|
|
if request == nil {
|
|
return false
|
|
}
|
|
|
|
if config.AccessToken != "" {
|
|
header := request.Header.Get("Authorization")
|
|
prefix := "Bearer "
|
|
if !strings.HasPrefix(header, prefix) || strings.TrimSpace(strings.TrimPrefix(header, prefix)) != config.AccessToken {
|
|
writer.Header().Set("WWW-Authenticate", "Bearer")
|
|
http.Error(writer, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized)
|
|
return false
|
|
}
|
|
}
|
|
|
|
if config.Restricted && request.Method != http.MethodGet {
|
|
http.Error(writer, http.StatusText(http.StatusMethodNotAllowed), http.StatusMethodNotAllowed)
|
|
return false
|
|
}
|
|
|
|
return true
|
|
}
|
|
|
|
func writeJSON(writer http.ResponseWriter, value interface{}) {
|
|
writer.Header().Set("Content-Type", "application/json")
|
|
_ = json.NewEncoder(writer).Encode(value)
|
|
}
|