github.com/Kolosok86/http@v0.1.2/responsecontroller.go (about)

     1  // Copyright 2022 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package http
     6  
     7  import (
     8  	"bufio"
     9  	"fmt"
    10  	"net"
    11  	"time"
    12  )
    13  
    14  // A ResponseController is used by an HTTP handler to control the response.
    15  //
    16  // A ResponseController may not be used after the Handler.ServeHTTP method has returned.
    17  type ResponseController struct {
    18  	rw ResponseWriter
    19  }
    20  
    21  // NewResponseController creates a ResponseController for a request.
    22  //
    23  // The ResponseWriter should be the original value passed to the Handler.ServeHTTP method,
    24  // or have an Unwrap method returning the original ResponseWriter.
    25  //
    26  // If the ResponseWriter implements any of the following methods, the ResponseController
    27  // will call them as appropriate:
    28  //
    29  //	Flush()
    30  //	FlushError() error // alternative Flush returning an error
    31  //	Hijack() (net.Conn, *bufio.ReadWriter, error)
    32  //	SetReadDeadline(deadline time.Time) error
    33  //	SetWriteDeadline(deadline time.Time) error
    34  //
    35  // If the ResponseWriter does not support a method, ResponseController returns
    36  // an error matching ErrNotSupported.
    37  func NewResponseController(rw ResponseWriter) *ResponseController {
    38  	return &ResponseController{rw}
    39  }
    40  
    41  type rwUnwrapper interface {
    42  	Unwrap() ResponseWriter
    43  }
    44  
    45  // Flush flushes buffered data to the client.
    46  func (c *ResponseController) Flush() error {
    47  	rw := c.rw
    48  	for {
    49  		switch t := rw.(type) {
    50  		case interface{ FlushError() error }:
    51  			return t.FlushError()
    52  		case Flusher:
    53  			t.Flush()
    54  			return nil
    55  		case rwUnwrapper:
    56  			rw = t.Unwrap()
    57  		default:
    58  			return errNotSupported()
    59  		}
    60  	}
    61  }
    62  
    63  // Hijack lets the caller take over the connection.
    64  // See the Hijacker interface for details.
    65  func (c *ResponseController) Hijack() (net.Conn, *bufio.ReadWriter, error) {
    66  	rw := c.rw
    67  	for {
    68  		switch t := rw.(type) {
    69  		case Hijacker:
    70  			return t.Hijack()
    71  		case rwUnwrapper:
    72  			rw = t.Unwrap()
    73  		default:
    74  			return nil, nil, errNotSupported()
    75  		}
    76  	}
    77  }
    78  
    79  // SetReadDeadline sets the deadline for reading the entire request, including the body.
    80  // Reads from the request body after the deadline has been exceeded will return an error.
    81  // A zero value means no deadline.
    82  //
    83  // Setting the read deadline after it has been exceeded will not extend it.
    84  func (c *ResponseController) SetReadDeadline(deadline time.Time) error {
    85  	rw := c.rw
    86  	for {
    87  		switch t := rw.(type) {
    88  		case interface{ SetReadDeadline(time.Time) error }:
    89  			return t.SetReadDeadline(deadline)
    90  		case rwUnwrapper:
    91  			rw = t.Unwrap()
    92  		default:
    93  			return errNotSupported()
    94  		}
    95  	}
    96  }
    97  
    98  // SetWriteDeadline sets the deadline for writing the response.
    99  // Writes to the response body after the deadline has been exceeded will not block,
   100  // but may succeed if the data has been buffered.
   101  // A zero value means no deadline.
   102  //
   103  // Setting the write deadline after it has been exceeded will not extend it.
   104  func (c *ResponseController) SetWriteDeadline(deadline time.Time) error {
   105  	rw := c.rw
   106  	for {
   107  		switch t := rw.(type) {
   108  		case interface{ SetWriteDeadline(time.Time) error }:
   109  			return t.SetWriteDeadline(deadline)
   110  		case rwUnwrapper:
   111  			rw = t.Unwrap()
   112  		default:
   113  			return errNotSupported()
   114  		}
   115  	}
   116  }
   117  
   118  // errNotSupported returns an error that Is ErrNotSupported,
   119  // but is not == to it.
   120  func errNotSupported() error {
   121  	return fmt.Errorf("%w", ErrNotSupported)
   122  }