...

Source file src/github.com/gin-gonic/gin/response_writer.go

Documentation: github.com/gin-gonic/gin

     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  	// Status returns the HTTP response status code of the current request.
    27  	Status() int
    28  
    29  	// Size returns the number of bytes already written into the response http body.
    30  	// See Written()
    31  	Size() int
    32  
    33  	// WriteString writes the string into the response body.
    34  	WriteString(string) (int, error)
    35  
    36  	// Written returns true if the response body was already written.
    37  	Written() bool
    38  
    39  	// WriteHeaderNow forces to write the http header (status code + headers).
    40  	WriteHeaderNow()
    41  
    42  	// Pusher 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)(nil)
    53  
    54  func (w *responseWriter) Unwrap() http.ResponseWriter {
    55  	return w.ResponseWriter
    56  }
    57  
    58  func (w *responseWriter) reset(writer http.ResponseWriter) {
    59  	w.ResponseWriter = writer
    60  	w.size = noWritten
    61  	w.status = defaultStatus
    62  }
    63  
    64  func (w *responseWriter) WriteHeader(code int) {
    65  	if code > 0 && w.status != code {
    66  		if w.Written() {
    67  			debugPrint("[WARNING] Headers were already written. Wanted to override status code %d with %d", w.status, code)
    68  			return
    69  		}
    70  		w.status = code
    71  	}
    72  }
    73  
    74  func (w *responseWriter) WriteHeaderNow() {
    75  	if !w.Written() {
    76  		w.size = 0
    77  		w.ResponseWriter.WriteHeader(w.status)
    78  	}
    79  }
    80  
    81  func (w *responseWriter) Write(data []byte) (n int, err error) {
    82  	w.WriteHeaderNow()
    83  	n, err = w.ResponseWriter.Write(data)
    84  	w.size += n
    85  	return
    86  }
    87  
    88  func (w *responseWriter) WriteString(s string) (n int, err error) {
    89  	w.WriteHeaderNow()
    90  	n, err = io.WriteString(w.ResponseWriter, s)
    91  	w.size += n
    92  	return
    93  }
    94  
    95  func (w *responseWriter) Status() int {
    96  	return w.status
    97  }
    98  
    99  func (w *responseWriter) Size() int {
   100  	return w.size
   101  }
   102  
   103  func (w *responseWriter) Written() bool {
   104  	return w.size != noWritten
   105  }
   106  
   107  // Hijack implements the http.Hijacker interface.
   108  func (w *responseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) {
   109  	if w.size < 0 {
   110  		w.size = 0
   111  	}
   112  	return w.ResponseWriter.(http.Hijacker).Hijack()
   113  }
   114  
   115  // CloseNotify implements the http.CloseNotifier interface.
   116  func (w *responseWriter) CloseNotify() <-chan bool {
   117  	return w.ResponseWriter.(http.CloseNotifier).CloseNotify()
   118  }
   119  
   120  // Flush implements the http.Flusher interface.
   121  func (w *responseWriter) Flush() {
   122  	w.WriteHeaderNow()
   123  	w.ResponseWriter.(http.Flusher).Flush()
   124  }
   125  
   126  func (w *responseWriter) Pusher() (pusher http.Pusher) {
   127  	if pusher, ok := w.ResponseWriter.(http.Pusher); ok {
   128  		return pusher
   129  	}
   130  	return nil
   131  }
   132  

View as plain text