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 5package gin 6 7import ( 8 "bufio" 9 "io" 10 "net" 11 "net/http" 12) 13 14const ( 15 noWritten = -1 16 defaultStatus = 200 17) 18 19type ( 20 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 43 responseWriter struct { 44 http.ResponseWriter 45 size int 46 status int 47 } 48) 49 50var _ ResponseWriter = &responseWriter{} 51 52func (w *responseWriter) reset(writer http.ResponseWriter) { 53 w.ResponseWriter = writer 54 w.size = noWritten 55 w.status = defaultStatus 56} 57 58func (w *responseWriter) WriteHeader(code int) { 59 if code > 0 && w.status != code { 60 if w.Written() { 61 debugPrint("[WARNING] Headers were already written. Wanted to override status code %d with %d", w.status, code) 62 } 63 w.status = code 64 } 65} 66 67func (w *responseWriter) WriteHeaderNow() { 68 if !w.Written() { 69 w.size = 0 70 w.ResponseWriter.WriteHeader(w.status) 71 } 72} 73 74func (w *responseWriter) Write(data []byte) (n int, err error) { 75 w.WriteHeaderNow() 76 n, err = w.ResponseWriter.Write(data) 77 w.size += n 78 return 79} 80 81func (w *responseWriter) WriteString(s string) (n int, err error) { 82 w.WriteHeaderNow() 83 n, err = io.WriteString(w.ResponseWriter, s) 84 w.size += n 85 return 86} 87 88func (w *responseWriter) Status() int { 89 return w.status 90} 91 92func (w *responseWriter) Size() int { 93 return w.size 94} 95 96func (w *responseWriter) Written() bool { 97 return w.size != noWritten 98} 99 100// Implements the http.Hijacker interface 101func (w *responseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) { 102 if w.size < 0 { 103 w.size = 0 104 } 105 return w.ResponseWriter.(http.Hijacker).Hijack() 106} 107 108// Implements the http.CloseNotify interface 109func (w *responseWriter) CloseNotify() <-chan bool { 110 return w.ResponseWriter.(http.CloseNotifier).CloseNotify() 111} 112 113// Implements the http.Flush interface 114func (w *responseWriter) Flush() { 115 w.ResponseWriter.(http.Flusher).Flush() 116} 117