Cleanup of internal http interface
This commit is contained in:
parent
e260c11839
commit
bb48f2d26e
28
api/types.go
28
api/types.go
@ -2,6 +2,7 @@ package api
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"blockbook/bchain"
|
"blockbook/bchain"
|
||||||
|
"blockbook/common"
|
||||||
"blockbook/db"
|
"blockbook/db"
|
||||||
"math/big"
|
"math/big"
|
||||||
"time"
|
"time"
|
||||||
@ -112,18 +113,21 @@ type Block struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type BlockbookInfo struct {
|
type BlockbookInfo struct {
|
||||||
Coin string `json:"coin"`
|
Coin string `json:"coin"`
|
||||||
Host string `json:"host"`
|
Host string `json:"host"`
|
||||||
Version string `json:"version"`
|
Version string `json:"version"`
|
||||||
GitCommit string `json:"gitcommit"`
|
GitCommit string `json:"gitcommit"`
|
||||||
BuildTime string `json:"buildtime"`
|
BuildTime string `json:"buildtime"`
|
||||||
InSync bool `json:"inSync"`
|
InSync bool `json:"inSync"`
|
||||||
BestHeight uint32 `json:"bestHeight"`
|
BestHeight uint32 `json:"bestHeight"`
|
||||||
LastBlockTime time.Time `json:"lastBlockTime"`
|
LastBlockTime time.Time `json:"lastBlockTime"`
|
||||||
InSyncMempool bool `json:"inSyncMempool"`
|
InSyncMempool bool `json:"inSyncMempool"`
|
||||||
LastMempoolTime time.Time `json:"lastMempoolTime"`
|
LastMempoolTime time.Time `json:"lastMempoolTime"`
|
||||||
DbSize int64 `json:"dbSize"`
|
MempoolSize int `json:"mempoolSize"`
|
||||||
About string `json:"about"`
|
DbSize int64 `json:"dbSize"`
|
||||||
|
DbSizeFromColumns int64 `json:"dbSizeFromColumns,omitempty"`
|
||||||
|
DbColumns []common.InternalStateColumn `json:"dbColumns,omitempty"`
|
||||||
|
About string `json:"about"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type SystemInfo struct {
|
type SystemInfo struct {
|
||||||
|
|||||||
@ -526,7 +526,7 @@ func (w *Worker) GetBlock(bid string, page int, txsOnPage int) (*Block, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetSystemInfo returns information about system
|
// GetSystemInfo returns information about system
|
||||||
func (w *Worker) GetSystemInfo() (*SystemInfo, error) {
|
func (w *Worker) GetSystemInfo(internal bool) (*SystemInfo, error) {
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
ci, err := w.chain.GetChainInfo()
|
ci, err := w.chain.GetChainInfo()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -534,20 +534,29 @@ func (w *Worker) GetSystemInfo() (*SystemInfo, error) {
|
|||||||
}
|
}
|
||||||
vi := common.GetVersionInfo()
|
vi := common.GetVersionInfo()
|
||||||
ss, bh, st := w.is.GetSyncState()
|
ss, bh, st := w.is.GetSyncState()
|
||||||
ms, mt, _ := w.is.GetMempoolSyncState()
|
ms, mt, msz := w.is.GetMempoolSyncState()
|
||||||
|
var dbc []common.InternalStateColumn
|
||||||
|
var dbs int64
|
||||||
|
if internal {
|
||||||
|
dbc = w.is.GetAllDBColumnStats()
|
||||||
|
dbs = w.is.DBSizeTotal()
|
||||||
|
}
|
||||||
bi := &BlockbookInfo{
|
bi := &BlockbookInfo{
|
||||||
Coin: w.is.Coin,
|
Coin: w.is.Coin,
|
||||||
Host: w.is.Host,
|
Host: w.is.Host,
|
||||||
Version: vi.Version,
|
Version: vi.Version,
|
||||||
GitCommit: vi.GitCommit,
|
GitCommit: vi.GitCommit,
|
||||||
BuildTime: vi.BuildTime,
|
BuildTime: vi.BuildTime,
|
||||||
InSync: ss,
|
InSync: ss,
|
||||||
BestHeight: bh,
|
BestHeight: bh,
|
||||||
LastBlockTime: st,
|
LastBlockTime: st,
|
||||||
InSyncMempool: ms,
|
InSyncMempool: ms,
|
||||||
LastMempoolTime: mt,
|
LastMempoolTime: mt,
|
||||||
About: BlockbookAbout,
|
MempoolSize: msz,
|
||||||
DbSize: w.db.DatabaseSizeOnDisk(),
|
DbSize: w.db.DatabaseSizeOnDisk(),
|
||||||
|
DbSizeFromColumns: dbs,
|
||||||
|
DbColumns: dbc,
|
||||||
|
About: BlockbookAbout,
|
||||||
}
|
}
|
||||||
glog.Info("GetSystemInfo finished in ", time.Since(start))
|
glog.Info("GetSystemInfo finished in ", time.Since(start))
|
||||||
return &SystemInfo{bi, ci}, nil
|
return &SystemInfo{bi, ci}, nil
|
||||||
|
|||||||
@ -1,20 +1,17 @@
|
|||||||
package server
|
package server
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"blockbook/api"
|
||||||
"blockbook/bchain"
|
"blockbook/bchain"
|
||||||
"blockbook/common"
|
"blockbook/common"
|
||||||
"blockbook/db"
|
"blockbook/db"
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strconv"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
|
|
||||||
"github.com/gorilla/mux"
|
|
||||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -27,29 +24,21 @@ type InternalServer struct {
|
|||||||
chain bchain.BlockChain
|
chain bchain.BlockChain
|
||||||
chainParser bchain.BlockChainParser
|
chainParser bchain.BlockChainParser
|
||||||
is *common.InternalState
|
is *common.InternalState
|
||||||
}
|
api *api.Worker
|
||||||
|
|
||||||
type resAboutBlockbookInternal struct {
|
|
||||||
Coin string `json:"coin"`
|
|
||||||
Host string `json:"host"`
|
|
||||||
Version string `json:"version"`
|
|
||||||
GitCommit string `json:"gitcommit"`
|
|
||||||
BuildTime string `json:"buildtime"`
|
|
||||||
InSync bool `json:"inSync"`
|
|
||||||
BestHeight uint32 `json:"bestHeight"`
|
|
||||||
LastBlockTime time.Time `json:"lastBlockTime"`
|
|
||||||
InSyncMempool bool `json:"inSyncMempool"`
|
|
||||||
LastMempoolTime time.Time `json:"lastMempoolTime"`
|
|
||||||
MempoolSize int `json:"mempoolSize"`
|
|
||||||
DbColumns []common.InternalStateColumn `json:"dbColumns"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewInternalServer creates new internal http interface to blockbook and returns its handle
|
// NewInternalServer creates new internal http interface to blockbook and returns its handle
|
||||||
func NewInternalServer(httpServerBinding string, certFiles string, db *db.RocksDB, chain bchain.BlockChain, txCache *db.TxCache, is *common.InternalState) (*InternalServer, error) {
|
func NewInternalServer(binding, certFiles string, db *db.RocksDB, chain bchain.BlockChain, txCache *db.TxCache, is *common.InternalState) (*InternalServer, error) {
|
||||||
r := mux.NewRouter()
|
api, err := api.NewWorker(db, chain, txCache, is)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
addr, path := splitBinding(binding)
|
||||||
|
serveMux := http.NewServeMux()
|
||||||
https := &http.Server{
|
https := &http.Server{
|
||||||
Addr: httpServerBinding,
|
Addr: addr,
|
||||||
Handler: r,
|
Handler: serveMux,
|
||||||
}
|
}
|
||||||
s := &InternalServer{
|
s := &InternalServer{
|
||||||
https: https,
|
https: https,
|
||||||
@ -59,15 +48,11 @@ func NewInternalServer(httpServerBinding string, certFiles string, db *db.RocksD
|
|||||||
chain: chain,
|
chain: chain,
|
||||||
chainParser: chain.GetChainParser(),
|
chainParser: chain.GetChainParser(),
|
||||||
is: is,
|
is: is,
|
||||||
|
api: api,
|
||||||
}
|
}
|
||||||
|
|
||||||
r.HandleFunc("/", s.index)
|
serveMux.HandleFunc(path+"metrics", promhttp.Handler().ServeHTTP)
|
||||||
r.HandleFunc("/bestBlockHash", s.bestBlockHash)
|
serveMux.HandleFunc(path, s.index)
|
||||||
r.HandleFunc("/blockHash/{height}", s.blockHash)
|
|
||||||
r.HandleFunc("/transactions/{address}/{lower}/{higher}", s.transactions)
|
|
||||||
r.HandleFunc("/confirmedTransactions/{address}/{lower}/{higher}", s.confirmedTransactions)
|
|
||||||
r.HandleFunc("/unconfirmedTransactions/{address}", s.unconfirmedTransactions)
|
|
||||||
r.HandleFunc("/metrics", promhttp.Handler().ServeHTTP)
|
|
||||||
|
|
||||||
return s, nil
|
return s, nil
|
||||||
}
|
}
|
||||||
@ -94,142 +79,11 @@ func (s *InternalServer) Shutdown(ctx context.Context) error {
|
|||||||
return s.https.Shutdown(ctx)
|
return s.https.Shutdown(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
func respondError(w http.ResponseWriter, err error, context string) {
|
|
||||||
w.WriteHeader(http.StatusBadRequest)
|
|
||||||
glog.Errorf("internal server: (context %s) error: %v", context, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
func respondHashData(w http.ResponseWriter, hash string) {
|
|
||||||
type hashData struct {
|
|
||||||
Hash string `json:"hash"`
|
|
||||||
}
|
|
||||||
json.NewEncoder(w).Encode(hashData{
|
|
||||||
Hash: hash,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *InternalServer) index(w http.ResponseWriter, r *http.Request) {
|
func (s *InternalServer) index(w http.ResponseWriter, r *http.Request) {
|
||||||
vi := common.GetVersionInfo()
|
si, err := s.api.GetSystemInfo(true)
|
||||||
ss, bh, st := s.is.GetSyncState()
|
buf, err := json.MarshalIndent(si, "", " ")
|
||||||
ms, mt, msz := s.is.GetMempoolSyncState()
|
|
||||||
a := resAboutBlockbookInternal{
|
|
||||||
Coin: s.is.Coin,
|
|
||||||
Host: s.is.Host,
|
|
||||||
Version: vi.Version,
|
|
||||||
GitCommit: vi.GitCommit,
|
|
||||||
BuildTime: vi.BuildTime,
|
|
||||||
InSync: ss,
|
|
||||||
BestHeight: bh,
|
|
||||||
LastBlockTime: st,
|
|
||||||
InSyncMempool: ms,
|
|
||||||
LastMempoolTime: mt,
|
|
||||||
MempoolSize: msz,
|
|
||||||
DbColumns: s.is.GetAllDBColumnStats(),
|
|
||||||
}
|
|
||||||
buf, err := json.MarshalIndent(a, "", " ")
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
glog.Error(err)
|
glog.Error(err)
|
||||||
}
|
}
|
||||||
w.Write(buf)
|
w.Write(buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *InternalServer) bestBlockHash(w http.ResponseWriter, r *http.Request) {
|
|
||||||
_, hash, err := s.db.GetBestBlock()
|
|
||||||
if err != nil {
|
|
||||||
respondError(w, err, "bestBlockHash")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
respondHashData(w, hash)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *InternalServer) blockHash(w http.ResponseWriter, r *http.Request) {
|
|
||||||
heightString := mux.Vars(r)["height"]
|
|
||||||
var hash string
|
|
||||||
height, err := strconv.ParseUint(heightString, 10, 32)
|
|
||||||
if err == nil {
|
|
||||||
hash, err = s.db.GetBlockHash(uint32(height))
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
respondError(w, err, fmt.Sprintf("blockHash %s", heightString))
|
|
||||||
} else {
|
|
||||||
respondHashData(w, hash)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *InternalServer) getAddress(r *http.Request) (address string, err error) {
|
|
||||||
address, ok := mux.Vars(r)["address"]
|
|
||||||
if !ok {
|
|
||||||
err = errors.New("Empty address")
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *InternalServer) getAddressAndHeightRange(r *http.Request) (address string, lower, higher uint32, err error) {
|
|
||||||
address, err = s.getAddress(r)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
higher64, err := strconv.ParseUint(mux.Vars(r)["higher"], 10, 32)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
lower64, err := strconv.ParseUint(mux.Vars(r)["lower"], 10, 32)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
return address, uint32(lower64), uint32(higher64), err
|
|
||||||
}
|
|
||||||
|
|
||||||
type transactionList struct {
|
|
||||||
Txid []string `json:"txid"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *InternalServer) unconfirmedTransactions(w http.ResponseWriter, r *http.Request) {
|
|
||||||
address, err := s.getAddress(r)
|
|
||||||
if err != nil {
|
|
||||||
respondError(w, err, fmt.Sprint("unconfirmedTransactions for address", address))
|
|
||||||
}
|
|
||||||
txs, err := s.chain.GetMempoolTransactions(address)
|
|
||||||
if err != nil {
|
|
||||||
respondError(w, err, fmt.Sprint("unconfirmedTransactions for address", address))
|
|
||||||
}
|
|
||||||
txList := transactionList{Txid: txs}
|
|
||||||
json.NewEncoder(w).Encode(txList)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *InternalServer) confirmedTransactions(w http.ResponseWriter, r *http.Request) {
|
|
||||||
address, lower, higher, err := s.getAddressAndHeightRange(r)
|
|
||||||
if err != nil {
|
|
||||||
respondError(w, err, fmt.Sprint("confirmedTransactions for address", address))
|
|
||||||
}
|
|
||||||
txList := transactionList{}
|
|
||||||
err = s.db.GetTransactions(address, lower, higher, func(txid string, vout uint32, isOutput bool) error {
|
|
||||||
txList.Txid = append(txList.Txid, txid)
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
respondError(w, err, fmt.Sprint("confirmedTransactions for address", address))
|
|
||||||
}
|
|
||||||
json.NewEncoder(w).Encode(txList)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *InternalServer) transactions(w http.ResponseWriter, r *http.Request) {
|
|
||||||
address, lower, higher, err := s.getAddressAndHeightRange(r)
|
|
||||||
if err != nil {
|
|
||||||
respondError(w, err, fmt.Sprint("transactions for address", address))
|
|
||||||
}
|
|
||||||
txList := transactionList{}
|
|
||||||
err = s.db.GetTransactions(address, lower, higher, func(txid string, vout uint32, isOutput bool) error {
|
|
||||||
txList.Txid = append(txList.Txid, txid)
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
respondError(w, err, fmt.Sprint("transactions for address", address))
|
|
||||||
}
|
|
||||||
txs, err := s.chain.GetMempoolTransactions(address)
|
|
||||||
if err != nil {
|
|
||||||
respondError(w, err, fmt.Sprint("transactions for address", address))
|
|
||||||
}
|
|
||||||
txList.Txid = append(txList.Txid, txs...)
|
|
||||||
json.NewEncoder(w).Encode(txList)
|
|
||||||
}
|
|
||||||
|
|||||||
@ -426,7 +426,7 @@ func (s *PublicServer) explorerIndex(w http.ResponseWriter, r *http.Request) (tp
|
|||||||
var si *api.SystemInfo
|
var si *api.SystemInfo
|
||||||
var err error
|
var err error
|
||||||
s.metrics.ExplorerViews.With(common.Labels{"action": "index"}).Inc()
|
s.metrics.ExplorerViews.With(common.Labels{"action": "index"}).Inc()
|
||||||
si, err = s.api.GetSystemInfo()
|
si, err = s.api.GetSystemInfo(false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errorTpl, nil, err
|
return errorTpl, nil, err
|
||||||
}
|
}
|
||||||
@ -522,7 +522,7 @@ func getPagingRange(page int, total int) ([]int, int, int) {
|
|||||||
|
|
||||||
func (s *PublicServer) apiIndex(r *http.Request) (interface{}, error) {
|
func (s *PublicServer) apiIndex(r *http.Request) (interface{}, error) {
|
||||||
s.metrics.ExplorerViews.With(common.Labels{"action": "api-index"}).Inc()
|
s.metrics.ExplorerViews.With(common.Labels{"action": "api-index"}).Inc()
|
||||||
return s.api.GetSystemInfo()
|
return s.api.GetSystemInfo(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *PublicServer) apiBlockIndex(r *http.Request) (interface{}, error) {
|
func (s *PublicServer) apiBlockIndex(r *http.Request) (interface{}, error) {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user