@@ -508,7 +508,8 @@ type RequestCtx struct {
508508 timeoutCh chan struct {}
509509 timeoutTimer * time.Timer
510510
511- hijackHandler HijackHandler
511+ hijackHandler HijackHandler
512+ hijackNoResponse bool
512513}
513514
514515// HijackHandler must process the hijacked connection c.
@@ -535,6 +536,7 @@ type HijackHandler func(c net.Conn)
535536// * Unexpected error during response writing to the connection.
536537//
537538// The server stops processing requests from hijacked connections.
539+ //
538540// Server limits such as Concurrency, ReadTimeout, WriteTimeout, etc.
539541// aren't applied to hijacked connections.
540542//
@@ -550,6 +552,15 @@ func (ctx *RequestCtx) Hijack(handler HijackHandler) {
550552 ctx .hijackHandler = handler
551553}
552554
555+ // HijackSetNoResponse changes the behavior of hijacking a request.
556+ // If HijackSetNoResponse is called with false fasthttp will send a response
557+ // to the client before calling the HijackHandler (default). If HijackSetNoResponse
558+ // is called with true no response is send back before calling the
559+ // HijackHandler supplied in the Hijack function.
560+ func (ctx * RequestCtx ) HijackSetNoResponse (noResponse bool ) {
561+ ctx .hijackNoResponse = noResponse
562+ }
563+
553564// Hijacked returns true after Hijack is called.
554565func (ctx * RequestCtx ) Hijacked () bool {
555566 return ctx .hijackHandler != nil
@@ -1869,9 +1880,10 @@ func (s *Server) serveConn(c net.Conn) error {
18691880 br * bufio.Reader
18701881 bw * bufio.Writer
18711882
1872- err error
1873- timeoutResponse * Response
1874- hijackHandler HijackHandler
1883+ err error
1884+ timeoutResponse * Response
1885+ hijackHandler HijackHandler
1886+ hijackNoResponse bool
18751887
18761888 connectionClose bool
18771889 isHTTP11 bool
@@ -2044,6 +2056,8 @@ func (s *Server) serveConn(c net.Conn) error {
20442056
20452057 hijackHandler = ctx .hijackHandler
20462058 ctx .hijackHandler = nil
2059+ hijackNoResponse = ctx .hijackNoResponse
2060+ ctx .hijackNoResponse = false
20472061
20482062 ctx .userValues .Reset ()
20492063
@@ -2071,30 +2085,32 @@ func (s *Server) serveConn(c net.Conn) error {
20712085 ctx .Response .Header .SetServerBytes (serverName )
20722086 }
20732087
2074- if bw == nil {
2075- bw = acquireWriter (ctx )
2076- }
2077- if err = writeResponse (ctx , bw ); err != nil {
2078- break
2079- }
2088+ if ! hijackNoResponse {
2089+ if bw == nil {
2090+ bw = acquireWriter (ctx )
2091+ }
2092+ if err = writeResponse (ctx , bw ); err != nil {
2093+ break
2094+ }
20802095
2081- // Only flush the writer if we don't have another request in the pipeline.
2082- // This is a big of an ugly optimization for https://www.techempower.com/benchmarks/
2083- // This benchmark will send 16 pipelined requests. It is faster to pack as many responses
2084- // in a TCP packet and send it back at once than waiting for a flush every request.
2085- // In real world circumstances this behaviour could be argued as being wrong.
2086- if br == nil || br .Buffered () == 0 || connectionClose {
2087- err = bw .Flush ()
2088- if err != nil {
2096+ // Only flush the writer if we don't have another request in the pipeline.
2097+ // This is a big of an ugly optimization for https://www.techempower.com/benchmarks/
2098+ // This benchmark will send 16 pipelined requests. It is faster to pack as many responses
2099+ // in a TCP packet and send it back at once than waiting for a flush every request.
2100+ // In real world circumstances this behaviour could be argued as being wrong.
2101+ if br == nil || br .Buffered () == 0 || connectionClose {
2102+ err = bw .Flush ()
2103+ if err != nil {
2104+ break
2105+ }
2106+ }
2107+ if connectionClose {
20892108 break
20902109 }
2091- }
2092- if connectionClose {
2093- break
2094- }
2095- if s .ReduceMemoryUsage {
2096- releaseWriter (s , bw )
2097- bw = nil
2110+ if s .ReduceMemoryUsage && hijackHandler == nil {
2111+ releaseWriter (s , bw )
2112+ bw = nil
2113+ }
20982114 }
20992115
21002116 if hijackHandler != nil {
0 commit comments