Source file src/net/http/responsecontroller.go

     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  //	EnableFullDuplex() error
    35  //
    36  // If the ResponseWriter does not support a method, ResponseController returns
    37  // an error matching [ErrNotSupported].
    38  func NewResponseController(rw ResponseWriter) *ResponseController {
    39  	return &ResponseController{rw}
    40  }
    41  
    42  type rwUnwrapper interface {
    43  	Unwrap() ResponseWriter
    44  }
    45  
    46  // Flush flushes buffered data to the client.
    47  func (c *ResponseController) Flush() error {
    48  	rw := c.rw
    49  	for {
    50  		switch t := rw.(type) {
    51  		case interface{ FlushError() error }:
    52  			return t.FlushError()
    53  		case Flusher:
    54  			t.Flush()
    55  			return nil
    56  		case rwUnwrapper:
    57  			rw = t.Unwrap()
    58  		default:
    59  			return errNotSupported()
    60  		}
    61  	}
    62  }
    63  
    64  // Hijack lets the caller take over the connection.
    65  // See the Hijacker interface for details.
    66  func (c *ResponseController) Hijack() (net.Conn, *bufio.ReadWriter, error) {
    67  	rw := c.rw
    68  	for {
    69  		switch t := rw.(type) {
    70  		case Hijacker:
    71  			return t.Hijack()
    72  		case rwUnwrapper:
    73  			rw = t.Unwrap()
    74  		default:
    75  			return nil, nil, errNotSupported()
    76  		}
    77  	}
    78  }
    79  
    80  // SetReadDeadline sets the deadline for reading the entire request, including the body.
    81  // Reads from the request body after the deadline has been exceeded will return an error.
    82  // A zero value means no deadline.
    83  //
    84  // Setting the read deadline after it has been exceeded will not extend it.
    85  func (c *ResponseController) SetReadDeadline(deadline time.Time) error {
    86  	rw := c.rw
    87  	for {
    88  		switch t := rw.(type) {
    89  		case interface{ SetReadDeadline(time.Time) error }:
    90  			return t.SetReadDeadline(deadline)
    91  		case rwUnwrapper:
    92  			rw = t.Unwrap()
    93  		default:
    94  			return errNotSupported()
    95  		}
    96  	}
    97  }
    98  
    99  // SetWriteDeadline sets the deadline for writing the response.
   100  // Writes to the response body after the deadline has been exceeded will not block,
   101  // but may succeed if the data has been buffered.
   102  // A zero value means no deadline.
   103  //
   104  // Setting the write deadline after it has been exceeded will not extend it.
   105  func (c *ResponseController) SetWriteDeadline(deadline time.Time) error {
   106  	rw := c.rw
   107  	for {
   108  		switch t := rw.(type) {
   109  		case interface{ SetWriteDeadline(time.Time) error }:
   110  			return t.SetWriteDeadline(deadline)
   111  		case rwUnwrapper:
   112  			rw = t.Unwrap()
   113  		default:
   114  			return errNotSupported()
   115  		}
   116  	}
   117  }
   118  
   119  // EnableFullDuplex indicates that the request handler will interleave reads from [Request.Body]
   120  // with writes to the [ResponseWriter].
   121  //
   122  // For HTTP/1 requests, the Go HTTP server by default consumes any unread portion of
   123  // the request body before beginning to write the response, preventing handlers from
   124  // concurrently reading from the request and writing the response.
   125  // Calling EnableFullDuplex disables this behavior and permits handlers to continue to read
   126  // from the request while concurrently writing the response.
   127  //
   128  // For HTTP/2 requests, the Go HTTP server always permits concurrent reads and responses.
   129  func (c *ResponseController) EnableFullDuplex() error {
   130  	rw := c.rw
   131  	for {
   132  		switch t := rw.(type) {
   133  		case interface{ EnableFullDuplex() error }:
   134  			return t.EnableFullDuplex()
   135  		case rwUnwrapper:
   136  			rw = t.Unwrap()
   137  		default:
   138  			return errNotSupported()
   139  		}
   140  	}
   141  }
   142  
   143  // errNotSupported returns an error that Is ErrNotSupported,
   144  // but is not == to it.
   145  func errNotSupported() error {
   146  	return fmt.Errorf("%w", ErrNotSupported)
   147  }
   148  

View as plain text