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
// ResponseWriter ...
20
type ResponseWriter interface {
21
	http.ResponseWriter
22
	http.Hijacker
23
	http.Flusher
24
	http.CloseNotifier
25

26
	// Returns the HTTP response status code of the current request.
27
	Status() int
28

29
	// Returns the number of bytes already written into the response http body.
30
	// See Written()
31
	Size() int
32

33
	// Writes the string into the response body.
34
	WriteString(string) (int, error)
35

36
	// Returns true if the response body was already written.
37
	Written() bool
38

39
	// Forces to write the http header (status code + headers).
40
	WriteHeaderNow()
41

42
	// get the http.Pusher for server push
43
	Pusher() http.Pusher
44
}
45

46
type responseWriter struct {
47
	http.ResponseWriter
48
	size   int
49
	status int
50
}
51

52
var _ ResponseWriter = &responseWriter{}
53

54
func (w *responseWriter) reset(writer http.ResponseWriter) {
55 14
	w.ResponseWriter = writer
56 14
	w.size = noWritten
57 14
	w.status = defaultStatus
58
}
59

60
func (w *responseWriter) WriteHeader(code int) {
61 14
	if code > 0 && w.status != code {
62 14
		if w.Written() {
63 14
			debugPrint("[WARNING] Headers were already written. Wanted to override status code %d with %d", w.status, code)
64
		}
65 14
		w.status = code
66
	}
67
}
68

69
func (w *responseWriter) WriteHeaderNow() {
70 14
	if !w.Written() {
71 14
		w.size = 0
72 14
		w.ResponseWriter.WriteHeader(w.status)
73
	}
74
}
75

76
func (w *responseWriter) Write(data []byte) (n int, err error) {
77 14
	w.WriteHeaderNow()
78 14
	n, err = w.ResponseWriter.Write(data)
79 14
	w.size += n
80 14
	return
81
}
82

83
func (w *responseWriter) WriteString(s string) (n int, err error) {
84 14
	w.WriteHeaderNow()
85 14
	n, err = io.WriteString(w.ResponseWriter, s)
86 14
	w.size += n
87 14
	return
88
}
89

90
func (w *responseWriter) Status() int {
91 14
	return w.status
92
}
93

94
func (w *responseWriter) Size() int {
95 14
	return w.size
96
}
97

98
func (w *responseWriter) Written() bool {
99 14
	return w.size != noWritten
100
}
101

102
// Hijack implements the http.Hijacker interface.
103
func (w *responseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) {
104 14
	if w.size < 0 {
105 14
		w.size = 0
106
	}
107 14
	return w.ResponseWriter.(http.Hijacker).Hijack()
108
}
109

110
// CloseNotify implements the http.CloseNotify interface.
111
func (w *responseWriter) CloseNotify() <-chan bool {
112 14
	return w.ResponseWriter.(http.CloseNotifier).CloseNotify()
113
}
114

115
// Flush implements the http.Flush interface.
116
func (w *responseWriter) Flush() {
117 14
	w.WriteHeaderNow()
118 14
	w.ResponseWriter.(http.Flusher).Flush()
119
}
120

121
func (w *responseWriter) Pusher() (pusher http.Pusher) {
122 14
	if pusher, ok := w.ResponseWriter.(http.Pusher); ok {
123 0
		return pusher
124
	}
125 14
	return nil
126
}

Read our documentation on viewing source code .

Loading