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 }