source: code/trunk/vendor/github.com/valyala/fasthttp/server.go@ 145

Last change on this file since 145 was 145, checked in by Izuru Yakumo, 22 months ago

Updated the Makefile and vendored depedencies

Signed-off-by: Izuru Yakumo <yakumo.izuru@…>

File size: 82.5 KB
Line 
1package fasthttp
2
3import (
4 "bufio"
5 "context"
6 "crypto/tls"
7 "errors"
8 "fmt"
9 "io"
10 "log"
11 "mime/multipart"
12 "net"
13 "os"
14 "strings"
15 "sync"
16 "sync/atomic"
17 "time"
18)
19
20var errNoCertOrKeyProvided = errors.New("cert or key has not provided")
21
22var (
23 // ErrAlreadyServing is returned when calling Serve on a Server
24 // that is already serving connections.
25 ErrAlreadyServing = errors.New("Server is already serving connections")
26)
27
28// ServeConn serves HTTP requests from the given connection
29// using the given handler.
30//
31// ServeConn returns nil if all requests from the c are successfully served.
32// It returns non-nil error otherwise.
33//
34// Connection c must immediately propagate all the data passed to Write()
35// to the client. Otherwise requests' processing may hang.
36//
37// ServeConn closes c before returning.
38func ServeConn(c net.Conn, handler RequestHandler) error {
39 v := serverPool.Get()
40 if v == nil {
41 v = &Server{}
42 }
43 s := v.(*Server)
44 s.Handler = handler
45 err := s.ServeConn(c)
46 s.Handler = nil
47 serverPool.Put(v)
48 return err
49}
50
51var serverPool sync.Pool
52
53// Serve serves incoming connections from the given listener
54// using the given handler.
55//
56// Serve blocks until the given listener returns permanent error.
57func Serve(ln net.Listener, handler RequestHandler) error {
58 s := &Server{
59 Handler: handler,
60 }
61 return s.Serve(ln)
62}
63
64// ServeTLS serves HTTPS requests from the given net.Listener
65// using the given handler.
66//
67// certFile and keyFile are paths to TLS certificate and key files.
68func ServeTLS(ln net.Listener, certFile, keyFile string, handler RequestHandler) error {
69 s := &Server{
70 Handler: handler,
71 }
72 return s.ServeTLS(ln, certFile, keyFile)
73}
74
75// ServeTLSEmbed serves HTTPS requests from the given net.Listener
76// using the given handler.
77//
78// certData and keyData must contain valid TLS certificate and key data.
79func ServeTLSEmbed(ln net.Listener, certData, keyData []byte, handler RequestHandler) error {
80 s := &Server{
81 Handler: handler,
82 }
83 return s.ServeTLSEmbed(ln, certData, keyData)
84}
85
86// ListenAndServe serves HTTP requests from the given TCP addr
87// using the given handler.
88func ListenAndServe(addr string, handler RequestHandler) error {
89 s := &Server{
90 Handler: handler,
91 }
92 return s.ListenAndServe(addr)
93}
94
95// ListenAndServeUNIX serves HTTP requests from the given UNIX addr
96// using the given handler.
97//
98// The function deletes existing file at addr before starting serving.
99//
100// The server sets the given file mode for the UNIX addr.
101func ListenAndServeUNIX(addr string, mode os.FileMode, handler RequestHandler) error {
102 s := &Server{
103 Handler: handler,
104 }
105 return s.ListenAndServeUNIX(addr, mode)
106}
107
108// ListenAndServeTLS serves HTTPS requests from the given TCP addr
109// using the given handler.
110//
111// certFile and keyFile are paths to TLS certificate and key files.
112func ListenAndServeTLS(addr, certFile, keyFile string, handler RequestHandler) error {
113 s := &Server{
114 Handler: handler,
115 }
116 return s.ListenAndServeTLS(addr, certFile, keyFile)
117}
118
119// ListenAndServeTLSEmbed serves HTTPS requests from the given TCP addr
120// using the given handler.
121//
122// certData and keyData must contain valid TLS certificate and key data.
123func ListenAndServeTLSEmbed(addr string, certData, keyData []byte, handler RequestHandler) error {
124 s := &Server{
125 Handler: handler,
126 }
127 return s.ListenAndServeTLSEmbed(addr, certData, keyData)
128}
129
130// RequestHandler must process incoming requests.
131//
132// RequestHandler must call ctx.TimeoutError() before returning
133// if it keeps references to ctx and/or its' members after the return.
134// Consider wrapping RequestHandler into TimeoutHandler if response time
135// must be limited.
136type RequestHandler func(ctx *RequestCtx)
137
138// ServeHandler must process tls.Config.NextProto negotiated requests.
139type ServeHandler func(c net.Conn) error
140
141// Server implements HTTP server.
142//
143// Default Server settings should satisfy the majority of Server users.
144// Adjust Server settings only if you really understand the consequences.
145//
146// It is forbidden copying Server instances. Create new Server instances
147// instead.
148//
149// It is safe to call Server methods from concurrently running goroutines.
150type Server struct {
151 noCopy noCopy //nolint:unused,structcheck
152
153 // Handler for processing incoming requests.
154 //
155 // Take into account that no `panic` recovery is done by `fasthttp` (thus any `panic` will take down the entire server).
156 // Instead the user should use `recover` to handle these situations.
157 Handler RequestHandler
158
159 // ErrorHandler for returning a response in case of an error while receiving or parsing the request.
160 //
161 // The following is a non-exhaustive list of errors that can be expected as argument:
162 // * io.EOF
163 // * io.ErrUnexpectedEOF
164 // * ErrGetOnly
165 // * ErrSmallBuffer
166 // * ErrBodyTooLarge
167 // * ErrBrokenChunks
168 ErrorHandler func(ctx *RequestCtx, err error)
169
170 // HeaderReceived is called after receiving the header
171 //
172 // non zero RequestConfig field values will overwrite the default configs
173 HeaderReceived func(header *RequestHeader) RequestConfig
174
175 // ContinueHandler is called after receiving the Expect 100 Continue Header
176 //
177 // https://www.w3.org/Protocols/rfc2616/rfc2616-sec8.html#sec8.2.3
178 // https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.1.1
179 // Using ContinueHandler a server can make decisioning on whether or not
180 // to read a potentially large request body based on the headers
181 //
182 // The default is to automatically read request bodies of Expect 100 Continue requests
183 // like they are normal requests
184 ContinueHandler func(header *RequestHeader) bool
185
186 // Server name for sending in response headers.
187 //
188 // Default server name is used if left blank.
189 Name string
190
191 // The maximum number of concurrent connections the server may serve.
192 //
193 // DefaultConcurrency is used if not set.
194 //
195 // Concurrency only works if you either call Serve once, or only ServeConn multiple times.
196 // It works with ListenAndServe as well.
197 Concurrency int
198
199 // Per-connection buffer size for requests' reading.
200 // This also limits the maximum header size.
201 //
202 // Increase this buffer if your clients send multi-KB RequestURIs
203 // and/or multi-KB headers (for example, BIG cookies).
204 //
205 // Default buffer size is used if not set.
206 ReadBufferSize int
207
208 // Per-connection buffer size for responses' writing.
209 //
210 // Default buffer size is used if not set.
211 WriteBufferSize int
212
213 // ReadTimeout is the amount of time allowed to read
214 // the full request including body. The connection's read
215 // deadline is reset when the connection opens, or for
216 // keep-alive connections after the first byte has been read.
217 //
218 // By default request read timeout is unlimited.
219 ReadTimeout time.Duration
220
221 // WriteTimeout is the maximum duration before timing out
222 // writes of the response. It is reset after the request handler
223 // has returned.
224 //
225 // By default response write timeout is unlimited.
226 WriteTimeout time.Duration
227
228 // IdleTimeout is the maximum amount of time to wait for the
229 // next request when keep-alive is enabled. If IdleTimeout
230 // is zero, the value of ReadTimeout is used.
231 IdleTimeout time.Duration
232
233 // Maximum number of concurrent client connections allowed per IP.
234 //
235 // By default unlimited number of concurrent connections
236 // may be established to the server from a single IP address.
237 MaxConnsPerIP int
238
239 // Maximum number of requests served per connection.
240 //
241 // The server closes connection after the last request.
242 // 'Connection: close' header is added to the last response.
243 //
244 // By default unlimited number of requests may be served per connection.
245 MaxRequestsPerConn int
246
247 // MaxKeepaliveDuration is a no-op and only left here for backwards compatibility.
248 // Deprecated: Use IdleTimeout instead.
249 MaxKeepaliveDuration time.Duration
250
251 // MaxIdleWorkerDuration is the maximum idle time of a single worker in the underlying
252 // worker pool of the Server. Idle workers beyond this time will be cleared.
253 MaxIdleWorkerDuration time.Duration
254
255 // Period between tcp keep-alive messages.
256 //
257 // TCP keep-alive period is determined by operation system by default.
258 TCPKeepalivePeriod time.Duration
259
260 // Maximum request body size.
261 //
262 // The server rejects requests with bodies exceeding this limit.
263 //
264 // Request body size is limited by DefaultMaxRequestBodySize by default.
265 MaxRequestBodySize int
266
267 // Whether to disable keep-alive connections.
268 //
269 // The server will close all the incoming connections after sending
270 // the first response to client if this option is set to true.
271 //
272 // By default keep-alive connections are enabled.
273 DisableKeepalive bool
274
275 // Whether to enable tcp keep-alive connections.
276 //
277 // Whether the operating system should send tcp keep-alive messages on the tcp connection.
278 //
279 // By default tcp keep-alive connections are disabled.
280 TCPKeepalive bool
281
282 // Aggressively reduces memory usage at the cost of higher CPU usage
283 // if set to true.
284 //
285 // Try enabling this option only if the server consumes too much memory
286 // serving mostly idle keep-alive connections. This may reduce memory
287 // usage by more than 50%.
288 //
289 // Aggressive memory usage reduction is disabled by default.
290 ReduceMemoryUsage bool
291
292 // Rejects all non-GET requests if set to true.
293 //
294 // This option is useful as anti-DoS protection for servers
295 // accepting only GET requests. The request size is limited
296 // by ReadBufferSize if GetOnly is set.
297 //
298 // Server accepts all the requests by default.
299 GetOnly bool
300
301 // Will not pre parse Multipart Form data if set to true.
302 //
303 // This option is useful for servers that desire to treat
304 // multipart form data as a binary blob, or choose when to parse the data.
305 //
306 // Server pre parses multipart form data by default.
307 DisablePreParseMultipartForm bool
308
309 // Logs all errors, including the most frequent
310 // 'connection reset by peer', 'broken pipe' and 'connection timeout'
311 // errors. Such errors are common in production serving real-world
312 // clients.
313 //
314 // By default the most frequent errors such as
315 // 'connection reset by peer', 'broken pipe' and 'connection timeout'
316 // are suppressed in order to limit output log traffic.
317 LogAllErrors bool
318
319 // Will not log potentially sensitive content in error logs
320 //
321 // This option is useful for servers that handle sensitive data
322 // in the request/response.
323 //
324 // Server logs all full errors by default.
325 SecureErrorLogMessage bool
326
327 // Header names are passed as-is without normalization
328 // if this option is set.
329 //
330 // Disabled header names' normalization may be useful only for proxying
331 // incoming requests to other servers expecting case-sensitive
332 // header names. See https://github.com/valyala/fasthttp/issues/57
333 // for details.
334 //
335 // By default request and response header names are normalized, i.e.
336 // The first letter and the first letters following dashes
337 // are uppercased, while all the other letters are lowercased.
338 // Examples:
339 //
340 // * HOST -> Host
341 // * content-type -> Content-Type
342 // * cONTENT-lenGTH -> Content-Length
343 DisableHeaderNamesNormalizing bool
344
345 // SleepWhenConcurrencyLimitsExceeded is a duration to be slept of if
346 // the concurrency limit in exceeded (default [when is 0]: don't sleep
347 // and accept new connections immediately).
348 SleepWhenConcurrencyLimitsExceeded time.Duration
349
350 // NoDefaultServerHeader, when set to true, causes the default Server header
351 // to be excluded from the Response.
352 //
353 // The default Server header value is the value of the Name field or an
354 // internal default value in its absence. With this option set to true,
355 // the only time a Server header will be sent is if a non-zero length
356 // value is explicitly provided during a request.
357 NoDefaultServerHeader bool
358
359 // NoDefaultDate, when set to true, causes the default Date
360 // header to be excluded from the Response.
361 //
362 // The default Date header value is the current date value. When
363 // set to true, the Date will not be present.
364 NoDefaultDate bool
365
366 // NoDefaultContentType, when set to true, causes the default Content-Type
367 // header to be excluded from the Response.
368 //
369 // The default Content-Type header value is the internal default value. When
370 // set to true, the Content-Type will not be present.
371 NoDefaultContentType bool
372
373 // KeepHijackedConns is an opt-in disable of connection
374 // close by fasthttp after connections' HijackHandler returns.
375 // This allows to save goroutines, e.g. when fasthttp used to upgrade
376 // http connections to WS and connection goes to another handler,
377 // which will close it when needed.
378 KeepHijackedConns bool
379
380 // CloseOnShutdown when true adds a `Connection: close` header when when the server is shutting down.
381 CloseOnShutdown bool
382
383 // StreamRequestBody enables request body streaming,
384 // and calls the handler sooner when given body is
385 // larger then the current limit.
386 StreamRequestBody bool
387
388 // ConnState specifies an optional callback function that is
389 // called when a client connection changes state. See the
390 // ConnState type and associated constants for details.
391 ConnState func(net.Conn, ConnState)
392
393 // Logger, which is used by RequestCtx.Logger().
394 //
395 // By default standard logger from log package is used.
396 Logger Logger
397
398 // TLSConfig optionally provides a TLS configuration for use
399 // by ServeTLS, ServeTLSEmbed, ListenAndServeTLS, ListenAndServeTLSEmbed,
400 // AppendCert, AppendCertEmbed and NextProto.
401 //
402 // Note that this value is cloned by ServeTLS, ServeTLSEmbed, ListenAndServeTLS
403 // and ListenAndServeTLSEmbed, so it's not possible to modify the configuration
404 // with methods like tls.Config.SetSessionTicketKeys.
405 // To use SetSessionTicketKeys, use Server.Serve with a TLS Listener
406 // instead.
407 TLSConfig *tls.Config
408
409 nextProtos map[string]ServeHandler
410
411 concurrency uint32
412 concurrencyCh chan struct{}
413 perIPConnCounter perIPConnCounter
414 serverName atomic.Value
415
416 ctxPool sync.Pool
417 readerPool sync.Pool
418 writerPool sync.Pool
419 hijackConnPool sync.Pool
420
421 // We need to know our listeners and idle connections so we can close them in Shutdown().
422 ln []net.Listener
423
424 idleConns map[net.Conn]struct{}
425 idleConnsMu sync.Mutex
426
427 mu sync.Mutex
428 open int32
429 stop int32
430 done chan struct{}
431}
432
433// TimeoutHandler creates RequestHandler, which returns StatusRequestTimeout
434// error with the given msg to the client if h didn't return during
435// the given duration.
436//
437// The returned handler may return StatusTooManyRequests error with the given
438// msg to the client if there are more than Server.Concurrency concurrent
439// handlers h are running at the moment.
440func TimeoutHandler(h RequestHandler, timeout time.Duration, msg string) RequestHandler {
441 return TimeoutWithCodeHandler(h, timeout, msg, StatusRequestTimeout)
442}
443
444// TimeoutWithCodeHandler creates RequestHandler, which returns an error with
445// the given msg and status code to the client if h didn't return during
446// the given duration.
447//
448// The returned handler may return StatusTooManyRequests error with the given
449// msg to the client if there are more than Server.Concurrency concurrent
450// handlers h are running at the moment.
451func TimeoutWithCodeHandler(h RequestHandler, timeout time.Duration, msg string, statusCode int) RequestHandler {
452 if timeout <= 0 {
453 return h
454 }
455
456 return func(ctx *RequestCtx) {
457 concurrencyCh := ctx.s.concurrencyCh
458 select {
459 case concurrencyCh <- struct{}{}:
460 default:
461 ctx.Error(msg, StatusTooManyRequests)
462 return
463 }
464
465 ch := ctx.timeoutCh
466 if ch == nil {
467 ch = make(chan struct{}, 1)
468 ctx.timeoutCh = ch
469 }
470 go func() {
471 h(ctx)
472 ch <- struct{}{}
473 <-concurrencyCh
474 }()
475 ctx.timeoutTimer = initTimer(ctx.timeoutTimer, timeout)
476 select {
477 case <-ch:
478 case <-ctx.timeoutTimer.C:
479 ctx.TimeoutErrorWithCode(msg, statusCode)
480 }
481 stopTimer(ctx.timeoutTimer)
482 }
483}
484
485//RequestConfig configure the per request deadline and body limits
486type RequestConfig struct {
487 // ReadTimeout is the maximum duration for reading the entire
488 // request body.
489 // a zero value means that default values will be honored
490 ReadTimeout time.Duration
491 // WriteTimeout is the maximum duration before timing out
492 // writes of the response.
493 // a zero value means that default values will be honored
494 WriteTimeout time.Duration
495 // Maximum request body size.
496 // a zero value means that default values will be honored
497 MaxRequestBodySize int
498}
499
500// CompressHandler returns RequestHandler that transparently compresses
501// response body generated by h if the request contains 'gzip' or 'deflate'
502// 'Accept-Encoding' header.
503func CompressHandler(h RequestHandler) RequestHandler {
504 return CompressHandlerLevel(h, CompressDefaultCompression)
505}
506
507// CompressHandlerLevel returns RequestHandler that transparently compresses
508// response body generated by h if the request contains a 'gzip' or 'deflate'
509// 'Accept-Encoding' header.
510//
511// Level is the desired compression level:
512//
513// * CompressNoCompression
514// * CompressBestSpeed
515// * CompressBestCompression
516// * CompressDefaultCompression
517// * CompressHuffmanOnly
518func CompressHandlerLevel(h RequestHandler, level int) RequestHandler {
519 return func(ctx *RequestCtx) {
520 h(ctx)
521 if ctx.Request.Header.HasAcceptEncodingBytes(strGzip) {
522 ctx.Response.gzipBody(level) //nolint:errcheck
523 } else if ctx.Request.Header.HasAcceptEncodingBytes(strDeflate) {
524 ctx.Response.deflateBody(level) //nolint:errcheck
525 }
526 }
527}
528
529// CompressHandlerBrotliLevel returns RequestHandler that transparently compresses
530// response body generated by h if the request contains a 'br', 'gzip' or 'deflate'
531// 'Accept-Encoding' header.
532//
533// brotliLevel is the desired compression level for brotli.
534//
535// * CompressBrotliNoCompression
536// * CompressBrotliBestSpeed
537// * CompressBrotliBestCompression
538// * CompressBrotliDefaultCompression
539//
540// otherLevel is the desired compression level for gzip and deflate.
541//
542// * CompressNoCompression
543// * CompressBestSpeed
544// * CompressBestCompression
545// * CompressDefaultCompression
546// * CompressHuffmanOnly
547func CompressHandlerBrotliLevel(h RequestHandler, brotliLevel, otherLevel int) RequestHandler {
548 return func(ctx *RequestCtx) {
549 h(ctx)
550 if ctx.Request.Header.HasAcceptEncodingBytes(strBr) {
551 ctx.Response.brotliBody(brotliLevel) //nolint:errcheck
552 } else if ctx.Request.Header.HasAcceptEncodingBytes(strGzip) {
553 ctx.Response.gzipBody(otherLevel) //nolint:errcheck
554 } else if ctx.Request.Header.HasAcceptEncodingBytes(strDeflate) {
555 ctx.Response.deflateBody(otherLevel) //nolint:errcheck
556 }
557 }
558}
559
560// RequestCtx contains incoming request and manages outgoing response.
561//
562// It is forbidden copying RequestCtx instances.
563//
564// RequestHandler should avoid holding references to incoming RequestCtx and/or
565// its' members after the return.
566// If holding RequestCtx references after the return is unavoidable
567// (for instance, ctx is passed to a separate goroutine and ctx lifetime cannot
568// be controlled), then the RequestHandler MUST call ctx.TimeoutError()
569// before return.
570//
571// It is unsafe modifying/reading RequestCtx instance from concurrently
572// running goroutines. The only exception is TimeoutError*, which may be called
573// while other goroutines accessing RequestCtx.
574type RequestCtx struct {
575 noCopy noCopy //nolint:unused,structcheck
576
577 // Incoming request.
578 //
579 // Copying Request by value is forbidden. Use pointer to Request instead.
580 Request Request
581
582 // Outgoing response.
583 //
584 // Copying Response by value is forbidden. Use pointer to Response instead.
585 Response Response
586
587 userValues userData
588
589 connID uint64
590 connRequestNum uint64
591 connTime time.Time
592 remoteAddr net.Addr
593
594 time time.Time
595
596 logger ctxLogger
597 s *Server
598 c net.Conn
599 fbr firstByteReader
600
601 timeoutResponse *Response
602 timeoutCh chan struct{}
603 timeoutTimer *time.Timer
604
605 hijackHandler HijackHandler
606 hijackNoResponse bool
607}
608
609// HijackHandler must process the hijacked connection c.
610//
611// If KeepHijackedConns is disabled, which is by default,
612// the connection c is automatically closed after returning from HijackHandler.
613//
614// The connection c must not be used after returning from the handler, if KeepHijackedConns is disabled.
615//
616// When KeepHijackedConns enabled, fasthttp will not Close() the connection,
617// you must do it when you need it. You must not use c in any way after calling Close().
618type HijackHandler func(c net.Conn)
619
620// Hijack registers the given handler for connection hijacking.
621//
622// The handler is called after returning from RequestHandler
623// and sending http response. The current connection is passed
624// to the handler. The connection is automatically closed after
625// returning from the handler.
626//
627// The server skips calling the handler in the following cases:
628//
629// * 'Connection: close' header exists in either request or response.
630// * Unexpected error during response writing to the connection.
631//
632// The server stops processing requests from hijacked connections.
633//
634// Server limits such as Concurrency, ReadTimeout, WriteTimeout, etc.
635// aren't applied to hijacked connections.
636//
637// The handler must not retain references to ctx members.
638//
639// Arbitrary 'Connection: Upgrade' protocols may be implemented
640// with HijackHandler. For instance,
641//
642// * WebSocket ( https://en.wikipedia.org/wiki/WebSocket )
643// * HTTP/2.0 ( https://en.wikipedia.org/wiki/HTTP/2 )
644//
645func (ctx *RequestCtx) Hijack(handler HijackHandler) {
646 ctx.hijackHandler = handler
647}
648
649// HijackSetNoResponse changes the behavior of hijacking a request.
650// If HijackSetNoResponse is called with false fasthttp will send a response
651// to the client before calling the HijackHandler (default). If HijackSetNoResponse
652// is called with true no response is send back before calling the
653// HijackHandler supplied in the Hijack function.
654func (ctx *RequestCtx) HijackSetNoResponse(noResponse bool) {
655 ctx.hijackNoResponse = noResponse
656}
657
658// Hijacked returns true after Hijack is called.
659func (ctx *RequestCtx) Hijacked() bool {
660 return ctx.hijackHandler != nil
661}
662
663// SetUserValue stores the given value (arbitrary object)
664// under the given key in ctx.
665//
666// The value stored in ctx may be obtained by UserValue*.
667//
668// This functionality may be useful for passing arbitrary values between
669// functions involved in request processing.
670//
671// All the values are removed from ctx after returning from the top
672// RequestHandler. Additionally, Close method is called on each value
673// implementing io.Closer before removing the value from ctx.
674func (ctx *RequestCtx) SetUserValue(key string, value interface{}) {
675 ctx.userValues.Set(key, value)
676}
677
678// SetUserValueBytes stores the given value (arbitrary object)
679// under the given key in ctx.
680//
681// The value stored in ctx may be obtained by UserValue*.
682//
683// This functionality may be useful for passing arbitrary values between
684// functions involved in request processing.
685//
686// All the values stored in ctx are deleted after returning from RequestHandler.
687func (ctx *RequestCtx) SetUserValueBytes(key []byte, value interface{}) {
688 ctx.userValues.SetBytes(key, value)
689}
690
691// UserValue returns the value stored via SetUserValue* under the given key.
692func (ctx *RequestCtx) UserValue(key string) interface{} {
693 return ctx.userValues.Get(key)
694}
695
696// UserValueBytes returns the value stored via SetUserValue*
697// under the given key.
698func (ctx *RequestCtx) UserValueBytes(key []byte) interface{} {
699 return ctx.userValues.GetBytes(key)
700}
701
702// VisitUserValues calls visitor for each existing userValue.
703//
704// visitor must not retain references to key and value after returning.
705// Make key and/or value copies if you need storing them after returning.
706func (ctx *RequestCtx) VisitUserValues(visitor func([]byte, interface{})) {
707 for i, n := 0, len(ctx.userValues); i < n; i++ {
708 kv := &ctx.userValues[i]
709 visitor(kv.key, kv.value)
710 }
711}
712
713// ResetUserValues allows to reset user values from Request Context
714func (ctx *RequestCtx) ResetUserValues() {
715 ctx.userValues.Reset()
716}
717
718// RemoveUserValue removes the given key and the value under it in ctx.
719func (ctx *RequestCtx) RemoveUserValue(key string) {
720 ctx.userValues.Remove(key)
721}
722
723// RemoveUserValueBytes removes the given key and the value under it in ctx.
724func (ctx *RequestCtx) RemoveUserValueBytes(key []byte) {
725 ctx.userValues.RemoveBytes(key)
726}
727
728type connTLSer interface {
729 Handshake() error
730 ConnectionState() tls.ConnectionState
731}
732
733// IsTLS returns true if the underlying connection is tls.Conn.
734//
735// tls.Conn is an encrypted connection (aka SSL, HTTPS).
736func (ctx *RequestCtx) IsTLS() bool {
737 // cast to (connTLSer) instead of (*tls.Conn), since it catches
738 // cases with overridden tls.Conn such as:
739 //
740 // type customConn struct {
741 // *tls.Conn
742 //
743 // // other custom fields here
744 // }
745
746 // perIPConn wraps the net.Conn in the Conn field
747 if pic, ok := ctx.c.(*perIPConn); ok {
748 _, ok := pic.Conn.(connTLSer)
749 return ok
750 }
751
752 _, ok := ctx.c.(connTLSer)
753 return ok
754}
755
756// TLSConnectionState returns TLS connection state.
757//
758// The function returns nil if the underlying connection isn't tls.Conn.
759//
760// The returned state may be used for verifying TLS version, client certificates,
761// etc.
762func (ctx *RequestCtx) TLSConnectionState() *tls.ConnectionState {
763 tlsConn, ok := ctx.c.(connTLSer)
764 if !ok {
765 return nil
766 }
767 state := tlsConn.ConnectionState()
768 return &state
769}
770
771// Conn returns a reference to the underlying net.Conn.
772//
773// WARNING: Only use this method if you know what you are doing!
774//
775// Reading from or writing to the returned connection will end badly!
776func (ctx *RequestCtx) Conn() net.Conn {
777 return ctx.c
778}
779
780func (ctx *RequestCtx) reset() {
781 ctx.userValues.Reset()
782 ctx.Request.Reset()
783 ctx.Response.Reset()
784 ctx.fbr.reset()
785
786 ctx.connID = 0
787 ctx.connRequestNum = 0
788 ctx.connTime = zeroTime
789 ctx.remoteAddr = nil
790 ctx.time = zeroTime
791 ctx.c = nil
792
793 // Don't reset ctx.s!
794 // We have a pool per server so the next time this ctx is used it
795 // will be assigned the same value again.
796 // ctx might still be in use for context.Done() and context.Err()
797 // which are safe to use as they only use ctx.s and no other value.
798
799 if ctx.timeoutResponse != nil {
800 ctx.timeoutResponse.Reset()
801 }
802
803 if ctx.timeoutTimer != nil {
804 stopTimer(ctx.timeoutTimer)
805 }
806
807 ctx.hijackHandler = nil
808 ctx.hijackNoResponse = false
809}
810
811type firstByteReader struct {
812 c net.Conn
813 ch byte
814 byteRead bool
815}
816
817func (r *firstByteReader) reset() {
818 r.c = nil
819 r.ch = 0
820 r.byteRead = false
821}
822
823func (r *firstByteReader) Read(b []byte) (int, error) {
824 if len(b) == 0 {
825 return 0, nil
826 }
827 nn := 0
828 if !r.byteRead {
829 b[0] = r.ch
830 b = b[1:]
831 r.byteRead = true
832 nn = 1
833 }
834 n, err := r.c.Read(b)
835 return n + nn, err
836}
837
838// Logger is used for logging formatted messages.
839type Logger interface {
840 // Printf must have the same semantics as log.Printf.
841 Printf(format string, args ...interface{})
842}
843
844var ctxLoggerLock sync.Mutex
845
846type ctxLogger struct {
847 ctx *RequestCtx
848 logger Logger
849}
850
851func (cl *ctxLogger) Printf(format string, args ...interface{}) {
852 msg := fmt.Sprintf(format, args...)
853 ctxLoggerLock.Lock()
854 cl.logger.Printf("%.3f %s - %s", time.Since(cl.ctx.ConnTime()).Seconds(), cl.ctx.String(), msg)
855 ctxLoggerLock.Unlock()
856}
857
858var zeroTCPAddr = &net.TCPAddr{
859 IP: net.IPv4zero,
860}
861
862// String returns unique string representation of the ctx.
863//
864// The returned value may be useful for logging.
865func (ctx *RequestCtx) String() string {
866 return fmt.Sprintf("#%016X - %s<->%s - %s %s", ctx.ID(), ctx.LocalAddr(), ctx.RemoteAddr(), ctx.Request.Header.Method(), ctx.URI().FullURI())
867}
868
869// ID returns unique ID of the request.
870func (ctx *RequestCtx) ID() uint64 {
871 return (ctx.connID << 32) | ctx.connRequestNum
872}
873
874// ConnID returns unique connection ID.
875//
876// This ID may be used to match distinct requests to the same incoming
877// connection.
878func (ctx *RequestCtx) ConnID() uint64 {
879 return ctx.connID
880}
881
882// Time returns RequestHandler call time.
883func (ctx *RequestCtx) Time() time.Time {
884 return ctx.time
885}
886
887// ConnTime returns the time the server started serving the connection
888// the current request came from.
889func (ctx *RequestCtx) ConnTime() time.Time {
890 return ctx.connTime
891}
892
893// ConnRequestNum returns request sequence number
894// for the current connection.
895//
896// Sequence starts with 1.
897func (ctx *RequestCtx) ConnRequestNum() uint64 {
898 return ctx.connRequestNum
899}
900
901// SetConnectionClose sets 'Connection: close' response header and closes
902// connection after the RequestHandler returns.
903func (ctx *RequestCtx) SetConnectionClose() {
904 ctx.Response.SetConnectionClose()
905}
906
907// SetStatusCode sets response status code.
908func (ctx *RequestCtx) SetStatusCode(statusCode int) {
909 ctx.Response.SetStatusCode(statusCode)
910}
911
912// SetContentType sets response Content-Type.
913func (ctx *RequestCtx) SetContentType(contentType string) {
914 ctx.Response.Header.SetContentType(contentType)
915}
916
917// SetContentTypeBytes sets response Content-Type.
918//
919// It is safe modifying contentType buffer after function return.
920func (ctx *RequestCtx) SetContentTypeBytes(contentType []byte) {
921 ctx.Response.Header.SetContentTypeBytes(contentType)
922}
923
924// RequestURI returns RequestURI.
925//
926// The returned bytes are valid until your request handler returns.
927func (ctx *RequestCtx) RequestURI() []byte {
928 return ctx.Request.Header.RequestURI()
929}
930
931// URI returns requested uri.
932//
933// This uri is valid until your request handler returns.
934func (ctx *RequestCtx) URI() *URI {
935 return ctx.Request.URI()
936}
937
938// Referer returns request referer.
939//
940// The returned bytes are valid until your request handler returns.
941func (ctx *RequestCtx) Referer() []byte {
942 return ctx.Request.Header.Referer()
943}
944
945// UserAgent returns User-Agent header value from the request.
946//
947// The returned bytes are valid until your request handler returns.
948func (ctx *RequestCtx) UserAgent() []byte {
949 return ctx.Request.Header.UserAgent()
950}
951
952// Path returns requested path.
953//
954// The returned bytes are valid until your request handler returns.
955func (ctx *RequestCtx) Path() []byte {
956 return ctx.URI().Path()
957}
958
959// Host returns requested host.
960//
961// The returned bytes are valid until your request handler returns.
962func (ctx *RequestCtx) Host() []byte {
963 return ctx.URI().Host()
964}
965
966// QueryArgs returns query arguments from RequestURI.
967//
968// It doesn't return POST'ed arguments - use PostArgs() for this.
969//
970// See also PostArgs, FormValue and FormFile.
971//
972// These args are valid until your request handler returns.
973func (ctx *RequestCtx) QueryArgs() *Args {
974 return ctx.URI().QueryArgs()
975}
976
977// PostArgs returns POST arguments.
978//
979// It doesn't return query arguments from RequestURI - use QueryArgs for this.
980//
981// See also QueryArgs, FormValue and FormFile.
982//
983// These args are valid until your request handler returns.
984func (ctx *RequestCtx) PostArgs() *Args {
985 return ctx.Request.PostArgs()
986}
987
988// MultipartForm returns requests's multipart form.
989//
990// Returns ErrNoMultipartForm if request's content-type
991// isn't 'multipart/form-data'.
992//
993// All uploaded temporary files are automatically deleted after
994// returning from RequestHandler. Either move or copy uploaded files
995// into new place if you want retaining them.
996//
997// Use SaveMultipartFile function for permanently saving uploaded file.
998//
999// The returned form is valid until your request handler returns.
1000//
1001// See also FormFile and FormValue.
1002func (ctx *RequestCtx) MultipartForm() (*multipart.Form, error) {
1003 return ctx.Request.MultipartForm()
1004}
1005
1006// FormFile returns uploaded file associated with the given multipart form key.
1007//
1008// The file is automatically deleted after returning from RequestHandler,
1009// so either move or copy uploaded file into new place if you want retaining it.
1010//
1011// Use SaveMultipartFile function for permanently saving uploaded file.
1012//
1013// The returned file header is valid until your request handler returns.
1014func (ctx *RequestCtx) FormFile(key string) (*multipart.FileHeader, error) {
1015 mf, err := ctx.MultipartForm()
1016 if err != nil {
1017 return nil, err
1018 }
1019 if mf.File == nil {
1020 return nil, err
1021 }
1022 fhh := mf.File[key]
1023 if fhh == nil {
1024 return nil, ErrMissingFile
1025 }
1026 return fhh[0], nil
1027}
1028
1029// ErrMissingFile may be returned from FormFile when the is no uploaded file
1030// associated with the given multipart form key.
1031var ErrMissingFile = errors.New("there is no uploaded file associated with the given key")
1032
1033// SaveMultipartFile saves multipart file fh under the given filename path.
1034func SaveMultipartFile(fh *multipart.FileHeader, path string) (err error) {
1035 var (
1036 f multipart.File
1037 ff *os.File
1038 )
1039 f, err = fh.Open()
1040 if err != nil {
1041 return
1042 }
1043
1044 var ok bool
1045 if ff, ok = f.(*os.File); ok {
1046 // Windows can't rename files that are opened.
1047 if err = f.Close(); err != nil {
1048 return
1049 }
1050
1051 // If renaming fails we try the normal copying method.
1052 // Renaming could fail if the files are on different devices.
1053 if os.Rename(ff.Name(), path) == nil {
1054 return nil
1055 }
1056
1057 // Reopen f for the code below.
1058 if f, err = fh.Open(); err != nil {
1059 return
1060 }
1061 }
1062
1063 defer func() {
1064 e := f.Close()
1065 if err == nil {
1066 err = e
1067 }
1068 }()
1069
1070 if ff, err = os.Create(path); err != nil {
1071 return
1072 }
1073 defer func() {
1074 e := ff.Close()
1075 if err == nil {
1076 err = e
1077 }
1078 }()
1079 _, err = copyZeroAlloc(ff, f)
1080 return
1081}
1082
1083// FormValue returns form value associated with the given key.
1084//
1085// The value is searched in the following places:
1086//
1087// * Query string.
1088// * POST or PUT body.
1089//
1090// There are more fine-grained methods for obtaining form values:
1091//
1092// * QueryArgs for obtaining values from query string.
1093// * PostArgs for obtaining values from POST or PUT body.
1094// * MultipartForm for obtaining values from multipart form.
1095// * FormFile for obtaining uploaded files.
1096//
1097// The returned value is valid until your request handler returns.
1098func (ctx *RequestCtx) FormValue(key string) []byte {
1099 v := ctx.QueryArgs().Peek(key)
1100 if len(v) > 0 {
1101 return v
1102 }
1103 v = ctx.PostArgs().Peek(key)
1104 if len(v) > 0 {
1105 return v
1106 }
1107 mf, err := ctx.MultipartForm()
1108 if err == nil && mf.Value != nil {
1109 vv := mf.Value[key]
1110 if len(vv) > 0 {
1111 return []byte(vv[0])
1112 }
1113 }
1114 return nil
1115}
1116
1117// IsGet returns true if request method is GET.
1118func (ctx *RequestCtx) IsGet() bool {
1119 return ctx.Request.Header.IsGet()
1120}
1121
1122// IsPost returns true if request method is POST.
1123func (ctx *RequestCtx) IsPost() bool {
1124 return ctx.Request.Header.IsPost()
1125}
1126
1127// IsPut returns true if request method is PUT.
1128func (ctx *RequestCtx) IsPut() bool {
1129 return ctx.Request.Header.IsPut()
1130}
1131
1132// IsDelete returns true if request method is DELETE.
1133func (ctx *RequestCtx) IsDelete() bool {
1134 return ctx.Request.Header.IsDelete()
1135}
1136
1137// IsConnect returns true if request method is CONNECT.
1138func (ctx *RequestCtx) IsConnect() bool {
1139 return ctx.Request.Header.IsConnect()
1140}
1141
1142// IsOptions returns true if request method is OPTIONS.
1143func (ctx *RequestCtx) IsOptions() bool {
1144 return ctx.Request.Header.IsOptions()
1145}
1146
1147// IsTrace returns true if request method is TRACE.
1148func (ctx *RequestCtx) IsTrace() bool {
1149 return ctx.Request.Header.IsTrace()
1150}
1151
1152// IsPatch returns true if request method is PATCH.
1153func (ctx *RequestCtx) IsPatch() bool {
1154 return ctx.Request.Header.IsPatch()
1155}
1156
1157// Method return request method.
1158//
1159// Returned value is valid until your request handler returns.
1160func (ctx *RequestCtx) Method() []byte {
1161 return ctx.Request.Header.Method()
1162}
1163
1164// IsHead returns true if request method is HEAD.
1165func (ctx *RequestCtx) IsHead() bool {
1166 return ctx.Request.Header.IsHead()
1167}
1168
1169// RemoteAddr returns client address for the given request.
1170//
1171// Always returns non-nil result.
1172func (ctx *RequestCtx) RemoteAddr() net.Addr {
1173 if ctx.remoteAddr != nil {
1174 return ctx.remoteAddr
1175 }
1176 if ctx.c == nil {
1177 return zeroTCPAddr
1178 }
1179 addr := ctx.c.RemoteAddr()
1180 if addr == nil {
1181 return zeroTCPAddr
1182 }
1183 return addr
1184}
1185
1186// SetRemoteAddr sets remote address to the given value.
1187//
1188// Set nil value to resore default behaviour for using
1189// connection remote address.
1190func (ctx *RequestCtx) SetRemoteAddr(remoteAddr net.Addr) {
1191 ctx.remoteAddr = remoteAddr
1192}
1193
1194// LocalAddr returns server address for the given request.
1195//
1196// Always returns non-nil result.
1197func (ctx *RequestCtx) LocalAddr() net.Addr {
1198 if ctx.c == nil {
1199 return zeroTCPAddr
1200 }
1201 addr := ctx.c.LocalAddr()
1202 if addr == nil {
1203 return zeroTCPAddr
1204 }
1205 return addr
1206}
1207
1208// RemoteIP returns the client ip the request came from.
1209//
1210// Always returns non-nil result.
1211func (ctx *RequestCtx) RemoteIP() net.IP {
1212 return addrToIP(ctx.RemoteAddr())
1213}
1214
1215// LocalIP returns the server ip the request came to.
1216//
1217// Always returns non-nil result.
1218func (ctx *RequestCtx) LocalIP() net.IP {
1219 return addrToIP(ctx.LocalAddr())
1220}
1221
1222func addrToIP(addr net.Addr) net.IP {
1223 x, ok := addr.(*net.TCPAddr)
1224 if !ok {
1225 return net.IPv4zero
1226 }
1227 return x.IP
1228}
1229
1230// Error sets response status code to the given value and sets response body
1231// to the given message.
1232//
1233// Warning: this will reset the response headers and body already set!
1234func (ctx *RequestCtx) Error(msg string, statusCode int) {
1235 ctx.Response.Reset()
1236 ctx.SetStatusCode(statusCode)
1237 ctx.SetContentTypeBytes(defaultContentType)
1238 ctx.SetBodyString(msg)
1239}
1240
1241// Success sets response Content-Type and body to the given values.
1242func (ctx *RequestCtx) Success(contentType string, body []byte) {
1243 ctx.SetContentType(contentType)
1244 ctx.SetBody(body)
1245}
1246
1247// SuccessString sets response Content-Type and body to the given values.
1248func (ctx *RequestCtx) SuccessString(contentType, body string) {
1249 ctx.SetContentType(contentType)
1250 ctx.SetBodyString(body)
1251}
1252
1253// Redirect sets 'Location: uri' response header and sets the given statusCode.
1254//
1255// statusCode must have one of the following values:
1256//
1257// * StatusMovedPermanently (301)
1258// * StatusFound (302)
1259// * StatusSeeOther (303)
1260// * StatusTemporaryRedirect (307)
1261// * StatusPermanentRedirect (308)
1262//
1263// All other statusCode values are replaced by StatusFound (302).
1264//
1265// The redirect uri may be either absolute or relative to the current
1266// request uri. Fasthttp will always send an absolute uri back to the client.
1267// To send a relative uri you can use the following code:
1268//
1269// strLocation = []byte("Location") // Put this with your top level var () declarations.
1270// ctx.Response.Header.SetCanonical(strLocation, "/relative?uri")
1271// ctx.Response.SetStatusCode(fasthttp.StatusMovedPermanently)
1272//
1273func (ctx *RequestCtx) Redirect(uri string, statusCode int) {
1274 u := AcquireURI()
1275 ctx.URI().CopyTo(u)
1276 u.Update(uri)
1277 ctx.redirect(u.FullURI(), statusCode)
1278 ReleaseURI(u)
1279}
1280
1281// RedirectBytes sets 'Location: uri' response header and sets
1282// the given statusCode.
1283//
1284// statusCode must have one of the following values:
1285//
1286// * StatusMovedPermanently (301)
1287// * StatusFound (302)
1288// * StatusSeeOther (303)
1289// * StatusTemporaryRedirect (307)
1290// * StatusPermanentRedirect (308)
1291//
1292// All other statusCode values are replaced by StatusFound (302).
1293//
1294// The redirect uri may be either absolute or relative to the current
1295// request uri. Fasthttp will always send an absolute uri back to the client.
1296// To send a relative uri you can use the following code:
1297//
1298// strLocation = []byte("Location") // Put this with your top level var () declarations.
1299// ctx.Response.Header.SetCanonical(strLocation, "/relative?uri")
1300// ctx.Response.SetStatusCode(fasthttp.StatusMovedPermanently)
1301//
1302func (ctx *RequestCtx) RedirectBytes(uri []byte, statusCode int) {
1303 s := b2s(uri)
1304 ctx.Redirect(s, statusCode)
1305}
1306
1307func (ctx *RequestCtx) redirect(uri []byte, statusCode int) {
1308 ctx.Response.Header.SetCanonical(strLocation, uri)
1309 statusCode = getRedirectStatusCode(statusCode)
1310 ctx.Response.SetStatusCode(statusCode)
1311}
1312
1313func getRedirectStatusCode(statusCode int) int {
1314 if statusCode == StatusMovedPermanently || statusCode == StatusFound ||
1315 statusCode == StatusSeeOther || statusCode == StatusTemporaryRedirect ||
1316 statusCode == StatusPermanentRedirect {
1317 return statusCode
1318 }
1319 return StatusFound
1320}
1321
1322// SetBody sets response body to the given value.
1323//
1324// It is safe re-using body argument after the function returns.
1325func (ctx *RequestCtx) SetBody(body []byte) {
1326 ctx.Response.SetBody(body)
1327}
1328
1329// SetBodyString sets response body to the given value.
1330func (ctx *RequestCtx) SetBodyString(body string) {
1331 ctx.Response.SetBodyString(body)
1332}
1333
1334// ResetBody resets response body contents.
1335func (ctx *RequestCtx) ResetBody() {
1336 ctx.Response.ResetBody()
1337}
1338
1339// SendFile sends local file contents from the given path as response body.
1340//
1341// This is a shortcut to ServeFile(ctx, path).
1342//
1343// SendFile logs all the errors via ctx.Logger.
1344//
1345// See also ServeFile, FSHandler and FS.
1346//
1347// WARNING: do not pass any user supplied paths to this function!
1348// WARNING: if path is based on user input users will be able to request
1349// any file on your filesystem! Use fasthttp.FS with a sane Root instead.
1350func (ctx *RequestCtx) SendFile(path string) {
1351 ServeFile(ctx, path)
1352}
1353
1354// SendFileBytes sends local file contents from the given path as response body.
1355//
1356// This is a shortcut to ServeFileBytes(ctx, path).
1357//
1358// SendFileBytes logs all the errors via ctx.Logger.
1359//
1360// See also ServeFileBytes, FSHandler and FS.
1361//
1362// WARNING: do not pass any user supplied paths to this function!
1363// WARNING: if path is based on user input users will be able to request
1364// any file on your filesystem! Use fasthttp.FS with a sane Root instead.
1365func (ctx *RequestCtx) SendFileBytes(path []byte) {
1366 ServeFileBytes(ctx, path)
1367}
1368
1369// IfModifiedSince returns true if lastModified exceeds 'If-Modified-Since'
1370// value from the request header.
1371//
1372// The function returns true also 'If-Modified-Since' request header is missing.
1373func (ctx *RequestCtx) IfModifiedSince(lastModified time.Time) bool {
1374 ifModStr := ctx.Request.Header.peek(strIfModifiedSince)
1375 if len(ifModStr) == 0 {
1376 return true
1377 }
1378 ifMod, err := ParseHTTPDate(ifModStr)
1379 if err != nil {
1380 return true
1381 }
1382 lastModified = lastModified.Truncate(time.Second)
1383 return ifMod.Before(lastModified)
1384}
1385
1386// NotModified resets response and sets '304 Not Modified' response status code.
1387func (ctx *RequestCtx) NotModified() {
1388 ctx.Response.Reset()
1389 ctx.SetStatusCode(StatusNotModified)
1390}
1391
1392// NotFound resets response and sets '404 Not Found' response status code.
1393func (ctx *RequestCtx) NotFound() {
1394 ctx.Response.Reset()
1395 ctx.SetStatusCode(StatusNotFound)
1396 ctx.SetBodyString("404 Page not found")
1397}
1398
1399// Write writes p into response body.
1400func (ctx *RequestCtx) Write(p []byte) (int, error) {
1401 ctx.Response.AppendBody(p)
1402 return len(p), nil
1403}
1404
1405// WriteString appends s to response body.
1406func (ctx *RequestCtx) WriteString(s string) (int, error) {
1407 ctx.Response.AppendBodyString(s)
1408 return len(s), nil
1409}
1410
1411// PostBody returns POST request body.
1412//
1413// The returned bytes are valid until your request handler returns.
1414func (ctx *RequestCtx) PostBody() []byte {
1415 return ctx.Request.Body()
1416}
1417
1418// SetBodyStream sets response body stream and, optionally body size.
1419//
1420// bodyStream.Close() is called after finishing reading all body data
1421// if it implements io.Closer.
1422//
1423// If bodySize is >= 0, then bodySize bytes must be provided by bodyStream
1424// before returning io.EOF.
1425//
1426// If bodySize < 0, then bodyStream is read until io.EOF.
1427//
1428// See also SetBodyStreamWriter.
1429func (ctx *RequestCtx) SetBodyStream(bodyStream io.Reader, bodySize int) {
1430 ctx.Response.SetBodyStream(bodyStream, bodySize)
1431}
1432
1433// SetBodyStreamWriter registers the given stream writer for populating
1434// response body.
1435//
1436// Access to RequestCtx and/or its' members is forbidden from sw.
1437//
1438// This function may be used in the following cases:
1439//
1440// * if response body is too big (more than 10MB).
1441// * if response body is streamed from slow external sources.
1442// * if response body must be streamed to the client in chunks.
1443// (aka `http server push`).
1444func (ctx *RequestCtx) SetBodyStreamWriter(sw StreamWriter) {
1445 ctx.Response.SetBodyStreamWriter(sw)
1446}
1447
1448// IsBodyStream returns true if response body is set via SetBodyStream*.
1449func (ctx *RequestCtx) IsBodyStream() bool {
1450 return ctx.Response.IsBodyStream()
1451}
1452
1453// Logger returns logger, which may be used for logging arbitrary
1454// request-specific messages inside RequestHandler.
1455//
1456// Each message logged via returned logger contains request-specific information
1457// such as request id, request duration, local address, remote address,
1458// request method and request url.
1459//
1460// It is safe re-using returned logger for logging multiple messages
1461// for the current request.
1462//
1463// The returned logger is valid until your request handler returns.
1464func (ctx *RequestCtx) Logger() Logger {
1465 if ctx.logger.ctx == nil {
1466 ctx.logger.ctx = ctx
1467 }
1468 if ctx.logger.logger == nil {
1469 ctx.logger.logger = ctx.s.logger()
1470 }
1471 return &ctx.logger
1472}
1473
1474// TimeoutError sets response status code to StatusRequestTimeout and sets
1475// body to the given msg.
1476//
1477// All response modifications after TimeoutError call are ignored.
1478//
1479// TimeoutError MUST be called before returning from RequestHandler if there are
1480// references to ctx and/or its members in other goroutines remain.
1481//
1482// Usage of this function is discouraged. Prefer eliminating ctx references
1483// from pending goroutines instead of using this function.
1484func (ctx *RequestCtx) TimeoutError(msg string) {
1485 ctx.TimeoutErrorWithCode(msg, StatusRequestTimeout)
1486}
1487
1488// TimeoutErrorWithCode sets response body to msg and response status
1489// code to statusCode.
1490//
1491// All response modifications after TimeoutErrorWithCode call are ignored.
1492//
1493// TimeoutErrorWithCode MUST be called before returning from RequestHandler
1494// if there are references to ctx and/or its members in other goroutines remain.
1495//
1496// Usage of this function is discouraged. Prefer eliminating ctx references
1497// from pending goroutines instead of using this function.
1498func (ctx *RequestCtx) TimeoutErrorWithCode(msg string, statusCode int) {
1499 var resp Response
1500 resp.SetStatusCode(statusCode)
1501 resp.SetBodyString(msg)
1502 ctx.TimeoutErrorWithResponse(&resp)
1503}
1504
1505// TimeoutErrorWithResponse marks the ctx as timed out and sends the given
1506// response to the client.
1507//
1508// All ctx modifications after TimeoutErrorWithResponse call are ignored.
1509//
1510// TimeoutErrorWithResponse MUST be called before returning from RequestHandler
1511// if there are references to ctx and/or its members in other goroutines remain.
1512//
1513// Usage of this function is discouraged. Prefer eliminating ctx references
1514// from pending goroutines instead of using this function.
1515func (ctx *RequestCtx) TimeoutErrorWithResponse(resp *Response) {
1516 respCopy := &Response{}
1517 resp.CopyTo(respCopy)
1518 ctx.timeoutResponse = respCopy
1519}
1520
1521// NextProto adds nph to be processed when key is negotiated when TLS
1522// connection is established.
1523//
1524// This function can only be called before the server is started.
1525func (s *Server) NextProto(key string, nph ServeHandler) {
1526 if s.nextProtos == nil {
1527 s.nextProtos = make(map[string]ServeHandler)
1528 }
1529
1530 s.configTLS()
1531 s.TLSConfig.NextProtos = append(s.TLSConfig.NextProtos, key)
1532 s.nextProtos[key] = nph
1533}
1534
1535func (s *Server) getNextProto(c net.Conn) (proto string, err error) {
1536 if tlsConn, ok := c.(connTLSer); ok {
1537 if s.ReadTimeout > 0 {
1538 if err := c.SetReadDeadline(time.Now().Add(s.ReadTimeout)); err != nil {
1539 panic(fmt.Sprintf("BUG: error in SetReadDeadline(%s): %s", s.ReadTimeout, err))
1540 }
1541 }
1542
1543 if s.WriteTimeout > 0 {
1544 if err := c.SetWriteDeadline(time.Now().Add(s.WriteTimeout)); err != nil {
1545 panic(fmt.Sprintf("BUG: error in SetWriteDeadline(%s): %s", s.WriteTimeout, err))
1546 }
1547 }
1548
1549 err = tlsConn.Handshake()
1550 if err == nil {
1551 proto = tlsConn.ConnectionState().NegotiatedProtocol
1552 }
1553 }
1554 return
1555}
1556
1557// tcpKeepAliveListener sets TCP keep-alive timeouts on accepted
1558// connections. It's used by ListenAndServe, ListenAndServeTLS and
1559// ListenAndServeTLSEmbed so dead TCP connections (e.g. closing laptop mid-download)
1560// eventually go away.
1561type tcpKeepaliveListener struct {
1562 *net.TCPListener
1563 keepalive bool
1564 keepalivePeriod time.Duration
1565}
1566
1567func (ln tcpKeepaliveListener) Accept() (net.Conn, error) {
1568 tc, err := ln.AcceptTCP()
1569 if err != nil {
1570 return nil, err
1571 }
1572 if err := tc.SetKeepAlive(ln.keepalive); err != nil {
1573 tc.Close() //nolint:errcheck
1574 return nil, err
1575 }
1576 if ln.keepalivePeriod > 0 {
1577 if err := tc.SetKeepAlivePeriod(ln.keepalivePeriod); err != nil {
1578 tc.Close() //nolint:errcheck
1579 return nil, err
1580 }
1581 }
1582 return tc, nil
1583}
1584
1585// ListenAndServe serves HTTP requests from the given TCP4 addr.
1586//
1587// Pass custom listener to Serve if you need listening on non-TCP4 media
1588// such as IPv6.
1589//
1590// Accepted connections are configured to enable TCP keep-alives.
1591func (s *Server) ListenAndServe(addr string) error {
1592 ln, err := net.Listen("tcp4", addr)
1593 if err != nil {
1594 return err
1595 }
1596 if tcpln, ok := ln.(*net.TCPListener); ok {
1597 return s.Serve(tcpKeepaliveListener{
1598 TCPListener: tcpln,
1599 keepalive: s.TCPKeepalive,
1600 keepalivePeriod: s.TCPKeepalivePeriod,
1601 })
1602 }
1603 return s.Serve(ln)
1604}
1605
1606// ListenAndServeUNIX serves HTTP requests from the given UNIX addr.
1607//
1608// The function deletes existing file at addr before starting serving.
1609//
1610// The server sets the given file mode for the UNIX addr.
1611func (s *Server) ListenAndServeUNIX(addr string, mode os.FileMode) error {
1612 if err := os.Remove(addr); err != nil && !os.IsNotExist(err) {
1613 return fmt.Errorf("unexpected error when trying to remove unix socket file %q: %w", addr, err)
1614 }
1615 ln, err := net.Listen("unix", addr)
1616 if err != nil {
1617 return err
1618 }
1619 if err = os.Chmod(addr, mode); err != nil {
1620 return fmt.Errorf("cannot chmod %#o for %q: %w", mode, addr, err)
1621 }
1622 return s.Serve(ln)
1623}
1624
1625// ListenAndServeTLS serves HTTPS requests from the given TCP4 addr.
1626//
1627// certFile and keyFile are paths to TLS certificate and key files.
1628//
1629// Pass custom listener to Serve if you need listening on non-TCP4 media
1630// such as IPv6.
1631//
1632// If the certFile or keyFile has not been provided to the server structure,
1633// the function will use the previously added TLS configuration.
1634//
1635// Accepted connections are configured to enable TCP keep-alives.
1636func (s *Server) ListenAndServeTLS(addr, certFile, keyFile string) error {
1637 ln, err := net.Listen("tcp4", addr)
1638 if err != nil {
1639 return err
1640 }
1641 if tcpln, ok := ln.(*net.TCPListener); ok {
1642 return s.ServeTLS(tcpKeepaliveListener{
1643 TCPListener: tcpln,
1644 keepalive: s.TCPKeepalive,
1645 keepalivePeriod: s.TCPKeepalivePeriod,
1646 }, certFile, keyFile)
1647 }
1648 return s.ServeTLS(ln, certFile, keyFile)
1649}
1650
1651// ListenAndServeTLSEmbed serves HTTPS requests from the given TCP4 addr.
1652//
1653// certData and keyData must contain valid TLS certificate and key data.
1654//
1655// Pass custom listener to Serve if you need listening on arbitrary media
1656// such as IPv6.
1657//
1658// If the certFile or keyFile has not been provided the server structure,
1659// the function will use previously added TLS configuration.
1660//
1661// Accepted connections are configured to enable TCP keep-alives.
1662func (s *Server) ListenAndServeTLSEmbed(addr string, certData, keyData []byte) error {
1663 ln, err := net.Listen("tcp4", addr)
1664 if err != nil {
1665 return err
1666 }
1667 if tcpln, ok := ln.(*net.TCPListener); ok {
1668 return s.ServeTLSEmbed(tcpKeepaliveListener{
1669 TCPListener: tcpln,
1670 keepalive: s.TCPKeepalive,
1671 keepalivePeriod: s.TCPKeepalivePeriod,
1672 }, certData, keyData)
1673 }
1674 return s.ServeTLSEmbed(ln, certData, keyData)
1675}
1676
1677// ServeTLS serves HTTPS requests from the given listener.
1678//
1679// certFile and keyFile are paths to TLS certificate and key files.
1680//
1681// If the certFile or keyFile has not been provided the server structure,
1682// the function will use previously added TLS configuration.
1683func (s *Server) ServeTLS(ln net.Listener, certFile, keyFile string) error {
1684 s.mu.Lock()
1685 err := s.AppendCert(certFile, keyFile)
1686 if err != nil && err != errNoCertOrKeyProvided {
1687 s.mu.Unlock()
1688 return err
1689 }
1690 if s.TLSConfig == nil {
1691 s.mu.Unlock()
1692 return errNoCertOrKeyProvided
1693 }
1694
1695 // BuildNameToCertificate has been deprecated since 1.14.
1696 // But since we also support older versions we'll keep this here.
1697 s.TLSConfig.BuildNameToCertificate() //nolint:staticcheck
1698
1699 s.mu.Unlock()
1700
1701 return s.Serve(
1702 tls.NewListener(ln, s.TLSConfig.Clone()),
1703 )
1704}
1705
1706// ServeTLSEmbed serves HTTPS requests from the given listener.
1707//
1708// certData and keyData must contain valid TLS certificate and key data.
1709//
1710// If the certFile or keyFile has not been provided the server structure,
1711// the function will use previously added TLS configuration.
1712func (s *Server) ServeTLSEmbed(ln net.Listener, certData, keyData []byte) error {
1713 s.mu.Lock()
1714
1715 err := s.AppendCertEmbed(certData, keyData)
1716 if err != nil && err != errNoCertOrKeyProvided {
1717 s.mu.Unlock()
1718 return err
1719 }
1720 if s.TLSConfig == nil {
1721 s.mu.Unlock()
1722 return errNoCertOrKeyProvided
1723 }
1724
1725 // BuildNameToCertificate has been deprecated since 1.14.
1726 // But since we also support older versions we'll keep this here.
1727 s.TLSConfig.BuildNameToCertificate() //nolint:staticcheck
1728
1729 s.mu.Unlock()
1730
1731 return s.Serve(
1732 tls.NewListener(ln, s.TLSConfig.Clone()),
1733 )
1734}
1735
1736// AppendCert appends certificate and keyfile to TLS Configuration.
1737//
1738// This function allows programmer to handle multiple domains
1739// in one server structure. See examples/multidomain
1740func (s *Server) AppendCert(certFile, keyFile string) error {
1741 if len(certFile) == 0 && len(keyFile) == 0 {
1742 return errNoCertOrKeyProvided
1743 }
1744
1745 cert, err := tls.LoadX509KeyPair(certFile, keyFile)
1746 if err != nil {
1747 return fmt.Errorf("cannot load TLS key pair from certFile=%q and keyFile=%q: %w", certFile, keyFile, err)
1748 }
1749
1750 s.configTLS()
1751 s.TLSConfig.Certificates = append(s.TLSConfig.Certificates, cert)
1752
1753 return nil
1754}
1755
1756// AppendCertEmbed does the same as AppendCert but using in-memory data.
1757func (s *Server) AppendCertEmbed(certData, keyData []byte) error {
1758 if len(certData) == 0 && len(keyData) == 0 {
1759 return errNoCertOrKeyProvided
1760 }
1761
1762 cert, err := tls.X509KeyPair(certData, keyData)
1763 if err != nil {
1764 return fmt.Errorf("cannot load TLS key pair from the provided certData(%d) and keyData(%d): %s",
1765 len(certData), len(keyData), err)
1766 }
1767
1768 s.configTLS()
1769 s.TLSConfig.Certificates = append(s.TLSConfig.Certificates, cert)
1770
1771 return nil
1772}
1773
1774func (s *Server) configTLS() {
1775 if s.TLSConfig == nil {
1776 s.TLSConfig = &tls.Config{}
1777 }
1778}
1779
1780// DefaultConcurrency is the maximum number of concurrent connections
1781// the Server may serve by default (i.e. if Server.Concurrency isn't set).
1782const DefaultConcurrency = 256 * 1024
1783
1784// Serve serves incoming connections from the given listener.
1785//
1786// Serve blocks until the given listener returns permanent error.
1787func (s *Server) Serve(ln net.Listener) error {
1788 var lastOverflowErrorTime time.Time
1789 var lastPerIPErrorTime time.Time
1790 var c net.Conn
1791 var err error
1792
1793 maxWorkersCount := s.getConcurrency()
1794
1795 s.mu.Lock()
1796 {
1797 s.ln = append(s.ln, ln)
1798 if s.done == nil {
1799 s.done = make(chan struct{})
1800 }
1801
1802 if s.concurrencyCh == nil {
1803 s.concurrencyCh = make(chan struct{}, maxWorkersCount)
1804 }
1805 }
1806 s.mu.Unlock()
1807
1808 wp := &workerPool{
1809 WorkerFunc: s.serveConn,
1810 MaxWorkersCount: maxWorkersCount,
1811 LogAllErrors: s.LogAllErrors,
1812 MaxIdleWorkerDuration: s.MaxIdleWorkerDuration,
1813 Logger: s.logger(),
1814 connState: s.setState,
1815 }
1816 wp.Start()
1817
1818 // Count our waiting to accept a connection as an open connection.
1819 // This way we can't get into any weird state where just after accepting
1820 // a connection Shutdown is called which reads open as 0 because it isn't
1821 // incremented yet.
1822 atomic.AddInt32(&s.open, 1)
1823 defer atomic.AddInt32(&s.open, -1)
1824
1825 for {
1826 if c, err = acceptConn(s, ln, &lastPerIPErrorTime); err != nil {
1827 wp.Stop()
1828 if err == io.EOF {
1829 return nil
1830 }
1831 return err
1832 }
1833 s.setState(c, StateNew)
1834 atomic.AddInt32(&s.open, 1)
1835 if !wp.Serve(c) {
1836 atomic.AddInt32(&s.open, -1)
1837 s.writeFastError(c, StatusServiceUnavailable,
1838 "The connection cannot be served because Server.Concurrency limit exceeded")
1839 c.Close()
1840 s.setState(c, StateClosed)
1841 if time.Since(lastOverflowErrorTime) > time.Minute {
1842 s.logger().Printf("The incoming connection cannot be served, because %d concurrent connections are served. "+
1843 "Try increasing Server.Concurrency", maxWorkersCount)
1844 lastOverflowErrorTime = time.Now()
1845 }
1846
1847 // The current server reached concurrency limit,
1848 // so give other concurrently running servers a chance
1849 // accepting incoming connections on the same address.
1850 //
1851 // There is a hope other servers didn't reach their
1852 // concurrency limits yet :)
1853 //
1854 // See also: https://github.com/valyala/fasthttp/pull/485#discussion_r239994990
1855 if s.SleepWhenConcurrencyLimitsExceeded > 0 {
1856 time.Sleep(s.SleepWhenConcurrencyLimitsExceeded)
1857 }
1858 }
1859 c = nil
1860 }
1861}
1862
1863// Shutdown gracefully shuts down the server without interrupting any active connections.
1864// Shutdown works by first closing all open listeners and then waiting indefinitely for all connections to return to idle and then shut down.
1865//
1866// When Shutdown is called, Serve, ListenAndServe, and ListenAndServeTLS immediately return nil.
1867// Make sure the program doesn't exit and waits instead for Shutdown to return.
1868//
1869// Shutdown does not close keepalive connections so its recommended to set ReadTimeout and IdleTimeout to something else than 0.
1870func (s *Server) Shutdown() error {
1871 s.mu.Lock()
1872 defer s.mu.Unlock()
1873
1874 atomic.StoreInt32(&s.stop, 1)
1875 defer atomic.StoreInt32(&s.stop, 0)
1876
1877 if s.ln == nil {
1878 return nil
1879 }
1880
1881 for _, ln := range s.ln {
1882 if err := ln.Close(); err != nil {
1883 return err
1884 }
1885 }
1886
1887 if s.done != nil {
1888 close(s.done)
1889 }
1890
1891 s.closeIdleConns()
1892
1893 // Closing the listener will make Serve() call Stop on the worker pool.
1894 // Setting .stop to 1 will make serveConn() break out of its loop.
1895 // Now we just have to wait until all workers are done.
1896 for {
1897 if open := atomic.LoadInt32(&s.open); open == 0 {
1898 break
1899 }
1900 // This is not an optimal solution but using a sync.WaitGroup
1901 // here causes data races as it's hard to prevent Add() to be called
1902 // while Wait() is waiting.
1903 time.Sleep(time.Millisecond * 100)
1904 }
1905
1906 s.done = nil
1907 s.ln = nil
1908 return nil
1909}
1910
1911func acceptConn(s *Server, ln net.Listener, lastPerIPErrorTime *time.Time) (net.Conn, error) {
1912 for {
1913 c, err := ln.Accept()
1914 if err != nil {
1915 if c != nil {
1916 panic("BUG: net.Listener returned non-nil conn and non-nil error")
1917 }
1918 if netErr, ok := err.(net.Error); ok && netErr.Temporary() {
1919 s.logger().Printf("Temporary error when accepting new connections: %s", netErr)
1920 time.Sleep(time.Second)
1921 continue
1922 }
1923 if err != io.EOF && !strings.Contains(err.Error(), "use of closed network connection") {
1924 s.logger().Printf("Permanent error when accepting new connections: %s", err)
1925 return nil, err
1926 }
1927 return nil, io.EOF
1928 }
1929 if c == nil {
1930 panic("BUG: net.Listener returned (nil, nil)")
1931 }
1932 if s.MaxConnsPerIP > 0 {
1933 pic := wrapPerIPConn(s, c)
1934 if pic == nil {
1935 if time.Since(*lastPerIPErrorTime) > time.Minute {
1936 s.logger().Printf("The number of connections from %s exceeds MaxConnsPerIP=%d",
1937 getConnIP4(c), s.MaxConnsPerIP)
1938 *lastPerIPErrorTime = time.Now()
1939 }
1940 continue
1941 }
1942 c = pic
1943 }
1944 return c, nil
1945 }
1946}
1947
1948func wrapPerIPConn(s *Server, c net.Conn) net.Conn {
1949 ip := getUint32IP(c)
1950 if ip == 0 {
1951 return c
1952 }
1953 n := s.perIPConnCounter.Register(ip)
1954 if n > s.MaxConnsPerIP {
1955 s.perIPConnCounter.Unregister(ip)
1956 s.writeFastError(c, StatusTooManyRequests, "The number of connections from your ip exceeds MaxConnsPerIP")
1957 c.Close()
1958 return nil
1959 }
1960 return acquirePerIPConn(c, ip, &s.perIPConnCounter)
1961}
1962
1963var defaultLogger = Logger(log.New(os.Stderr, "", log.LstdFlags))
1964
1965func (s *Server) logger() Logger {
1966 if s.Logger != nil {
1967 return s.Logger
1968 }
1969 return defaultLogger
1970}
1971
1972var (
1973 // ErrPerIPConnLimit may be returned from ServeConn if the number of connections
1974 // per ip exceeds Server.MaxConnsPerIP.
1975 ErrPerIPConnLimit = errors.New("too many connections per ip")
1976
1977 // ErrConcurrencyLimit may be returned from ServeConn if the number
1978 // of concurrently served connections exceeds Server.Concurrency.
1979 ErrConcurrencyLimit = errors.New("cannot serve the connection because Server.Concurrency concurrent connections are served")
1980)
1981
1982// ServeConn serves HTTP requests from the given connection.
1983//
1984// ServeConn returns nil if all requests from the c are successfully served.
1985// It returns non-nil error otherwise.
1986//
1987// Connection c must immediately propagate all the data passed to Write()
1988// to the client. Otherwise requests' processing may hang.
1989//
1990// ServeConn closes c before returning.
1991func (s *Server) ServeConn(c net.Conn) error {
1992 if s.MaxConnsPerIP > 0 {
1993 pic := wrapPerIPConn(s, c)
1994 if pic == nil {
1995 return ErrPerIPConnLimit
1996 }
1997 c = pic
1998 }
1999
2000 n := atomic.AddUint32(&s.concurrency, 1)
2001 if n > uint32(s.getConcurrency()) {
2002 atomic.AddUint32(&s.concurrency, ^uint32(0))
2003 s.writeFastError(c, StatusServiceUnavailable, "The connection cannot be served because Server.Concurrency limit exceeded")
2004 c.Close()
2005 return ErrConcurrencyLimit
2006 }
2007
2008 atomic.AddInt32(&s.open, 1)
2009
2010 err := s.serveConn(c)
2011
2012 atomic.AddUint32(&s.concurrency, ^uint32(0))
2013
2014 if err != errHijacked {
2015 err1 := c.Close()
2016 s.setState(c, StateClosed)
2017 if err == nil {
2018 err = err1
2019 }
2020 } else {
2021 err = nil
2022 s.setState(c, StateHijacked)
2023 }
2024 return err
2025}
2026
2027var errHijacked = errors.New("connection has been hijacked")
2028
2029// GetCurrentConcurrency returns a number of currently served
2030// connections.
2031//
2032// This function is intended be used by monitoring systems
2033func (s *Server) GetCurrentConcurrency() uint32 {
2034 return atomic.LoadUint32(&s.concurrency)
2035}
2036
2037// GetOpenConnectionsCount returns a number of opened connections.
2038//
2039// This function is intended be used by monitoring systems
2040func (s *Server) GetOpenConnectionsCount() int32 {
2041 if atomic.LoadInt32(&s.stop) == 0 {
2042 // Decrement by one to avoid reporting the extra open value that gets
2043 // counted while the server is listening.
2044 return atomic.LoadInt32(&s.open) - 1
2045 }
2046 // This is not perfect, because s.stop could have changed to zero
2047 // before we load the value of s.open. However, in the common case
2048 // this avoids underreporting open connections by 1 during server shutdown.
2049 return atomic.LoadInt32(&s.open)
2050}
2051
2052func (s *Server) getConcurrency() int {
2053 n := s.Concurrency
2054 if n <= 0 {
2055 n = DefaultConcurrency
2056 }
2057 return n
2058}
2059
2060var globalConnID uint64
2061
2062func nextConnID() uint64 {
2063 return atomic.AddUint64(&globalConnID, 1)
2064}
2065
2066// DefaultMaxRequestBodySize is the maximum request body size the server
2067// reads by default.
2068//
2069// See Server.MaxRequestBodySize for details.
2070const DefaultMaxRequestBodySize = 4 * 1024 * 1024
2071
2072func (s *Server) idleTimeout() time.Duration {
2073 if s.IdleTimeout != 0 {
2074 return s.IdleTimeout
2075 }
2076 return s.ReadTimeout
2077}
2078
2079func (s *Server) serveConnCleanup() {
2080 atomic.AddInt32(&s.open, -1)
2081 atomic.AddUint32(&s.concurrency, ^uint32(0))
2082}
2083
2084func (s *Server) serveConn(c net.Conn) (err error) {
2085 defer s.serveConnCleanup()
2086 atomic.AddUint32(&s.concurrency, 1)
2087
2088 var proto string
2089 if proto, err = s.getNextProto(c); err != nil {
2090 return
2091 }
2092 if handler, ok := s.nextProtos[proto]; ok {
2093 // Remove read or write deadlines that might have previously been set.
2094 // The next handler is responsible for setting its own deadlines.
2095 if s.ReadTimeout > 0 || s.WriteTimeout > 0 {
2096 if err := c.SetDeadline(zeroTime); err != nil {
2097 panic(fmt.Sprintf("BUG: error in SetDeadline(zeroTime): %s", err))
2098 }
2099 }
2100
2101 return handler(c)
2102 }
2103
2104 var serverName []byte
2105 if !s.NoDefaultServerHeader {
2106 serverName = s.getServerName()
2107 }
2108 connRequestNum := uint64(0)
2109 connID := nextConnID()
2110 connTime := time.Now()
2111 maxRequestBodySize := s.MaxRequestBodySize
2112 if maxRequestBodySize <= 0 {
2113 maxRequestBodySize = DefaultMaxRequestBodySize
2114 }
2115 writeTimeout := s.WriteTimeout
2116 previousWriteTimeout := time.Duration(0)
2117
2118 ctx := s.acquireCtx(c)
2119 ctx.connTime = connTime
2120 isTLS := ctx.IsTLS()
2121 var (
2122 br *bufio.Reader
2123 bw *bufio.Writer
2124
2125 timeoutResponse *Response
2126 hijackHandler HijackHandler
2127 hijackNoResponse bool
2128
2129 connectionClose bool
2130 isHTTP11 bool
2131
2132 continueReadingRequest bool = true
2133 )
2134 for {
2135 connRequestNum++
2136
2137 // If this is a keep-alive connection set the idle timeout.
2138 if connRequestNum > 1 {
2139 if d := s.idleTimeout(); d > 0 {
2140 if err := c.SetReadDeadline(time.Now().Add(d)); err != nil {
2141 panic(fmt.Sprintf("BUG: error in SetReadDeadline(%s): %s", d, err))
2142 }
2143 }
2144 }
2145
2146 if !s.ReduceMemoryUsage || br != nil {
2147 if br == nil {
2148 br = acquireReader(ctx)
2149 }
2150
2151 // If this is a keep-alive connection we want to try and read the first bytes
2152 // within the idle time.
2153 if connRequestNum > 1 {
2154 var b []byte
2155 b, err = br.Peek(1)
2156 if len(b) == 0 {
2157 // If reading from a keep-alive connection returns nothing it means
2158 // the connection was closed (either timeout or from the other side).
2159 if err != io.EOF {
2160 err = ErrNothingRead{err}
2161 }
2162 }
2163 }
2164 } else {
2165 // If this is a keep-alive connection acquireByteReader will try to peek
2166 // a couple of bytes already so the idle timeout will already be used.
2167 br, err = acquireByteReader(&ctx)
2168 }
2169
2170 ctx.Request.isTLS = isTLS
2171 ctx.Response.Header.noDefaultContentType = s.NoDefaultContentType
2172 ctx.Response.Header.noDefaultDate = s.NoDefaultDate
2173
2174 // Secure header error logs configuration
2175 ctx.Request.Header.secureErrorLogMessage = s.SecureErrorLogMessage
2176 ctx.Response.Header.secureErrorLogMessage = s.SecureErrorLogMessage
2177 ctx.Request.secureErrorLogMessage = s.SecureErrorLogMessage
2178 ctx.Response.secureErrorLogMessage = s.SecureErrorLogMessage
2179
2180 if err == nil {
2181 if s.ReadTimeout > 0 {
2182 if err := c.SetReadDeadline(time.Now().Add(s.ReadTimeout)); err != nil {
2183 panic(fmt.Sprintf("BUG: error in SetReadDeadline(%s): %s", s.ReadTimeout, err))
2184 }
2185 } else if s.IdleTimeout > 0 && connRequestNum > 1 {
2186 // If this was an idle connection and the server has an IdleTimeout but
2187 // no ReadTimeout then we should remove the ReadTimeout.
2188 if err := c.SetReadDeadline(zeroTime); err != nil {
2189 panic(fmt.Sprintf("BUG: error in SetReadDeadline(zeroTime): %s", err))
2190 }
2191 }
2192 if s.DisableHeaderNamesNormalizing {
2193 ctx.Request.Header.DisableNormalizing()
2194 ctx.Response.Header.DisableNormalizing()
2195 }
2196
2197 // Reading Headers.
2198 //
2199 // If we have pipline response in the outgoing buffer,
2200 // we only want to try and read the next headers once.
2201 // If we have to wait for the next request we flush the
2202 // outgoing buffer first so it doesn't have to wait.
2203 if bw != nil && bw.Buffered() > 0 {
2204 err = ctx.Request.Header.readLoop(br, false)
2205 if err == errNeedMore {
2206 err = bw.Flush()
2207 if err != nil {
2208 break
2209 }
2210
2211 err = ctx.Request.Header.Read(br)
2212 }
2213 } else {
2214 err = ctx.Request.Header.Read(br)
2215 }
2216
2217 if err == nil {
2218 if onHdrRecv := s.HeaderReceived; onHdrRecv != nil {
2219 reqConf := onHdrRecv(&ctx.Request.Header)
2220 if reqConf.ReadTimeout > 0 {
2221 deadline := time.Now().Add(reqConf.ReadTimeout)
2222 if err := c.SetReadDeadline(deadline); err != nil {
2223 panic(fmt.Sprintf("BUG: error in SetReadDeadline(%s): %s", deadline, err))
2224 }
2225 }
2226 if reqConf.MaxRequestBodySize > 0 {
2227 maxRequestBodySize = reqConf.MaxRequestBodySize
2228 }
2229 if reqConf.WriteTimeout > 0 {
2230 writeTimeout = reqConf.WriteTimeout
2231 }
2232 }
2233 //read body
2234 if s.StreamRequestBody {
2235 err = ctx.Request.readBodyStream(br, maxRequestBodySize, s.GetOnly, !s.DisablePreParseMultipartForm)
2236 } else {
2237 err = ctx.Request.readLimitBody(br, maxRequestBodySize, s.GetOnly, !s.DisablePreParseMultipartForm)
2238 }
2239 }
2240
2241 if err == nil {
2242 // If we read any bytes off the wire, we're active.
2243 s.setState(c, StateActive)
2244 }
2245
2246 if (s.ReduceMemoryUsage && br.Buffered() == 0) || err != nil {
2247 releaseReader(s, br)
2248 br = nil
2249 }
2250 }
2251
2252 if err != nil {
2253 if err == io.EOF {
2254 err = nil
2255 } else if nr, ok := err.(ErrNothingRead); ok {
2256 if connRequestNum > 1 {
2257 // This is not the first request and we haven't read a single byte
2258 // of a new request yet. This means it's just a keep-alive connection
2259 // closing down either because the remote closed it or because
2260 // or a read timeout on our side. Either way just close the connection
2261 // and don't return any error response.
2262 err = nil
2263 } else {
2264 err = nr.error
2265 }
2266 }
2267
2268 if err != nil {
2269 bw = s.writeErrorResponse(bw, ctx, serverName, err)
2270 }
2271 break
2272 }
2273
2274 // 'Expect: 100-continue' request handling.
2275 // See https://www.w3.org/Protocols/rfc2616/rfc2616-sec8.html#sec8.2.3 for details.
2276 if ctx.Request.MayContinue() {
2277
2278 // Allow the ability to deny reading the incoming request body
2279 if s.ContinueHandler != nil {
2280 if continueReadingRequest = s.ContinueHandler(&ctx.Request.Header); !continueReadingRequest {
2281 if br != nil {
2282 br.Reset(ctx.c)
2283 }
2284
2285 ctx.SetStatusCode(StatusExpectationFailed)
2286 }
2287 }
2288
2289 if continueReadingRequest {
2290 if bw == nil {
2291 bw = acquireWriter(ctx)
2292 }
2293
2294 // Send 'HTTP/1.1 100 Continue' response.
2295 _, err = bw.Write(strResponseContinue)
2296 if err != nil {
2297 break
2298 }
2299 err = bw.Flush()
2300 if err != nil {
2301 break
2302 }
2303 if s.ReduceMemoryUsage {
2304 releaseWriter(s, bw)
2305 bw = nil
2306 }
2307
2308 // Read request body.
2309 if br == nil {
2310 br = acquireReader(ctx)
2311 }
2312
2313 if s.StreamRequestBody {
2314 err = ctx.Request.ContinueReadBodyStream(br, maxRequestBodySize, !s.DisablePreParseMultipartForm)
2315 } else {
2316 err = ctx.Request.ContinueReadBody(br, maxRequestBodySize, !s.DisablePreParseMultipartForm)
2317 }
2318 if (s.ReduceMemoryUsage && br.Buffered() == 0) || err != nil {
2319 releaseReader(s, br)
2320 br = nil
2321 }
2322 if err != nil {
2323 bw = s.writeErrorResponse(bw, ctx, serverName, err)
2324 break
2325 }
2326 }
2327 }
2328
2329 connectionClose = s.DisableKeepalive || ctx.Request.Header.ConnectionClose()
2330 isHTTP11 = ctx.Request.Header.IsHTTP11()
2331
2332 if serverName != nil {
2333 ctx.Response.Header.SetServerBytes(serverName)
2334 }
2335 ctx.connID = connID
2336 ctx.connRequestNum = connRequestNum
2337 ctx.time = time.Now()
2338
2339 // If a client denies a request the handler should not be called
2340 if continueReadingRequest {
2341 s.Handler(ctx)
2342 }
2343
2344 timeoutResponse = ctx.timeoutResponse
2345 if timeoutResponse != nil {
2346 // Acquire a new ctx because the old one will still be in use by the timeout out handler.
2347 ctx = s.acquireCtx(c)
2348 timeoutResponse.CopyTo(&ctx.Response)
2349 }
2350
2351 if ctx.IsHead() {
2352 ctx.Response.SkipBody = true
2353 }
2354
2355 hijackHandler = ctx.hijackHandler
2356 ctx.hijackHandler = nil
2357 hijackNoResponse = ctx.hijackNoResponse && hijackHandler != nil
2358 ctx.hijackNoResponse = false
2359
2360 if s.MaxRequestsPerConn > 0 && connRequestNum >= uint64(s.MaxRequestsPerConn) {
2361 ctx.SetConnectionClose()
2362 }
2363
2364 if writeTimeout > 0 {
2365 if err := c.SetWriteDeadline(time.Now().Add(writeTimeout)); err != nil {
2366 panic(fmt.Sprintf("BUG: error in SetWriteDeadline(%s): %s", writeTimeout, err))
2367 }
2368 previousWriteTimeout = writeTimeout
2369 } else if previousWriteTimeout > 0 {
2370 // We don't want a write timeout but we previously set one, remove it.
2371 if err := c.SetWriteDeadline(zeroTime); err != nil {
2372 panic(fmt.Sprintf("BUG: error in SetWriteDeadline(zeroTime): %s", err))
2373 }
2374 previousWriteTimeout = 0
2375 }
2376
2377 connectionClose = connectionClose || ctx.Response.ConnectionClose() || (s.CloseOnShutdown && atomic.LoadInt32(&s.stop) == 1)
2378 if connectionClose {
2379 ctx.Response.Header.SetCanonical(strConnection, strClose)
2380 } else if !isHTTP11 {
2381 // Set 'Connection: keep-alive' response header for non-HTTP/1.1 request.
2382 // There is no need in setting this header for http/1.1, since in http/1.1
2383 // connections are keep-alive by default.
2384 ctx.Response.Header.SetCanonical(strConnection, strKeepAlive)
2385 }
2386
2387 if serverName != nil && len(ctx.Response.Header.Server()) == 0 {
2388 ctx.Response.Header.SetServerBytes(serverName)
2389 }
2390
2391 if !hijackNoResponse {
2392 if bw == nil {
2393 bw = acquireWriter(ctx)
2394 }
2395 if err = writeResponse(ctx, bw); err != nil {
2396 break
2397 }
2398
2399 // Only flush the writer if we don't have another request in the pipeline.
2400 // This is a big of an ugly optimization for https://www.techempower.com/benchmarks/
2401 // This benchmark will send 16 pipelined requests. It is faster to pack as many responses
2402 // in a TCP packet and send it back at once than waiting for a flush every request.
2403 // In real world circumstances this behaviour could be argued as being wrong.
2404 if br == nil || br.Buffered() == 0 || connectionClose {
2405 err = bw.Flush()
2406 if err != nil {
2407 break
2408 }
2409 }
2410 if connectionClose {
2411 break
2412 }
2413 if s.ReduceMemoryUsage && hijackHandler == nil {
2414 releaseWriter(s, bw)
2415 bw = nil
2416 }
2417 }
2418
2419 if hijackHandler != nil {
2420 var hjr io.Reader = c
2421 if br != nil {
2422 hjr = br
2423 br = nil
2424 }
2425 if bw != nil {
2426 err = bw.Flush()
2427 if err != nil {
2428 break
2429 }
2430 releaseWriter(s, bw)
2431 bw = nil
2432 }
2433 err = c.SetDeadline(zeroTime)
2434 if err != nil {
2435 break
2436 }
2437 go hijackConnHandler(ctx, hjr, c, s, hijackHandler)
2438 err = errHijacked
2439 break
2440 }
2441
2442 if ctx.Request.bodyStream != nil {
2443 if rs, ok := ctx.Request.bodyStream.(*requestStream); ok {
2444 releaseRequestStream(rs)
2445 }
2446 }
2447
2448 s.setState(c, StateIdle)
2449 ctx.userValues.Reset()
2450 ctx.Request.Reset()
2451 ctx.Response.Reset()
2452
2453 if atomic.LoadInt32(&s.stop) == 1 {
2454 err = nil
2455 break
2456 }
2457 }
2458
2459 if br != nil {
2460 releaseReader(s, br)
2461 }
2462 if bw != nil {
2463 releaseWriter(s, bw)
2464 }
2465 if hijackHandler == nil {
2466 s.releaseCtx(ctx)
2467 }
2468
2469 return
2470}
2471
2472func (s *Server) setState(nc net.Conn, state ConnState) {
2473 s.trackConn(nc, state)
2474 if hook := s.ConnState; hook != nil {
2475 hook(nc, state)
2476 }
2477}
2478
2479func hijackConnHandler(ctx *RequestCtx, r io.Reader, c net.Conn, s *Server, h HijackHandler) {
2480 hjc := s.acquireHijackConn(r, c)
2481 h(hjc)
2482
2483 if br, ok := r.(*bufio.Reader); ok {
2484 releaseReader(s, br)
2485 }
2486 if !s.KeepHijackedConns {
2487 c.Close()
2488 s.releaseHijackConn(hjc)
2489 }
2490 s.releaseCtx(ctx)
2491}
2492
2493func (s *Server) acquireHijackConn(r io.Reader, c net.Conn) *hijackConn {
2494 v := s.hijackConnPool.Get()
2495 if v == nil {
2496 hjc := &hijackConn{
2497 Conn: c,
2498 r: r,
2499 s: s,
2500 }
2501 return hjc
2502 }
2503 hjc := v.(*hijackConn)
2504 hjc.Conn = c
2505 hjc.r = r
2506 return hjc
2507}
2508
2509func (s *Server) releaseHijackConn(hjc *hijackConn) {
2510 hjc.Conn = nil
2511 hjc.r = nil
2512 s.hijackConnPool.Put(hjc)
2513}
2514
2515type hijackConn struct {
2516 net.Conn
2517 r io.Reader
2518 s *Server
2519}
2520
2521func (c *hijackConn) UnsafeConn() net.Conn {
2522 return c.Conn
2523}
2524
2525func (c *hijackConn) Read(p []byte) (int, error) {
2526 return c.r.Read(p)
2527}
2528
2529func (c *hijackConn) Close() error {
2530 if !c.s.KeepHijackedConns {
2531 // when we do not keep hijacked connections,
2532 // it is closed in hijackConnHandler.
2533 return nil
2534 }
2535
2536 conn := c.Conn
2537 c.s.releaseHijackConn(c)
2538 return conn.Close()
2539}
2540
2541// LastTimeoutErrorResponse returns the last timeout response set
2542// via TimeoutError* call.
2543//
2544// This function is intended for custom server implementations.
2545func (ctx *RequestCtx) LastTimeoutErrorResponse() *Response {
2546 return ctx.timeoutResponse
2547}
2548
2549func writeResponse(ctx *RequestCtx, w *bufio.Writer) error {
2550 if ctx.timeoutResponse != nil {
2551 panic("BUG: cannot write timed out response")
2552 }
2553 err := ctx.Response.Write(w)
2554
2555 return err
2556}
2557
2558const (
2559 defaultReadBufferSize = 4096
2560 defaultWriteBufferSize = 4096
2561)
2562
2563func acquireByteReader(ctxP **RequestCtx) (*bufio.Reader, error) {
2564 ctx := *ctxP
2565 s := ctx.s
2566 c := ctx.c
2567 s.releaseCtx(ctx)
2568
2569 // Make GC happy, so it could garbage collect ctx
2570 // while we waiting for the next request.
2571 ctx = nil
2572 *ctxP = nil
2573
2574 var b [1]byte
2575 n, err := c.Read(b[:])
2576
2577 ctx = s.acquireCtx(c)
2578 *ctxP = ctx
2579 if err != nil {
2580 // Treat all errors as EOF on unsuccessful read
2581 // of the first request byte.
2582 return nil, io.EOF
2583 }
2584 if n != 1 {
2585 panic("BUG: Reader must return at least one byte")
2586 }
2587
2588 ctx.fbr.c = c
2589 ctx.fbr.ch = b[0]
2590 ctx.fbr.byteRead = false
2591 r := acquireReader(ctx)
2592 r.Reset(&ctx.fbr)
2593 return r, nil
2594}
2595
2596func acquireReader(ctx *RequestCtx) *bufio.Reader {
2597 v := ctx.s.readerPool.Get()
2598 if v == nil {
2599 n := ctx.s.ReadBufferSize
2600 if n <= 0 {
2601 n = defaultReadBufferSize
2602 }
2603 return bufio.NewReaderSize(ctx.c, n)
2604 }
2605 r := v.(*bufio.Reader)
2606 r.Reset(ctx.c)
2607 return r
2608}
2609
2610func releaseReader(s *Server, r *bufio.Reader) {
2611 s.readerPool.Put(r)
2612}
2613
2614func acquireWriter(ctx *RequestCtx) *bufio.Writer {
2615 v := ctx.s.writerPool.Get()
2616 if v == nil {
2617 n := ctx.s.WriteBufferSize
2618 if n <= 0 {
2619 n = defaultWriteBufferSize
2620 }
2621 return bufio.NewWriterSize(ctx.c, n)
2622 }
2623 w := v.(*bufio.Writer)
2624 w.Reset(ctx.c)
2625 return w
2626}
2627
2628func releaseWriter(s *Server, w *bufio.Writer) {
2629 s.writerPool.Put(w)
2630}
2631
2632func (s *Server) acquireCtx(c net.Conn) (ctx *RequestCtx) {
2633 v := s.ctxPool.Get()
2634 if v == nil {
2635 keepBodyBuffer := !s.ReduceMemoryUsage
2636
2637 ctx = new(RequestCtx)
2638 ctx.Request.keepBodyBuffer = keepBodyBuffer
2639 ctx.Response.keepBodyBuffer = keepBodyBuffer
2640 } else {
2641 ctx = v.(*RequestCtx)
2642 }
2643
2644 ctx.s = s
2645 ctx.c = c
2646
2647 return ctx
2648}
2649
2650// Init2 prepares ctx for passing to RequestHandler.
2651//
2652// conn is used only for determining local and remote addresses.
2653//
2654// This function is intended for custom Server implementations.
2655// See https://github.com/valyala/httpteleport for details.
2656func (ctx *RequestCtx) Init2(conn net.Conn, logger Logger, reduceMemoryUsage bool) {
2657 ctx.c = conn
2658 ctx.remoteAddr = nil
2659 ctx.logger.logger = logger
2660 ctx.connID = nextConnID()
2661 ctx.s = fakeServer
2662 ctx.connRequestNum = 0
2663 ctx.connTime = time.Now()
2664
2665 keepBodyBuffer := !reduceMemoryUsage
2666 ctx.Request.keepBodyBuffer = keepBodyBuffer
2667 ctx.Response.keepBodyBuffer = keepBodyBuffer
2668}
2669
2670// Init prepares ctx for passing to RequestHandler.
2671//
2672// remoteAddr and logger are optional. They are used by RequestCtx.Logger().
2673//
2674// This function is intended for custom Server implementations.
2675func (ctx *RequestCtx) Init(req *Request, remoteAddr net.Addr, logger Logger) {
2676 if remoteAddr == nil {
2677 remoteAddr = zeroTCPAddr
2678 }
2679 c := &fakeAddrer{
2680 laddr: zeroTCPAddr,
2681 raddr: remoteAddr,
2682 }
2683 if logger == nil {
2684 logger = defaultLogger
2685 }
2686 ctx.Init2(c, logger, true)
2687 req.CopyTo(&ctx.Request)
2688}
2689
2690// Deadline returns the time when work done on behalf of this context
2691// should be canceled. Deadline returns ok==false when no deadline is
2692// set. Successive calls to Deadline return the same results.
2693//
2694// This method always returns 0, false and is only present to make
2695// RequestCtx implement the context interface.
2696func (ctx *RequestCtx) Deadline() (deadline time.Time, ok bool) {
2697 return
2698}
2699
2700// Done returns a channel that's closed when work done on behalf of this
2701// context should be canceled. Done may return nil if this context can
2702// never be canceled. Successive calls to Done return the same value.
2703func (ctx *RequestCtx) Done() <-chan struct{} {
2704 return ctx.s.done
2705}
2706
2707// Err returns a non-nil error value after Done is closed,
2708// successive calls to Err return the same error.
2709// If Done is not yet closed, Err returns nil.
2710// If Done is closed, Err returns a non-nil error explaining why:
2711// Canceled if the context was canceled (via server Shutdown)
2712// or DeadlineExceeded if the context's deadline passed.
2713func (ctx *RequestCtx) Err() error {
2714 select {
2715 case <-ctx.s.done:
2716 return context.Canceled
2717 default:
2718 return nil
2719 }
2720}
2721
2722// Value returns the value associated with this context for key, or nil
2723// if no value is associated with key. Successive calls to Value with
2724// the same key returns the same result.
2725//
2726// This method is present to make RequestCtx implement the context interface.
2727// This method is the same as calling ctx.UserValue(key)
2728func (ctx *RequestCtx) Value(key interface{}) interface{} {
2729 if keyString, ok := key.(string); ok {
2730 return ctx.UserValue(keyString)
2731 }
2732 return nil
2733}
2734
2735var fakeServer = &Server{
2736 // Initialize concurrencyCh for TimeoutHandler
2737 concurrencyCh: make(chan struct{}, DefaultConcurrency),
2738}
2739
2740type fakeAddrer struct {
2741 net.Conn
2742 laddr net.Addr
2743 raddr net.Addr
2744}
2745
2746func (fa *fakeAddrer) RemoteAddr() net.Addr {
2747 return fa.raddr
2748}
2749
2750func (fa *fakeAddrer) LocalAddr() net.Addr {
2751 return fa.laddr
2752}
2753
2754func (fa *fakeAddrer) Read(p []byte) (int, error) {
2755 panic("BUG: unexpected Read call")
2756}
2757
2758func (fa *fakeAddrer) Write(p []byte) (int, error) {
2759 panic("BUG: unexpected Write call")
2760}
2761
2762func (fa *fakeAddrer) Close() error {
2763 panic("BUG: unexpected Close call")
2764}
2765
2766func (s *Server) releaseCtx(ctx *RequestCtx) {
2767 if ctx.timeoutResponse != nil {
2768 panic("BUG: cannot release timed out RequestCtx")
2769 }
2770
2771 ctx.reset()
2772 s.ctxPool.Put(ctx)
2773}
2774
2775func (s *Server) getServerName() []byte {
2776 v := s.serverName.Load()
2777 var serverName []byte
2778 if v == nil {
2779 serverName = []byte(s.Name)
2780 if len(serverName) == 0 {
2781 serverName = defaultServerName
2782 }
2783 s.serverName.Store(serverName)
2784 } else {
2785 serverName = v.([]byte)
2786 }
2787 return serverName
2788}
2789
2790func (s *Server) writeFastError(w io.Writer, statusCode int, msg string) {
2791 w.Write(formatStatusLine(nil, strHTTP11, statusCode, s2b(StatusMessage(statusCode)))) //nolint:errcheck
2792
2793 server := ""
2794 if !s.NoDefaultServerHeader {
2795 server = fmt.Sprintf("Server: %s\r\n", s.getServerName())
2796 }
2797
2798 date := ""
2799 if !s.NoDefaultDate {
2800 serverDateOnce.Do(updateServerDate)
2801 date = fmt.Sprintf("Date: %s\r\n", serverDate.Load())
2802 }
2803
2804 fmt.Fprintf(w, "Connection: close\r\n"+
2805 server+
2806 date+
2807 "Content-Type: text/plain\r\n"+
2808 "Content-Length: %d\r\n"+
2809 "\r\n"+
2810 "%s",
2811 len(msg), msg)
2812}
2813
2814func defaultErrorHandler(ctx *RequestCtx, err error) {
2815 if _, ok := err.(*ErrSmallBuffer); ok {
2816 ctx.Error("Too big request header", StatusRequestHeaderFieldsTooLarge)
2817 } else if netErr, ok := err.(*net.OpError); ok && netErr.Timeout() {
2818 ctx.Error("Request timeout", StatusRequestTimeout)
2819 } else {
2820 ctx.Error("Error when parsing request", StatusBadRequest)
2821 }
2822}
2823
2824func (s *Server) writeErrorResponse(bw *bufio.Writer, ctx *RequestCtx, serverName []byte, err error) *bufio.Writer {
2825 errorHandler := defaultErrorHandler
2826 if s.ErrorHandler != nil {
2827 errorHandler = s.ErrorHandler
2828 }
2829
2830 errorHandler(ctx, err)
2831
2832 if serverName != nil {
2833 ctx.Response.Header.SetServerBytes(serverName)
2834 }
2835 ctx.SetConnectionClose()
2836 if bw == nil {
2837 bw = acquireWriter(ctx)
2838 }
2839
2840 writeResponse(ctx, bw) //nolint:errcheck
2841 ctx.Response.Reset()
2842 bw.Flush()
2843
2844 return bw
2845}
2846
2847func (s *Server) trackConn(c net.Conn, state ConnState) {
2848 s.idleConnsMu.Lock()
2849 switch state {
2850 case StateIdle:
2851 if s.idleConns == nil {
2852 s.idleConns = make(map[net.Conn]struct{})
2853 }
2854 s.idleConns[c] = struct{}{}
2855
2856 default:
2857 delete(s.idleConns, c)
2858 }
2859 s.idleConnsMu.Unlock()
2860}
2861
2862func (s *Server) closeIdleConns() {
2863 s.idleConnsMu.Lock()
2864 for c := range s.idleConns {
2865 _ = c.Close()
2866 }
2867 s.idleConns = nil
2868 s.idleConnsMu.Unlock()
2869}
2870
2871// A ConnState represents the state of a client connection to a server.
2872// It's used by the optional Server.ConnState hook.
2873type ConnState int
2874
2875const (
2876 // StateNew represents a new connection that is expected to
2877 // send a request immediately. Connections begin at this
2878 // state and then transition to either StateActive or
2879 // StateClosed.
2880 StateNew ConnState = iota
2881
2882 // StateActive represents a connection that has read 1 or more
2883 // bytes of a request. The Server.ConnState hook for
2884 // StateActive fires before the request has entered a handler
2885 // and doesn't fire again until the request has been
2886 // handled. After the request is handled, the state
2887 // transitions to StateClosed, StateHijacked, or StateIdle.
2888 // For HTTP/2, StateActive fires on the transition from zero
2889 // to one active request, and only transitions away once all
2890 // active requests are complete. That means that ConnState
2891 // cannot be used to do per-request work; ConnState only notes
2892 // the overall state of the connection.
2893 StateActive
2894
2895 // StateIdle represents a connection that has finished
2896 // handling a request and is in the keep-alive state, waiting
2897 // for a new request. Connections transition from StateIdle
2898 // to either StateActive or StateClosed.
2899 StateIdle
2900
2901 // StateHijacked represents a hijacked connection.
2902 // This is a terminal state. It does not transition to StateClosed.
2903 StateHijacked
2904
2905 // StateClosed represents a closed connection.
2906 // This is a terminal state. Hijacked connections do not
2907 // transition to StateClosed.
2908 StateClosed
2909)
2910
2911var stateName = map[ConnState]string{
2912 StateNew: "new",
2913 StateActive: "active",
2914 StateIdle: "idle",
2915 StateHijacked: "hijacked",
2916 StateClosed: "closed",
2917}
2918
2919func (c ConnState) String() string {
2920 return stateName[c]
2921}
Note: See TracBrowser for help on using the repository browser.