@@ -14,7 +14,7 @@ import (
14
14
Concerns:
15
15
1) the server depends on a hard type, coupling to the exact inmem db
16
16
a) what happens if we want a different db?
17
- 2) auth is copy-pasted in each handler
17
+ ✅ 2) auth is copy-pasted in each handler
18
18
a) what happens if we forget that copy pasta?
19
19
3) auth is hardcoded to basic auth
20
20
a) what happens if we want to adapt some other means of auth?
@@ -81,11 +81,13 @@ func NewServer(db *InmemDB, user, pass string, opts ...func(*Server)) *Server {
81
81
}
82
82
83
83
func (s * Server ) routes () {
84
+ authMW := BasicAuth (s .user , s .pass ) // 2)
85
+
84
86
// 4) 7) 9) 10)
85
- s .mux .Handle ("POST /foo" , http .HandlerFunc (s .createFoo ))
86
- s .mux .Handle ("GET /foo" , http .HandlerFunc (s .readFoo ))
87
- s .mux .Handle ("PUT /foo" , http .HandlerFunc (s .updateFoo ))
88
- s .mux .Handle ("DELETE /foo" , http .HandlerFunc (s .delFoo ))
87
+ s .mux .Handle ("POST /foo" , authMW ( http .HandlerFunc (s .createFoo ) ))
88
+ s .mux .Handle ("GET /foo" , authMW ( http .HandlerFunc (s .readFoo ) ))
89
+ s .mux .Handle ("PUT /foo" , authMW ( http .HandlerFunc (s .updateFoo ) ))
90
+ s .mux .Handle ("DELETE /foo" , authMW ( http .HandlerFunc (s .delFoo ) ))
89
91
}
90
92
91
93
func (s * Server ) ServeHTTP (w http.ResponseWriter , r * http.Request ) {
@@ -101,12 +103,6 @@ type Foo struct {
101
103
}
102
104
103
105
func (s * Server ) createFoo (w http.ResponseWriter , r * http.Request ) {
104
- // 2)
105
- if user , pass , ok := r .BasicAuth (); ! (ok && user == s .user && pass == s .pass ) {
106
- w .WriteHeader (http .StatusUnauthorized ) // 9)
107
- return
108
- }
109
-
110
106
var f Foo
111
107
if err := json .NewDecoder (r .Body ).Decode (& f ); err != nil {
112
108
w .WriteHeader (http .StatusForbidden ) // 9)
@@ -127,12 +123,6 @@ func (s *Server) createFoo(w http.ResponseWriter, r *http.Request) {
127
123
}
128
124
129
125
func (s * Server ) readFoo (w http.ResponseWriter , r * http.Request ) {
130
- // 2)
131
- if user , pass , ok := r .BasicAuth (); ! (ok && user == s .user && pass == s .pass ) {
132
- w .WriteHeader (http .StatusUnauthorized ) // 9)
133
- return
134
- }
135
-
136
126
f , err := s .db .readFoo (r .URL .Query ().Get ("id" ))
137
127
if err != nil {
138
128
w .WriteHeader (http .StatusNotFound ) // 9)
@@ -145,12 +135,6 @@ func (s *Server) readFoo(w http.ResponseWriter, r *http.Request) {
145
135
}
146
136
147
137
func (s * Server ) updateFoo (w http.ResponseWriter , r * http.Request ) {
148
- // 2)
149
- if user , pass , ok := r .BasicAuth (); ! (ok && user == s .user && pass == s .pass ) {
150
- w .WriteHeader (http .StatusUnauthorized ) // 9)
151
- return
152
- }
153
-
154
138
var f Foo
155
139
if err := json .NewDecoder (r .Body ).Decode (& f ); err != nil {
156
140
w .WriteHeader (http .StatusForbidden ) // 9)
@@ -164,18 +148,26 @@ func (s *Server) updateFoo(w http.ResponseWriter, r *http.Request) {
164
148
}
165
149
166
150
func (s * Server ) delFoo (w http.ResponseWriter , r * http.Request ) {
167
- // 2)
168
- if user , pass , ok := r .BasicAuth (); ! (ok && user == s .user && pass == s .pass ) {
169
- w .WriteHeader (http .StatusUnauthorized ) // 9)
170
- return
171
- }
172
-
173
151
if err := s .db .delFoo (r .URL .Query ().Get ("id" )); err != nil {
174
152
w .WriteHeader (http .StatusNotFound ) // 9)
175
153
return
176
154
}
177
155
}
178
156
157
+ // BasicAuth provides a basic auth middleware to an http server.
158
+ // 2)
159
+ func BasicAuth (expectedUser , expectedPass string ) func (http.Handler ) http.Handler {
160
+ return func (next http.Handler ) http.Handler {
161
+ return http .HandlerFunc (func (w http.ResponseWriter , r * http.Request ) {
162
+ if user , pass , ok := r .BasicAuth (); ! (ok && user == expectedUser && pass == expectedPass ) {
163
+ w .WriteHeader (http .StatusUnauthorized ) // 9)
164
+ return
165
+ }
166
+ next .ServeHTTP (w , r )
167
+ })
168
+ }
169
+ }
170
+
179
171
// InmemDB is an in-memory store.
180
172
type InmemDB struct {
181
173
m []Foo // 12)
0 commit comments