forked from ardanlabs/gotraining
-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.go
138 lines (108 loc) · 3.42 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
// All material is licensed under the Apache License Version 2.0, January 2004
// http://www.apache.org/licenses/LICENSE-2.0
// Sample program to show how to use a regex to handle REST based
// URL schemas and routes.
package main
import (
"errors"
"fmt"
"log"
"net/http"
"regexp"
"strconv"
"github.com/ardanlabs/gotraining/topics/web/customer"
)
// App handles the routing of all the incoming customer
// requests into the server.
func App() http.Handler {
// The regex allows us to match `/customers/:id`
rx := regexp.MustCompile(`^/([^/]+)/?(\d*)$`)
h := func(res http.ResponseWriter, req *http.Request) {
log.Printf("[%s] %s\n", req.Method, req.URL.Path)
// Validate we have a customer url.
m := rx.FindAllStringSubmatch(req.URL.Path, -1)
if len(m) == 0 {
// Redirect to `/customers` if there isn't a match.
http.Redirect(res, req, "/customers", http.StatusPermanentRedirect)
return
}
// Extract the id portion of the customer url, `/customers/:id`.
idStr := m[0][2]
switch {
case req.Method == "GET":
// Show the content of the requested customer.
if idStr != "" {
showHandler(res, req, idStr)
return
}
// Show the base index page.
indexHandler(res, req)
return
case req.Method == "POST":
// Show the create customer page.
createHandler(res, req)
return
// The request is not formatted properly.
default:
// The request does not conform to what we expect.
err := errors.New("invalid")
http.Error(res, err.Error(), http.StatusInternalServerError)
return
}
}
return http.HandlerFunc(h)
}
// indexHandler returns the entire list of customers in the DB.
func indexHandler(res http.ResponseWriter, req *http.Request) {
// Retrieve the list of customers and render the document.
err := customer.T.ExecuteTemplate(res, "index.html", customer.All())
if err != nil {
http.Error(res, err.Error(), http.StatusInternalServerError)
}
}
// createHandler adds new customers to the DB.
func createHandler(res http.ResponseWriter, req *http.Request) {
// Parse the raw query from the URL and update r.Form.
if err := req.ParseForm(); err != nil {
http.Error(res, err.Error(), http.StatusInternalServerError)
return
}
// Create a customer to save.
c := customer.Customer{
Name: req.FormValue("name"),
}
// Save the customer in the DB.
var err error
c.ID, err = customer.Save(c)
if err != nil {
http.Error(res, err.Error(), http.StatusInternalServerError)
return
}
// Redirect the user to the customer page.
http.Redirect(res, req, fmt.Sprintf("/customers/%d", c.ID), http.StatusSeeOther)
}
// showHandler provides information about the specified customer.
func showHandler(res http.ResponseWriter, req *http.Request, idStr string) {
// Convert the id to an integer.
id, err := strconv.Atoi(idStr)
if err != nil {
http.Error(res, err.Error(), http.StatusBadRequest)
return
}
// Find that customer in the database. If that customer does
// not exist, then return a 404 and stop processing the request.
c, err := customer.Find(id)
if err != nil {
http.Error(res, err.Error(), http.StatusNotFound)
return
}
// Render the show.html template to display the customer.
if err := customer.T.ExecuteTemplate(res, "show.html", c); err != nil {
http.Error(res, err.Error(), http.StatusInternalServerError)
}
}
func main() {
// Start the http server to handle the request for
// both versions of the API.
log.Fatal(http.ListenAndServe(":3000", App()))
}