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  }