auth

Paddy 2014-12-14 Parent:5bccbed6631b Child:2e4b5722eed0

104:bc77a315f823 Go to Latest

auth/request.go

Add request helpers. Fix a typo in the requestErrConflict constant. Create a response type that is used to build responses before sending them down the wire. Create vars for a few common types of error responses that never change. Create a negotiate middleware function that will respond with a 406 error if the client requests an encoding that we can't support. Create an encode helper that determines the requested encoding and uses it to send the data down the wire. Move our wrap middleware from the oauth2.go file to the request.go file, where it's more likely to be looked for.

History
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 }