github.com/hellobchain/third_party@v0.0.0-20230331131523-deb0478a2e52/gin/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 gin
     6  
     7  import (
     8  	"bufio"
     9  	"github.com/hellobchain/newcryptosm/http"
    10  	"io"
    11  	"net"
    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  	w.ResponseWriter = writer
    56  	w.size = noWritten
    57  	w.status = defaultStatus
    58  }
    59  
    60  func (w *responseWriter) WriteHeader(code int) {
    61  	if code > 0 && w.status != code {
    62  		if w.Written() {
    63  			debugPrint("[WARNING] Headers were already written. Wanted to override status code %d with %d", w.status, code)
    64  		}
    65  		w.status = code
    66  	}
    67  }
    68  
    69  func (w *responseWriter) WriteHeaderNow() {
    70  	if !w.Written() {
    71  		w.size = 0
    72  		w.ResponseWriter.WriteHeader(w.status)
    73  	}
    74  }
    75  
    76  func (w *responseWriter) Write(data []byte) (n int, err error) {
    77  	w.WriteHeaderNow()
    78  	n, err = w.ResponseWriter.Write(data)
    79  	w.size += n
    80  	return
    81  }
    82  
    83  func (w *responseWriter) WriteString(s string) (n int, err error) {
    84  	w.WriteHeaderNow()
    85  	n, err = io.WriteString(w.ResponseWriter, s)
    86  	w.size += n
    87  	return
    88  }
    89  
    90  func (w *responseWriter) Status() int {
    91  	return w.status
    92  }
    93  
    94  func (w *responseWriter) Size() int {
    95  	return w.size
    96  }
    97  
    98  func (w *responseWriter) Written() bool {
    99  	return w.size != noWritten
   100  }
   101  
   102  // Hijack implements the http.Hijacker interface.
   103  func (w *responseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) {
   104  	if w.size < 0 {
   105  		w.size = 0
   106  	}
   107  	return w.ResponseWriter.(http.Hijacker).Hijack()
   108  }
   109  
   110  // CloseNotify implements the http.CloseNotify interface.
   111  func (w *responseWriter) CloseNotify() <-chan bool {
   112  	return w.ResponseWriter.(http.CloseNotifier).CloseNotify()
   113  }
   114  
   115  // Flush implements the http.Flush interface.
   116  func (w *responseWriter) Flush() {
   117  	w.WriteHeaderNow()
   118  	w.ResponseWriter.(http.Flusher).Flush()
   119  }
   120  
   121  func (w *responseWriter) Pusher() (pusher http.Pusher) {
   122  	if pusher, ok := w.ResponseWriter.(http.Pusher); ok {
   123  		return pusher
   124  	}
   125  	return nil
   126  }