/
request_handler.go
141 lines (120 loc) · 3.58 KB
/
request_handler.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
130
131
132
133
134
135
136
137
138
139
140
141
package requesthandler
import (
"encoding/json"
"fmt"
"io/ioutil"
"log"
"net/http"
"github.com/ashishmax31/blockchain/requesthandler/requestvalidators"
"github.com/ashishmax31/blockchain/core/bchain"
"github.com/ashishmax31/blockchain/core/bchain/datatypes"
"github.com/ashishmax31/blockchain/core/nodes"
)
func ShowChain(w http.ResponseWriter, req *http.Request) {
switch req.Method {
case "GET":
payload, err := json.Marshal(bchain.BlockChain.ReadBlockChain())
if err != nil {
log.Fatalln(err.Error())
}
writeJSONResponse(payload, w)
}
}
func NewTransaction(w http.ResponseWriter, req *http.Request) {
switch req.Method {
case "POST":
decoder := json.NewDecoder(req.Body)
obj, err := decodeBody(decoder)
err = requestvalidators.Validate(obj)
err = requestvalidators.SignPayload(&obj)
if err != nil {
writeErrorResponse(err.Error(), w)
return
}
index, err := bchain.NewTransaction(obj)
if err != nil {
writeErrorResponse(err.Error()+":Couldnt verify the authenticity of the transaction", w)
return
}
w.WriteHeader(http.StatusOK)
w.Header().Set("Content-Type", "text")
w.Write([]byte(fmt.Sprintf("The transaction will be forged in block number %d \n", index)))
}
}
func Mine(w http.ResponseWriter, req *http.Request) {
switch req.Method {
case "GET":
bchain.Mine()
w.WriteHeader(http.StatusOK)
w.Header().Set("Content-Type", "text")
w.Write([]byte("Mined"))
}
}
func RegisterNode(w http.ResponseWriter, req *http.Request) {
if req.Method != "POST" {
w.WriteHeader(http.StatusNotFound)
fmt.Fprintf(w, "No route matches [%s] %q ", req.Method, req.URL.Path)
return
}
var data map[string]interface{}
body, err := ioutil.ReadAll(req.Body)
err = json.Unmarshal([]byte(body), &data)
if err != nil {
writeErrorResponse(err.Error(), w)
return
}
payload, sync := decodeNodeAddress(data)
// Post requests created by the nodes package will have sync set to true, whereas created by users/others
// will/should have sync set to false.
// Register the recieved node address only if the current node is the master node or if sync is set to true
// ie The request is generated by the nodes package as part of the node address syncing process.
// Testing this is going to be a PAIN IN THE ARSE!
if nodes.CurrentNodeAddress == nodes.MasterNode || sync == true {
status := nodes.RegNode(payload)
if status {
w.WriteHeader(http.StatusOK)
w.Write([]byte(req.RemoteAddr))
} else {
log.Println("Already present!")
writeErrorResponse("Already present", w)
}
} else {
// Pass the recieved node address to the master node for registering
log.Println("rerouting to master node!")
nodes.SyncNode(nodes.MasterNode, payload, true)
}
}
func ShowNodes(w http.ResponseWriter, req *http.Request) {
nodeList := []string{}
for addr := range nodes.NodeList() {
nodeList = append(nodeList, addr)
}
data, err := json.Marshal(nodeList)
if err != nil {
panic(err)
}
w.WriteHeader(http.StatusOK)
w.Header().Set("Content-Type", "text")
w.Write(data)
}
func writeJSONResponse(payload []byte, w http.ResponseWriter) {
w.WriteHeader(http.StatusOK)
w.Header().Set("Content-Type", "application/json")
w.Write(payload)
}
func decodeBody(d *json.Decoder) (t datatypes.Transaction, e error) {
e = d.Decode(&t)
return
}
func writeErrorResponse(e string, w http.ResponseWriter) {
w.WriteHeader(http.StatusUnprocessableEntity)
w.Write([]byte(e))
}
func decodeNodeAddress(data map[string]interface{}) (string, bool) {
payload, _ := data["Address"].(string)
sync, present := data["sync"].(bool)
if !present {
sync = false
}
return payload, sync
}