barometer: update DMA's vendoring packages
[barometer.git] / src / dma / vendor / github.com / labstack / echo / context.go
1 package echo
2
3 import (
4         "bytes"
5         "encoding/json"
6         "encoding/xml"
7         "fmt"
8         "io"
9         "mime/multipart"
10         "net"
11         "net/http"
12         "net/url"
13         "os"
14         "path/filepath"
15         "strings"
16 )
17
18 type (
19         // Context represents the context of the current HTTP request. It holds request and
20         // response objects, path, path parameters, data and registered handler.
21         Context interface {
22                 // Request returns `*http.Request`.
23                 Request() *http.Request
24
25                 // SetRequest sets `*http.Request`.
26                 SetRequest(r *http.Request)
27
28                 // Response returns `*Response`.
29                 Response() *Response
30
31                 // IsTLS returns true if HTTP connection is TLS otherwise false.
32                 IsTLS() bool
33
34                 // IsWebSocket returns true if HTTP connection is WebSocket otherwise false.
35                 IsWebSocket() bool
36
37                 // Scheme returns the HTTP protocol scheme, `http` or `https`.
38                 Scheme() string
39
40                 // RealIP returns the client's network address based on `X-Forwarded-For`
41                 // or `X-Real-IP` request header.
42                 RealIP() string
43
44                 // Path returns the registered path for the handler.
45                 Path() string
46
47                 // SetPath sets the registered path for the handler.
48                 SetPath(p string)
49
50                 // Param returns path parameter by name.
51                 Param(name string) string
52
53                 // ParamNames returns path parameter names.
54                 ParamNames() []string
55
56                 // SetParamNames sets path parameter names.
57                 SetParamNames(names ...string)
58
59                 // ParamValues returns path parameter values.
60                 ParamValues() []string
61
62                 // SetParamValues sets path parameter values.
63                 SetParamValues(values ...string)
64
65                 // QueryParam returns the query param for the provided name.
66                 QueryParam(name string) string
67
68                 // QueryParams returns the query parameters as `url.Values`.
69                 QueryParams() url.Values
70
71                 // QueryString returns the URL query string.
72                 QueryString() string
73
74                 // FormValue returns the form field value for the provided name.
75                 FormValue(name string) string
76
77                 // FormParams returns the form parameters as `url.Values`.
78                 FormParams() (url.Values, error)
79
80                 // FormFile returns the multipart form file for the provided name.
81                 FormFile(name string) (*multipart.FileHeader, error)
82
83                 // MultipartForm returns the multipart form.
84                 MultipartForm() (*multipart.Form, error)
85
86                 // Cookie returns the named cookie provided in the request.
87                 Cookie(name string) (*http.Cookie, error)
88
89                 // SetCookie adds a `Set-Cookie` header in HTTP response.
90                 SetCookie(cookie *http.Cookie)
91
92                 // Cookies returns the HTTP cookies sent with the request.
93                 Cookies() []*http.Cookie
94
95                 // Get retrieves data from the context.
96                 Get(key string) interface{}
97
98                 // Set saves data in the context.
99                 Set(key string, val interface{})
100
101                 // Bind binds the request body into provided type `i`. The default binder
102                 // does it based on Content-Type header.
103                 Bind(i interface{}) error
104
105                 // Validate validates provided `i`. It is usually called after `Context#Bind()`.
106                 // Validator must be registered using `Echo#Validator`.
107                 Validate(i interface{}) error
108
109                 // Render renders a template with data and sends a text/html response with status
110                 // code. Renderer must be registered using `Echo.Renderer`.
111                 Render(code int, name string, data interface{}) error
112
113                 // HTML sends an HTTP response with status code.
114                 HTML(code int, html string) error
115
116                 // HTMLBlob sends an HTTP blob response with status code.
117                 HTMLBlob(code int, b []byte) error
118
119                 // String sends a string response with status code.
120                 String(code int, s string) error
121
122                 // JSON sends a JSON response with status code.
123                 JSON(code int, i interface{}) error
124
125                 // JSONPretty sends a pretty-print JSON with status code.
126                 JSONPretty(code int, i interface{}, indent string) error
127
128                 // JSONBlob sends a JSON blob response with status code.
129                 JSONBlob(code int, b []byte) error
130
131                 // JSONP sends a JSONP response with status code. It uses `callback` to construct
132                 // the JSONP payload.
133                 JSONP(code int, callback string, i interface{}) error
134
135                 // JSONPBlob sends a JSONP blob response with status code. It uses `callback`
136                 // to construct the JSONP payload.
137                 JSONPBlob(code int, callback string, b []byte) error
138
139                 // XML sends an XML response with status code.
140                 XML(code int, i interface{}) error
141
142                 // XMLPretty sends a pretty-print XML with status code.
143                 XMLPretty(code int, i interface{}, indent string) error
144
145                 // XMLBlob sends an XML blob response with status code.
146                 XMLBlob(code int, b []byte) error
147
148                 // Blob sends a blob response with status code and content type.
149                 Blob(code int, contentType string, b []byte) error
150
151                 // Stream sends a streaming response with status code and content type.
152                 Stream(code int, contentType string, r io.Reader) error
153
154                 // File sends a response with the content of the file.
155                 File(file string) error
156
157                 // Attachment sends a response as attachment, prompting client to save the
158                 // file.
159                 Attachment(file string, name string) error
160
161                 // Inline sends a response as inline, opening the file in the browser.
162                 Inline(file string, name string) error
163
164                 // NoContent sends a response with no body and a status code.
165                 NoContent(code int) error
166
167                 // Redirect redirects the request to a provided URL with status code.
168                 Redirect(code int, url string) error
169
170                 // Error invokes the registered HTTP error handler. Generally used by middleware.
171                 Error(err error)
172
173                 // Handler returns the matched handler by router.
174                 Handler() HandlerFunc
175
176                 // SetHandler sets the matched handler by router.
177                 SetHandler(h HandlerFunc)
178
179                 // Logger returns the `Logger` instance.
180                 Logger() Logger
181
182                 // Echo returns the `Echo` instance.
183                 Echo() *Echo
184
185                 // Reset resets the context after request completes. It must be called along
186                 // with `Echo#AcquireContext()` and `Echo#ReleaseContext()`.
187                 // See `Echo#ServeHTTP()`
188                 Reset(r *http.Request, w http.ResponseWriter)
189         }
190
191         context struct {
192                 request  *http.Request
193                 response *Response
194                 path     string
195                 pnames   []string
196                 pvalues  []string
197                 query    url.Values
198                 handler  HandlerFunc
199                 store    Map
200                 echo     *Echo
201         }
202 )
203
204 const (
205         defaultMemory = 32 << 20 // 32 MB
206         indexPage     = "index.html"
207         defaultIndent = "  "
208 )
209
210 func (c *context) writeContentType(value string) {
211         header := c.Response().Header()
212         if header.Get(HeaderContentType) == "" {
213                 header.Set(HeaderContentType, value)
214         }
215 }
216
217 func (c *context) Request() *http.Request {
218         return c.request
219 }
220
221 func (c *context) SetRequest(r *http.Request) {
222         c.request = r
223 }
224
225 func (c *context) Response() *Response {
226         return c.response
227 }
228
229 func (c *context) IsTLS() bool {
230         return c.request.TLS != nil
231 }
232
233 func (c *context) IsWebSocket() bool {
234         upgrade := c.request.Header.Get(HeaderUpgrade)
235         return upgrade == "websocket" || upgrade == "Websocket"
236 }
237
238 func (c *context) Scheme() string {
239         // Can't use `r.Request.URL.Scheme`
240         // See: https://groups.google.com/forum/#!topic/golang-nuts/pMUkBlQBDF0
241         if c.IsTLS() {
242                 return "https"
243         }
244         if scheme := c.request.Header.Get(HeaderXForwardedProto); scheme != "" {
245                 return scheme
246         }
247         if scheme := c.request.Header.Get(HeaderXForwardedProtocol); scheme != "" {
248                 return scheme
249         }
250         if ssl := c.request.Header.Get(HeaderXForwardedSsl); ssl == "on" {
251                 return "https"
252         }
253         if scheme := c.request.Header.Get(HeaderXUrlScheme); scheme != "" {
254                 return scheme
255         }
256         return "http"
257 }
258
259 func (c *context) RealIP() string {
260         if ip := c.request.Header.Get(HeaderXForwardedFor); ip != "" {
261                 return strings.Split(ip, ", ")[0]
262         }
263         if ip := c.request.Header.Get(HeaderXRealIP); ip != "" {
264                 return ip
265         }
266         ra, _, _ := net.SplitHostPort(c.request.RemoteAddr)
267         return ra
268 }
269
270 func (c *context) Path() string {
271         return c.path
272 }
273
274 func (c *context) SetPath(p string) {
275         c.path = p
276 }
277
278 func (c *context) Param(name string) string {
279         for i, n := range c.pnames {
280                 if i < len(c.pvalues) {
281                         if n == name {
282                                 return c.pvalues[i]
283                         }
284                 }
285         }
286         return ""
287 }
288
289 func (c *context) ParamNames() []string {
290         return c.pnames
291 }
292
293 func (c *context) SetParamNames(names ...string) {
294         c.pnames = names
295 }
296
297 func (c *context) ParamValues() []string {
298         return c.pvalues[:len(c.pnames)]
299 }
300
301 func (c *context) SetParamValues(values ...string) {
302         c.pvalues = values
303 }
304
305 func (c *context) QueryParam(name string) string {
306         if c.query == nil {
307                 c.query = c.request.URL.Query()
308         }
309         return c.query.Get(name)
310 }
311
312 func (c *context) QueryParams() url.Values {
313         if c.query == nil {
314                 c.query = c.request.URL.Query()
315         }
316         return c.query
317 }
318
319 func (c *context) QueryString() string {
320         return c.request.URL.RawQuery
321 }
322
323 func (c *context) FormValue(name string) string {
324         return c.request.FormValue(name)
325 }
326
327 func (c *context) FormParams() (url.Values, error) {
328         if strings.HasPrefix(c.request.Header.Get(HeaderContentType), MIMEMultipartForm) {
329                 if err := c.request.ParseMultipartForm(defaultMemory); err != nil {
330                         return nil, err
331                 }
332         } else {
333                 if err := c.request.ParseForm(); err != nil {
334                         return nil, err
335                 }
336         }
337         return c.request.Form, nil
338 }
339
340 func (c *context) FormFile(name string) (*multipart.FileHeader, error) {
341         _, fh, err := c.request.FormFile(name)
342         return fh, err
343 }
344
345 func (c *context) MultipartForm() (*multipart.Form, error) {
346         err := c.request.ParseMultipartForm(defaultMemory)
347         return c.request.MultipartForm, err
348 }
349
350 func (c *context) Cookie(name string) (*http.Cookie, error) {
351         return c.request.Cookie(name)
352 }
353
354 func (c *context) SetCookie(cookie *http.Cookie) {
355         http.SetCookie(c.Response(), cookie)
356 }
357
358 func (c *context) Cookies() []*http.Cookie {
359         return c.request.Cookies()
360 }
361
362 func (c *context) Get(key string) interface{} {
363         return c.store[key]
364 }
365
366 func (c *context) Set(key string, val interface{}) {
367         if c.store == nil {
368                 c.store = make(Map)
369         }
370         c.store[key] = val
371 }
372
373 func (c *context) Bind(i interface{}) error {
374         return c.echo.Binder.Bind(i, c)
375 }
376
377 func (c *context) Validate(i interface{}) error {
378         if c.echo.Validator == nil {
379                 return ErrValidatorNotRegistered
380         }
381         return c.echo.Validator.Validate(i)
382 }
383
384 func (c *context) Render(code int, name string, data interface{}) (err error) {
385         if c.echo.Renderer == nil {
386                 return ErrRendererNotRegistered
387         }
388         buf := new(bytes.Buffer)
389         if err = c.echo.Renderer.Render(buf, name, data, c); err != nil {
390                 return
391         }
392         return c.HTMLBlob(code, buf.Bytes())
393 }
394
395 func (c *context) HTML(code int, html string) (err error) {
396         return c.HTMLBlob(code, []byte(html))
397 }
398
399 func (c *context) HTMLBlob(code int, b []byte) (err error) {
400         return c.Blob(code, MIMETextHTMLCharsetUTF8, b)
401 }
402
403 func (c *context) String(code int, s string) (err error) {
404         return c.Blob(code, MIMETextPlainCharsetUTF8, []byte(s))
405 }
406
407 func (c *context) jsonPBlob(code int, callback string, i interface{}) (err error) {
408         enc := json.NewEncoder(c.response)
409         _, pretty := c.QueryParams()["pretty"]
410         if c.echo.Debug || pretty {
411                 enc.SetIndent("", "  ")
412         }
413         c.writeContentType(MIMEApplicationJavaScriptCharsetUTF8)
414         c.response.WriteHeader(code)
415         if _, err = c.response.Write([]byte(callback + "(")); err != nil {
416                 return
417         }
418         if err = enc.Encode(i); err != nil {
419                 return
420         }
421         if _, err = c.response.Write([]byte(");")); err != nil {
422                 return
423         }
424         return
425 }
426
427 func (c *context) json(code int, i interface{}, indent string) error {
428         enc := json.NewEncoder(c.response)
429         if indent != "" {
430                 enc.SetIndent("", indent)
431         }
432         c.writeContentType(MIMEApplicationJSONCharsetUTF8)
433         c.response.WriteHeader(code)
434         return enc.Encode(i)
435 }
436
437 func (c *context) JSON(code int, i interface{}) (err error) {
438         indent := ""
439         if _, pretty := c.QueryParams()["pretty"]; c.echo.Debug || pretty {
440                 indent = defaultIndent
441         }
442         return c.json(code, i, indent)
443 }
444
445 func (c *context) JSONPretty(code int, i interface{}, indent string) (err error) {
446         return c.json(code, i, indent)
447 }
448
449 func (c *context) JSONBlob(code int, b []byte) (err error) {
450         return c.Blob(code, MIMEApplicationJSONCharsetUTF8, b)
451 }
452
453 func (c *context) JSONP(code int, callback string, i interface{}) (err error) {
454         return c.jsonPBlob(code, callback, i)
455 }
456
457 func (c *context) JSONPBlob(code int, callback string, b []byte) (err error) {
458         c.writeContentType(MIMEApplicationJavaScriptCharsetUTF8)
459         c.response.WriteHeader(code)
460         if _, err = c.response.Write([]byte(callback + "(")); err != nil {
461                 return
462         }
463         if _, err = c.response.Write(b); err != nil {
464                 return
465         }
466         _, err = c.response.Write([]byte(");"))
467         return
468 }
469
470 func (c *context) xml(code int, i interface{}, indent string) (err error) {
471         c.writeContentType(MIMEApplicationXMLCharsetUTF8)
472         c.response.WriteHeader(code)
473         enc := xml.NewEncoder(c.response)
474         if indent != "" {
475                 enc.Indent("", indent)
476         }
477         if _, err = c.response.Write([]byte(xml.Header)); err != nil {
478                 return
479         }
480         return enc.Encode(i)
481 }
482
483 func (c *context) XML(code int, i interface{}) (err error) {
484         indent := ""
485         if _, pretty := c.QueryParams()["pretty"]; c.echo.Debug || pretty {
486                 indent = defaultIndent
487         }
488         return c.xml(code, i, indent)
489 }
490
491 func (c *context) XMLPretty(code int, i interface{}, indent string) (err error) {
492         return c.xml(code, i, indent)
493 }
494
495 func (c *context) XMLBlob(code int, b []byte) (err error) {
496         c.writeContentType(MIMEApplicationXMLCharsetUTF8)
497         c.response.WriteHeader(code)
498         if _, err = c.response.Write([]byte(xml.Header)); err != nil {
499                 return
500         }
501         _, err = c.response.Write(b)
502         return
503 }
504
505 func (c *context) Blob(code int, contentType string, b []byte) (err error) {
506         c.writeContentType(contentType)
507         c.response.WriteHeader(code)
508         _, err = c.response.Write(b)
509         return
510 }
511
512 func (c *context) Stream(code int, contentType string, r io.Reader) (err error) {
513         c.writeContentType(contentType)
514         c.response.WriteHeader(code)
515         _, err = io.Copy(c.response, r)
516         return
517 }
518
519 func (c *context) File(file string) (err error) {
520         f, err := os.Open(file)
521         if err != nil {
522                 return NotFoundHandler(c)
523         }
524         defer f.Close()
525
526         fi, _ := f.Stat()
527         if fi.IsDir() {
528                 file = filepath.Join(file, indexPage)
529                 f, err = os.Open(file)
530                 if err != nil {
531                         return NotFoundHandler(c)
532                 }
533                 defer f.Close()
534                 if fi, err = f.Stat(); err != nil {
535                         return
536                 }
537         }
538         http.ServeContent(c.Response(), c.Request(), fi.Name(), fi.ModTime(), f)
539         return
540 }
541
542 func (c *context) Attachment(file, name string) error {
543         return c.contentDisposition(file, name, "attachment")
544 }
545
546 func (c *context) Inline(file, name string) error {
547         return c.contentDisposition(file, name, "inline")
548 }
549
550 func (c *context) contentDisposition(file, name, dispositionType string) error {
551         c.response.Header().Set(HeaderContentDisposition, fmt.Sprintf("%s; filename=%q", dispositionType, name))
552         return c.File(file)
553 }
554
555 func (c *context) NoContent(code int) error {
556         c.response.WriteHeader(code)
557         return nil
558 }
559
560 func (c *context) Redirect(code int, url string) error {
561         if code < 300 || code > 308 {
562                 return ErrInvalidRedirectCode
563         }
564         c.response.Header().Set(HeaderLocation, url)
565         c.response.WriteHeader(code)
566         return nil
567 }
568
569 func (c *context) Error(err error) {
570         c.echo.HTTPErrorHandler(err, c)
571 }
572
573 func (c *context) Echo() *Echo {
574         return c.echo
575 }
576
577 func (c *context) Handler() HandlerFunc {
578         return c.handler
579 }
580
581 func (c *context) SetHandler(h HandlerFunc) {
582         c.handler = h
583 }
584
585 func (c *context) Logger() Logger {
586         return c.echo.Logger
587 }
588
589 func (c *context) Reset(r *http.Request, w http.ResponseWriter) {
590         c.request = r
591         c.response.reset(w)
592         c.query = nil
593         c.handler = NotFoundHandler
594         c.store = nil
595         c.path = ""
596         c.pnames = nil
597         // NOTE: Don't reset because it has to have length c.echo.maxParam at all times
598         // c.pvalues = nil
599 }
600