/
handler_block.go
129 lines (107 loc) · 3.28 KB
/
handler_block.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
package digest
import (
"net/http"
"time"
"github.com/gorilla/mux"
"github.com/spikeekips/mitum/base"
quicnetwork "github.com/spikeekips/mitum/network/quic"
"github.com/spikeekips/mitum/util/valuehash"
)
var halBlockTemplate = map[string]HalLink{
"block:{height}": NewHalLink(HandlerPathBlockByHeight, nil).SetTemplated(),
"block:{hash}": NewHalLink(HandlerPathBlockByHeight, nil).SetTemplated(),
"manifest:{height}": NewHalLink(HandlerPathManifestByHeight, nil).SetTemplated(),
"manifest:{hash}": NewHalLink(HandlerPathManifestByHash, nil).SetTemplated(),
}
func (hd *Handlers) handleBlock(w http.ResponseWriter, r *http.Request) {
cachekey := CacheKeyPath(r)
if err := LoadFromCache(hd.cache, cachekey, w); err == nil {
return
}
if v, err, shared := hd.rg.Do(cachekey, func() (interface{}, error) {
return hd.handleBlockInGroup(mux.Vars(r))
}); err != nil {
HTTP2HandleError(w, err)
} else {
HTTP2WriteHalBytes(hd.enc, w, v.([]byte), http.StatusOK)
if !shared {
HTTP2WriteCache(w, cachekey, time.Hour*3000)
}
}
}
func (hd *Handlers) handleBlockInGroup(vars map[string]string) ([]byte, error) {
var hal Hal
if s, found := vars["height"]; found {
height, err := parseHeightFromPath(s)
if err != nil {
return nil, quicnetwork.BadRequestError.Errorf("invalid height found for block by height: %w", err)
}
h, err := hd.buildBlockHalByHeight(height)
if err != nil {
return nil, err
}
hal = h
} else if s, found := vars["hash"]; found {
h, err := parseHashFromPath(s)
if err != nil {
return nil, quicnetwork.BadRequestError.Errorf("invalid hash for block by hash: %w", err)
}
i, err := hd.buildBlockHalByHash(h)
if err != nil {
return nil, err
}
hal = i
}
return hd.enc.Marshal(hal)
}
func (hd *Handlers) buildBlockHalByHeight(height base.Height) (Hal, error) {
h, err := hd.combineURL(HandlerPathBlockByHeight, "height", height.String())
if err != nil {
return nil, err
}
var hal Hal
hal = NewBaseHal(nil, NewHalLink(h, nil))
h, err = hd.combineURL(HandlerPathBlockByHeight, "height", (height + 1).String())
if err != nil {
return nil, err
}
hal = hal.AddLink("next", NewHalLink(h, nil))
if height > base.PreGenesisHeight+1 {
h, err = hd.combineURL(HandlerPathBlockByHeight, "height", (height - 1).String())
if err != nil {
return nil, err
}
hal = hal.AddLink("prev", NewHalLink(h, nil))
}
h, err = hd.combineURL(HandlerPathBlockByHeight, "height", height.String())
if err != nil {
return nil, err
}
hal = hal.AddLink("current", NewHalLink(h, nil))
h, err = hd.combineURL(HandlerPathManifestByHeight, "height", height.String())
if err != nil {
return nil, err
}
hal = hal.AddLink("current-manifest", NewHalLink(h, nil))
for k := range halBlockTemplate {
hal = hal.AddLink(k, halBlockTemplate[k])
}
return hal, nil
}
func (hd *Handlers) buildBlockHalByHash(h valuehash.Hash) (Hal, error) {
i, err := hd.combineURL(HandlerPathBlockByHash, "hash", h.String())
if err != nil {
return nil, err
}
var hal Hal
hal = NewBaseHal(nil, NewHalLink(i, nil))
i, err = hd.combineURL(HandlerPathManifestByHash, "hash", h.String())
if err != nil {
return nil, err
}
hal = hal.AddLink("manifest", NewHalLink(i, nil))
for k := range halBlockTemplate {
hal = hal.AddLink(k, halBlockTemplate[k])
}
return hal, nil
}