go.sdls.io/sin@v0.0.9/pkg/sin/response_writer.go (about) 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 sin 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 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 w.status = code 59 if w.Written() { 60 w.ResponseWriter.WriteHeader(code) 61 } 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 // Flush implements the http.Flush interface. 107 func (w *responseWriter) Flush() { 108 w.WriteHeaderNow() 109 w.ResponseWriter.(http.Flusher).Flush() 110 }