/
rest_app.go
229 lines (179 loc) · 4.92 KB
/
rest_app.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
228
229
/*
* this demo shows how to implement a full RESTful web-app
* with data Persistence "using postgresSQL as our data-store"
**/
package main
import (
"database/sql"
"fmt"
"log"
"net/http"
_ "github.com/lib/pq"
)
var (
dbConnection *sql.DB
)
func init() {
var err error
//Create the Connection Pool
dbConnection, err = sql.Open("postgres", "user=gopher password=1111aaaa dbname=reset_demo sslmode=disable")
//check for err
if err != nil {
log.Fatal(err)
return
}
//Check for the database Connectivity, because the sql.Open() doesn't perform it
if err = dbConnection.Ping(); err != nil {
log.Fatal(err)
return
}
fmt.Println("Database Connection Established!")
// Prints logs in the format 2009/01/23 01:23:23 /a/b/c/d.go:23
log.SetFlags(Ldate | Ltime | log.Llongfile)
}
type Customer struct {
uid string
name string
email string
}
func main() {
//Create Routes and related actions!
http.HandleFunc("/customers", customers)
http.HandleFunc("/customers/show", customersShow) // -> link like localhost:3000/customers/show?uid= 29929
http.HandleFunc("/customers/create", customersCreate)
//Start The Server
http.ListenAndServe(":3000", nil)
}
//Handle the third route /customers/create
func customersCreate(w http.ResponseWriter, r *http.Request) {
//check if the Method is Post
if r.Method != http.MethodPost {
http.Error(w, http.StatusText(405), 405)
log.Println(w)
return
}
// get params from the post Request
var (
uid = r.FormValue("uid")
name = r.FormValue("name")
email = r.FormValue("email")
)
//check if they are empty
if uid == "" || name == "" || email == "" {
//Bad Request ... we need a uid !
http.Error(w, http.StatusText(400), 400)
log.Println(w)
return
}
//Build the Query String
query := "INSERT INTO reset_demo.customer VALUES($1,$2,$3)"
//execute the insert Query
result, err := dbConnection.Exec(query, uid, name, email)
//check if any error
if err != nil {
http.Error(w, http.StatusText(500), 500)
log.Println(err)
return
}
//check how many rows affected (added or modified in case of update!!!)
rowsAffected, err := result.RowsAffected()
if err != nil {
http.Error(w, http.StatusText(500), 500)
log.Println(err)
return
}
// output the result
fmt.Fprintf(w, " Customer %s created Succesfully (%d rows affected! ) \n", uid, rowsAffected)
}
// handle the second route /customers/show
func customersShow(w http.ResponseWriter, r *http.Request) {
//check the request Method again
if r.Method != http.MethodGet {
http.Error(w, http.StatusText(405), 405)
log.Println(w)
return
}
/// get the UID from the request
uid := r.FormValue("uid")
//check if the uid isn't empty
if uid == "" {
//Bad Request ... we need a uid !
http.Error(w, http.StatusText(400), 400)
log.Println(w)
return
}
//build the Query String
query := "SELECT * FROM reset_demo.customer WHERE uid=$1"
//Execute the query
row := dbConnection.QueryRow(query, uid)
//create a new Customer object to hold data
ctm := new(Customer)
//scan data from the row
err := row.Scan(&ctm.uid, &ctm.name, &ctm.email)
//check if any error !
if err != nil {
//First we need to check if no row is found !
if err == sql.ErrNoRows {
http.NotFound(w, r)
log.Println(err)
return
}
// internal error
http.Error(w, http.StatusText(500), 500)
log.Println(err)
return
}
// output the result
fmt.Fprintf(w, "uid:%s name:%s email:%s", ctm.uid, ctm.name, ctm.email)
}
// handle the First route /customers
func customers(w http.ResponseWriter, r *http.Request) {
// Check the Method sent
// We are looking for a GET method or the app will die/ stoped
if r.Method != http.MethodGet {
//any other method is not allowed !
http.Error(w, http.StatusText(405), 405)
//log the error to the console
log.Println(w)
return
}
// create the query string
query := "SELECT * FROM reset_demo.customer"
//Execute the Query
rows, err := dbConnection.Query(query)
if err != nil {
//Internal error
http.Error(w, http.StatusText(500), 500)
log.Println(err)
return
}
defer rows.Close() // Always close opened any resources
//create a new slice of Customer Object to hold all retrieved data
ctms := make([]*Customer, 0)
//Loop Over the rows
for rows.Next() {
//create a Customer to hold one row
ctm := new(Customer)
//Scan For data and fill the customer fields
err := rows.Scan(&ctm.uid, &ctm.name, &ctm.email)
if err != nil {
http.Error(w, http.StatusText(500), 500)
log.Println(err)
return
}
// append ctm to ctms slice
ctms = append(ctms, ctm)
}
// check for any errors occured during the retrieving process!!! might happened
if err := rows.Err(); err != nil {
http.Error(w, http.StatusText(500), 500)
log.Println(err)
return
}
//Send data to the output
fmt.Fprintln(w, "Customers List")
//Loopr Over Ctms to print the customers list
for _, ctm := range ctms {
fmt.Fprintf(w, "uid:%s name:%s email:%s", ctm.uid, ctm.name, ctm.email)
}
}