OSDN Git Service

feat(warder): add warder backbone (#181)
[bytom/vapor.git] / vendor / github.com / gin-gonic / gin / response_writer.go
1 // Copyright 2014 Manu Martinez-Almeida.  All rights reserved.
2 // Use of this source code is governed by a MIT style
3 // license that can be found in the LICENSE file.
4
5 package gin
6
7 import (
8         "bufio"
9         "io"
10         "net"
11         "net/http"
12 )
13
14 const (
15         noWritten     = -1
16         defaultStatus = http.StatusOK
17 )
18
19 type responseWriterBase interface {
20         http.ResponseWriter
21         http.Hijacker
22         http.Flusher
23         http.CloseNotifier
24
25         // Returns the HTTP response status code of the current request.
26         Status() int
27
28         // Returns the number of bytes already written into the response http body.
29         // See Written()
30         Size() int
31
32         // Writes the string into the response body.
33         WriteString(string) (int, error)
34
35         // Returns true if the response body was already written.
36         Written() bool
37
38         // Forces to write the http header (status code + headers).
39         WriteHeaderNow()
40 }
41
42 type responseWriter struct {
43         http.ResponseWriter
44         size   int
45         status int
46 }
47
48 var _ ResponseWriter = &responseWriter{}
49
50 func (w *responseWriter) reset(writer http.ResponseWriter) {
51         w.ResponseWriter = writer
52         w.size = noWritten
53         w.status = defaultStatus
54 }
55
56 func (w *responseWriter) WriteHeader(code int) {
57         if code > 0 && w.status != code {
58                 if w.Written() {
59                         debugPrint("[WARNING] Headers were already written. Wanted to override status code %d with %d", w.status, code)
60                 }
61                 w.status = code
62         }
63 }
64
65 func (w *responseWriter) WriteHeaderNow() {
66         if !w.Written() {
67                 w.size = 0
68                 w.ResponseWriter.WriteHeader(w.status)
69         }
70 }
71
72 func (w *responseWriter) Write(data []byte) (n int, err error) {
73         w.WriteHeaderNow()
74         n, err = w.ResponseWriter.Write(data)
75         w.size += n
76         return
77 }
78
79 func (w *responseWriter) WriteString(s string) (n int, err error) {
80         w.WriteHeaderNow()
81         n, err = io.WriteString(w.ResponseWriter, s)
82         w.size += n
83         return
84 }
85
86 func (w *responseWriter) Status() int {
87         return w.status
88 }
89
90 func (w *responseWriter) Size() int {
91         return w.size
92 }
93
94 func (w *responseWriter) Written() bool {
95         return w.size != noWritten
96 }
97
98 // Hijack implements the http.Hijacker interface.
99 func (w *responseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) {
100         if w.size < 0 {
101                 w.size = 0
102         }
103         return w.ResponseWriter.(http.Hijacker).Hijack()
104 }
105
106 // CloseNotify implements the http.CloseNotify interface.
107 func (w *responseWriter) CloseNotify() <-chan bool {
108         return w.ResponseWriter.(http.CloseNotifier).CloseNotify()
109 }
110
111 // Flush implements the http.Flush interface.
112 func (w *responseWriter) Flush() {
113         w.WriteHeaderNow()
114         w.ResponseWriter.(http.Flusher).Flush()
115 }