-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.go
227 lines (184 loc) · 12.2 KB
/
main.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
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
package main // Entry point, main func, packaged.
// Modules
import (
"encoding/json" // Data Type (json) Conversion/Parsing.
"log" // Error Logging.
"math/rand"
"net/http" // Basic REST API infrastructure.
"strconv" // Data Type (string) Conversion/Parsing.
"github.com/gorilla/mux" // HTTP router and URI/Path matching, for web servers. REST API infrastructure.
)
// Contact struct type to act as template for each record, added to our sudo-database. Contains fields to capture data & perform CRUD operations against.
type Contact struct {
ID int `json:"ID"`
Name string `json:"Name"`
Email string `json:"Email"`
Contact int `json:"Contact"`
}
// Contacts represents empty instance of our sudo-database, to store contact records.
var Contacts []Contact
/*
w.Write([]byte(fmt.Sprintf(`{"ID": %d, "Name": "%s", "Email": "%s", "Contact": %d }`, int, str, str, int))) // return data.
*/
// Handler function/method, that staisfies Handler interface. Called on "/home" GET Request, (handles this request path).
func homePage(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "text/html") // Tell client json is sent back in response, so client understands it.
http.ServeFile(w, r, "index.html")
}
// Handler function/method, that staisfies Handler interface. Called on "/new" POST Request, (handles this request path). JSON Data to be sent in request body.
func postNewContact(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json") // Tell client json is sent back in response, so client understands it.
r.ParseForm() // Parses the request body in a key value map.
x := r.Form // Store the parsed form.
//decoder := json.NewDecoder(r.Body) // New decoder, that reads request, to decode JSON in the request body.
contactNumber, err := strconv.Atoi(x["contact"][0]) // Parse query string as Int.
if err != nil { //Error: ID query string passed is not a number.
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte(`{"message": "Contact Number is not a number!"}`))
return
}
var newContact Contact
// Assign Request body data as new contact to be added to db.
newContact.ID = rand.Intn(1000) // Assign random ID integer between 1 and 1000.
newContact.Name = x["name"][0]
newContact.Email = x["email"][0]
newContact.Contact = contactNumber
Contacts = append(Contacts, newContact) // Append new contact to current db of contacts.
json.NewEncoder(w).Encode(Contacts) // Display full contacts db.
w.WriteHeader(http.StatusCreated) // Respond with status 201, to indicate successful creation request.
}
// Handler function/method, that staisfies Handler interface. Called on "/find?id=<id>" GET Request, (handles this request path).
func getContact(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json") // Tell client json is sent back in response, so client understands it.
query := r.URL.Query() // Get all query params sent with URL.
ID := query.Get("id") // Get the id query param.
intID, err := strconv.Atoi(ID) // Parse query string as Int.
if err != nil { //Error: ID query string passed is not a number.
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte(`{"message": "ID is not a number!"}`))
return
}
// Iterate through queryContacts (all contact records), where index is assigned the full range of indexes in Contacts db.
for _, queryContacts := range Contacts {
if queryContacts.ID == intID { // Check id against queried id.
json.NewEncoder(w).Encode(queryContacts) // Encode into json string, and write as part of response 'w'.
}
}
w.WriteHeader(http.StatusOK) // Respond with status 200, to indicate successful request.
}
// Handler function/method, that staisfies Handler interface. Called on "/all" GET Request, (handles this request path).
func getAllContacts(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json") // Tell client json is sent back in response, so client understands it.
json.NewEncoder(w).Encode(Contacts) // Write all contacts in response.
w.WriteHeader(http.StatusOK) // Respond with status 200, to indicate successful request.
}
// Handler function/method, that staisfies Handler interface. Called on "/update?id=<id>" PUT Request, (handles this request path). JSON Data to be sent in request body.
func putUpdateContact(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json") // Tell client json is sent back in response, so client understands it.
query := r.URL.Query() // Get all query params sent with URL.
ID := query.Get("id") // Get the id query param.
intID, err := strconv.Atoi(ID) // Parse query string as Int.
if err != nil { //Error: ID query string passed is not a number.
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte(`{"message": "ID is not a number!"}`))
return
}
r.ParseForm() // Parses the request body in a key value map.
x := r.Form // Store the parsed form.
//decoder := json.NewDecoder(r.Body) // New decoder, that reads request, to decode JSON in the request body.
contactNumber, err := strconv.Atoi(x["contact"][0]) // Parse query string as Int.
if err != nil { //Error: ID query string passed is not a number.
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte(`{"message": "Contact Number is not a number!"}`))
return
}
var updateData Contact
updateData.Name = x["name"][0]
updateData.Email = x["email"][0]
updateData.Contact = contactNumber
for index, contact := range Contacts { // Iterate through all contact records.
if contact.ID == intID { // Locate client specified id record.
updateData.ID = contact.ID // Assign current ID as updated contacts ID number.
Contacts = append(Contacts[:index], Contacts[index+1:]...) // Delete specified contact.
Contacts = append(Contacts, updateData) // Append new contacts list with updated contact, for full complete list.
json.NewEncoder(w).Encode(Contacts) // Encode into json string, and write as part of response 'w' sent.
}
}
w.WriteHeader(http.StatusAccepted) // Respond with status 201, to indicate successful creation request.
}
// Handler function/method, that staisfies Handler interface. Called on "/delete?id=<id>" DELETE Request, (handles this request path).
func deleteContact(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json") // Tell client json is sent back in response, so client understands it.
query := r.URL.Query() // Get all query params sent with URL.
ID := query.Get("id") // Get the id query param.
intID, err := strconv.Atoi(ID) // Parse query string as Int.
if err != nil { //Error: ID query string passed is not a number.
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte(`{"message": "ID is not a number!"}`))
return
}
for index, contact := range Contacts { // Iterate through all contact records.
if contact.ID == intID { // Locate client specified id record.
Contacts = append(Contacts[:index], Contacts[index+1:]...) // Delete specified contact.
json.NewEncoder(w).Encode(Contacts) // Encode into json string, and write as part of response 'w' sent.
}
}
w.WriteHeader(http.StatusOK) // Respond with status 200, to indicate successful request.
}
// Handler function/method, that staisfies Handler interface. Called on "/deleteAll" DELETE Request, (handles this request path).
func deleteAllContacts(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json") // Tell client json is sent back in response, so client understands it.
Contacts = nil // Delete all Contacts data.
json.NewEncoder(w).Encode(Contacts) // Encode into json string, and write as part of response 'w' sent.
w.WriteHeader(http.StatusOK) // Respond with status 200, to indicate successful request.
}
// Handler function/method for POST Request (Create), that staisfies Handler interface.
func post(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json") // Tell client json is sent back in response, so client understands it.
w.WriteHeader(http.StatusCreated) // Respond with status 201, to indicate successful creation request.
w.Write([]byte(`{"message": "http POST Request (Create)"}`))
}
// Handler function/method for GET Request (Read), that staisfies Handler interface.
func get(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json") // Tell client json is sent back in response, so client understands it.
w.WriteHeader(http.StatusOK) // Respond with status 200, to indicate successful request.
w.Write([]byte(`{"message": "http GET Request (Read)"}`))
}
// Handler function/method for POST Request (Update), that staisfies Handler interface.
func put(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json") // Tell client json is sent back in response, so client understands it.
w.WriteHeader(http.StatusAccepted) // Respond with status 202, to indicate accpeted request, but not acted upon.
w.Write([]byte(`{"message": "http PUT Request (Update)"}`))
}
// Handler function/method for DELETE Request (Delete), that staisfies Handler interface.
func delete(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json") // Tell client json is sent back in response, so client understands it.
w.WriteHeader(http.StatusOK) // Respond with status 200, to indicate successful request.
w.Write([]byte(`{"message": "http DELETE Request (Delete)"}`))
}
// Handler function/method for any exceptions/errors, that staisfies Handler interface.
func notFound(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json") // Tell client json is sent back in response, so client understands it.
w.WriteHeader(http.StatusNotFound) // 404 error.
w.Write([]byte(`{"message": "not found: Error 404 - Caught!"}`)) // Error handling/catching.
}
// Main entry point into API App, packaged. Provides all routing, and initialise server.
func main() {
// Init API infrastructure.
r := mux.NewRouter() // Init instance of request router/handler (interface?).
api := r.PathPrefix("/api/v0-1").Subrouter() // New sub-router. "/api/v1", i.e.: "localhost:8080/api/v1/{endpoint}".
// Handles given pattern/end-points/routes, to execute the given handler function, for each given request type received.
api.HandleFunc("", get).Methods(http.MethodGet) // localhost:8080/api/v0-1/
api.HandleFunc("", post).Methods(http.MethodPost) // localhost:8080/api/v0-1/
api.HandleFunc("", put).Methods(http.MethodPut) // localhost:8080/api/v0-1/
api.HandleFunc("", delete).Methods(http.MethodDelete) // localhost:8080/api/v0-1/
api.HandleFunc("", notFound) // localhost:8080/api/v0-1/
api.HandleFunc("/contacts/home", homePage).Methods(http.MethodGet) // localhost:8080/api/v0-1/contacts/home
api.HandleFunc("/contacts/new", postNewContact).Methods(http.MethodPost) // localhost:8080/api/v0-1/contacts/new
api.HandleFunc("/contacts/all", getAllContacts).Methods(http.MethodGet) // localhost:8080/api/v0-1/contacts/all
api.HandleFunc("/contacts/find", getContact).Methods(http.MethodGet) // localhost:8080/api/v0-1/contacts/find?id=<id>
api.HandleFunc("/contacts/update", putUpdateContact).Methods(http.MethodPut) // localhost:8080/api/v0-1/contacts/update?id=<id>
api.HandleFunc("/contacts/delete", deleteContact).Methods(http.MethodDelete) // localhost:8080/api/v0-1/contacts/delete?id=<id>
api.HandleFunc("/contacts/deleteAll", deleteAllContacts).Methods(http.MethodDelete) // localhost:8080/api/v0-1/contacts/deleteAll
log.Fatal(http.ListenAndServe(":8080", r)) // Listens for incoming TCP connection requests. Set port, to open local server on and handle the incoming requests.
}