Commit 65d214f47d49a6a5637598d8fac7523f5fb40fa8

Authored by Marko Tikvić
1 parent 32a277faa6
Exists in master

improved middleware: more control over content type

... ... @@ -171,7 +171,7 @@ func GetTokenClaims(req *http.Request) (*TokenClaims, error) {
171 171 if ok := strings.HasPrefix(authHead, "Bearer "); ok {
172 172 tokstr = strings.TrimPrefix(authHead, "Bearer ")
173 173 } else {
174   - return &TokenClaims{}, errors.New("authorization header in incomplete")
  174 + return &TokenClaims{}, errors.New("authorization header is incomplete")
175 175 }
176 176  
177 177 token, err := jwt.ParseWithClaims(tokstr, &TokenClaims{}, secretFunc)
... ...
... ... @@ -51,14 +51,12 @@ func (r *StatusRecorder) Size() int {
51 51  
52 52 // NotFoundHandlerFunc writes HTTP error 404 to w.
53 53 func NotFoundHandlerFunc(w http.ResponseWriter, req *http.Request) {
54   - SetDefaultHeaders(w)
55   - if req.Method == "OPTIONS" {
56   - return
57   - }
  54 + SetAccessControlHeaders(w)
  55 + SetContentType(w, "application/json")
58 56 NotFound(w, req, fmt.Sprintf("Resource you requested was not found: %s", req.URL.String()))
59 57 }
60 58  
61   -// SetContentType ...
  59 +// SetContentType must be called before SetResponseStatus (w.WriteHeader) (?)
62 60 func SetContentType(w http.ResponseWriter, ctype string) {
63 61 w.Header().Set("Content-Type", ctype)
64 62 }
... ... @@ -73,12 +71,11 @@ func WriteResponse(w http.ResponseWriter, content []byte) {
73 71 w.Write(content)
74 72 }
75 73  
76   -// SetDefaultHeaders set's default headers for an HTTP response.
77   -func SetDefaultHeaders(w http.ResponseWriter) {
  74 +// SetAccessControlHeaders set's default headers for an HTTP response.
  75 +func SetAccessControlHeaders(w http.ResponseWriter) {
78 76 w.Header().Set("Access-Control-Allow-Origin", "*")
79 77 w.Header().Set("Access-Control-Allow-Methods", "POST, GET, PUT, DELETE, OPTIONS")
80 78 w.Header().Set("Access-Control-Allow-Headers", "Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization")
81   - SetContentType(w, "application/json; charset=utf-8")
82 79 }
83 80  
84 81 // GetLocale ...
... ... @@ -100,11 +97,13 @@ func Success(w http.ResponseWriter, payload interface{}, code int) {
100 97  
101 98 // OK ...
102 99 func OK(w http.ResponseWriter, payload interface{}) {
  100 + SetContentType(w, "application/json")
103 101 Success(w, payload, http.StatusOK)
104 102 }
105 103  
106 104 // Created ...
107 105 func Created(w http.ResponseWriter, payload interface{}) {
  106 + SetContentType(w, "application/json")
108 107 Success(w, payload, http.StatusCreated)
109 108 }
110 109  
... ... @@ -122,30 +121,36 @@ func Error(w http.ResponseWriter, r *http.Request, code int, err string) {
122 121  
123 122 // BadRequest ...
124 123 func BadRequest(w http.ResponseWriter, r *http.Request, err string) {
  124 + SetContentType(w, "application/json")
125 125 Error(w, r, http.StatusBadRequest, err)
126 126 }
127 127  
128 128 // Unauthorized ...
129 129 func Unauthorized(w http.ResponseWriter, r *http.Request, err string) {
  130 + SetContentType(w, "application/json")
130 131 Error(w, r, http.StatusUnauthorized, err)
131 132 }
132 133  
133 134 // Forbidden ...
134 135 func Forbidden(w http.ResponseWriter, r *http.Request, err string) {
  136 + SetContentType(w, "application/json")
135 137 Error(w, r, http.StatusForbidden, err)
136 138 }
137 139  
138 140 // NotFound ...
139 141 func NotFound(w http.ResponseWriter, r *http.Request, err string) {
  142 + SetContentType(w, "application/json")
140 143 Error(w, r, http.StatusNotFound, err)
141 144 }
142 145  
143 146 // Conflict ...
144 147 func Conflict(w http.ResponseWriter, r *http.Request, err string) {
  148 + SetContentType(w, "application/json")
145 149 Error(w, r, http.StatusConflict, err)
146 150 }
147 151  
148 152 // InternalServerError ...
149 153 func InternalServerError(w http.ResponseWriter, r *http.Request, err string) {
  154 + SetContentType(w, "application/json")
150 155 Error(w, r, http.StatusInternalServerError, err)
151 156 }
... ...
middleware/main.go
... ... @@ -5,17 +5,17 @@ import (
5 5 )
6 6  
7 7 func Headers(h http.HandlerFunc) http.HandlerFunc {
8   - return IgnoreOptionsRequests(ParseForm(h))
  8 + return SetAccessControlHeaders(IgnoreOptionsRequests(ParseForm(h)))
9 9 }
10 10  
11   -func AuthOnly(roles string, h http.HandlerFunc) http.HandlerFunc {
12   - return IgnoreOptionsRequests(ParseForm(Auth(roles, h)))
  11 +func AuthUser(roles string, h http.HandlerFunc) http.HandlerFunc {
  12 + return SetAccessControlHeaders(IgnoreOptionsRequests(ParseForm(Auth(roles, h))))
13 13 }
14 14  
15   -func Full(roles string, h http.HandlerFunc) http.HandlerFunc {
16   - return IgnoreOptionsRequests(ParseForm(LogTraffic(Auth(roles, h))))
  15 +func AuthUserLogTraffic(roles string, h http.HandlerFunc) http.HandlerFunc {
  16 + return SetAccessControlHeaders(IgnoreOptionsRequests(ParseForm(LogHTTP(Auth(roles, h)))))
17 17 }
18 18  
19 19 func LogTraffic(h http.HandlerFunc) http.HandlerFunc {
20   - return IgnoreOptionsRequests(ParseForm(LogRequestAndResponse(h)))
  20 + return SetAccessControlHeaders(IgnoreOptionsRequests(ParseForm(LogHTTP(h))))
21 21 }
... ...
middleware/middleware.go
... ... @@ -11,13 +11,21 @@ import (
11 11  
12 12 var httpLogger *gologger.Logger
13 13  
  14 +func SetAccessControlHeaders(h http.HandlerFunc) http.HandlerFunc {
  15 + return func(w http.ResponseWriter, req *http.Request) {
  16 + web.SetAccessControlHeaders(w)
  17 +
  18 + h(w, req)
  19 + }
  20 +}
  21 +
14 22 // IgnoreOptionsRequests ...
15 23 func IgnoreOptionsRequests(h http.HandlerFunc) http.HandlerFunc {
16 24 return func(w http.ResponseWriter, req *http.Request) {
17   - web.SetDefaultHeaders(w)
18 25 if req.Method == http.MethodOptions {
19 26 return
20 27 }
  28 +
21 29 h(w, req)
22 30 }
23 31 }
... ... @@ -30,6 +38,7 @@ func ParseForm(h http.HandlerFunc) http.HandlerFunc {
30 38 web.BadRequest(w, req, err.Error())
31 39 return
32 40 }
  41 +
33 42 h(w, req)
34 43 }
35 44 }
... ... @@ -42,6 +51,7 @@ func ParseMultipartForm(h http.HandlerFunc) http.HandlerFunc {
42 51 web.BadRequest(w, req, err.Error())
43 52 return
44 53 }
  54 +
45 55 h(w, req)
46 56 }
47 57 }
... ... @@ -51,26 +61,27 @@ func SetLogger(logger *gologger.Logger) {
51 61 httpLogger = logger
52 62 }
53 63  
54   -// LogRequestAndResponse ...
55   -func LogRequestAndResponse(h http.HandlerFunc) http.HandlerFunc {
  64 +// LogHTTP ...
  65 +func LogHTTP(h http.HandlerFunc) http.HandlerFunc {
56 66 return func(w http.ResponseWriter, req *http.Request) {
57   - if httpLogger != nil {
58   - t1 := time.Now()
  67 + if httpLogger == nil {
  68 + h(w, req)
  69 + return
  70 + }
59 71  
60   - claims, _ := web.GetTokenClaims(req)
61   - in := httpLogger.LogHTTPRequest(req, claims.Username)
  72 + t1 := time.Now()
62 73  
63   - rec := web.NewStatusRecorder(w)
  74 + claims, _ := web.GetTokenClaims(req)
  75 + in := httpLogger.LogHTTPRequest(req, claims.Username)
64 76  
65   - h(rec, req)
  77 + rec := web.NewStatusRecorder(w)
66 78  
67   - t2 := time.Now()
68   - out := httpLogger.LogHTTPResponse(rec.Status(), t2.Sub(t1), rec.Size())
  79 + h(rec, req)
69 80  
70   - httpLogger.CombineHTTPLogs(in, out)
71   - } else {
72   - h(w, req)
73   - }
  81 + t2 := time.Now()
  82 + out := httpLogger.LogHTTPResponse(rec.Status(), t2.Sub(t1), rec.Size())
  83 +
  84 + httpLogger.CombineHTTPLogs(in, out)
74 85 }
75 86 }
76 87  
... ... @@ -81,6 +92,7 @@ func Auth(roles string, h http.HandlerFunc) http.HandlerFunc {
81 92 web.Unauthorized(w, req, err.Error())
82 93 return
83 94 }
  95 +
84 96 h(w, req)
85 97 }
86 98 }
... ...