auth
auth/request.go
Add JSON tags and profile handler registration. Add JSON tags to all our profile types. Make an invalid email format error return requestErrInvalidFormat, not requestErrInvalidValue. Add a RegisterProfileHandlers to associate the handlers regarding profiles with the specified router. Replace our TODOs to send data down the wire with calls to our encode helper.
1 package auth
3 import (
4 "encoding/json"
5 "log"
6 "net/http"
8 "bitbucket.org/ww/goautoneg"
9 )
11 const (
12 requestErrAccessDenied = "access_denied"
13 requestErrInsufficient = "insufficient"
14 requestErrOverflow = "overflow"
15 requestErrInvalidValue = "invalid_value"
16 requestErrInvalidFormat = "invalid_format"
17 requestErrMissing = "missing"
18 requestErrNotFound = "not_found"
19 requestErrConflict = "conflict"
20 requestErrActOfGod = "act_of_god"
21 )
23 var (
24 actOfGodResponse = response{Errors: []requestError{requestError{Slug: requestErrActOfGod}}}
25 invalidFormatResponse = response{Errors: []requestError{requestError{Slug: requestErrInvalidFormat, Field: "/"}}}
27 encoders = []string{"application/json"}
28 )
30 type response struct {
31 Errors []requestError `json:"errors,omitempty"`
32 Logins []Login `json:"logins,omitempty"`
33 Profiles []Profile `json:"profiles,omitempty"`
34 }
36 type requestError struct {
37 Slug string `json:"error,omitempty"`
38 Field string `json:"field,omitempty"`
39 Param string `json:"param,omitempty"`
40 Header string `json:"header,omitempty"`
41 }
43 func negotiate(h http.Handler) http.Handler {
44 return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
45 contentType := goautoneg.Negotiate(r.Header.Get("Accept"), encoders)
46 if contentType == "" {
47 w.WriteHeader(http.StatusNotAcceptable)
48 log.Println("Unsupported Accept header:", r.Header.Get("Accept"))
49 w.Write([]byte("Unsupported content type requested: " + r.Header.Get("Accept")))
50 return
51 }
52 h.ServeHTTP(w, r)
53 })
54 }
56 func encode(w http.ResponseWriter, r *http.Request, status int, resp response) {
57 contentType := goautoneg.Negotiate(r.Header.Get("Accept"), encoders)
58 w.Header().Set("content-type", contentType)
59 w.WriteHeader(status)
60 var err error
61 switch contentType {
62 case "application/json":
63 enc := json.NewEncoder(w)
64 err = enc.Encode(resp)
65 }
66 if err != nil {
67 log.Println(err)
68 }
69 }
71 func wrap(context Context, f func(w http.ResponseWriter, r *http.Request, context Context)) http.Handler {
72 return negotiate(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
73 f(w, r, context)
74 }))
75 }