source: code/trunk/vendor/github.com/valyala/fasthttp/header.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: 87.5 KB
Line 
1package fasthttp
2
3import (
4 "bufio"
5 "bytes"
6 "errors"
7 "fmt"
8 "io"
9 "sync"
10 "sync/atomic"
11 "time"
12)
13
14const (
15 rChar = byte('\r')
16 nChar = byte('\n')
17)
18
19// ResponseHeader represents HTTP response header.
20//
21// It is forbidden copying ResponseHeader instances.
22// Create new instances instead and use CopyTo.
23//
24// ResponseHeader instance MUST NOT be used from concurrently running
25// goroutines.
26type ResponseHeader struct {
27 noCopy noCopy //nolint:unused,structcheck
28
29 disableNormalizing bool
30 noHTTP11 bool
31 connectionClose bool
32 noDefaultContentType bool
33 noDefaultDate bool
34
35 statusCode int
36 statusMessage []byte
37 protocol []byte
38 contentLength int
39 contentLengthBytes []byte
40 secureErrorLogMessage bool
41
42 contentType []byte
43 server []byte
44
45 h []argsKV
46 trailer []argsKV
47 bufKV argsKV
48
49 cookies []argsKV
50}
51
52// RequestHeader represents HTTP request header.
53//
54// It is forbidden copying RequestHeader instances.
55// Create new instances instead and use CopyTo.
56//
57// RequestHeader instance MUST NOT be used from concurrently running
58// goroutines.
59type RequestHeader struct {
60 noCopy noCopy //nolint:unused,structcheck
61
62 disableNormalizing bool
63 noHTTP11 bool
64 connectionClose bool
65 noDefaultContentType bool
66
67 // These two fields have been moved close to other bool fields
68 // for reducing RequestHeader object size.
69 cookiesCollected bool
70
71 contentLength int
72 contentLengthBytes []byte
73 secureErrorLogMessage bool
74
75 method []byte
76 requestURI []byte
77 proto []byte
78 host []byte
79 contentType []byte
80 userAgent []byte
81
82 h []argsKV
83 trailer []argsKV
84 bufKV argsKV
85
86 cookies []argsKV
87
88 // stores an immutable copy of headers as they were received from the
89 // wire.
90 rawHeaders []byte
91}
92
93// SetContentRange sets 'Content-Range: bytes startPos-endPos/contentLength'
94// header.
95func (h *ResponseHeader) SetContentRange(startPos, endPos, contentLength int) {
96 b := h.bufKV.value[:0]
97 b = append(b, strBytes...)
98 b = append(b, ' ')
99 b = AppendUint(b, startPos)
100 b = append(b, '-')
101 b = AppendUint(b, endPos)
102 b = append(b, '/')
103 b = AppendUint(b, contentLength)
104 h.bufKV.value = b
105
106 h.SetCanonical(strContentRange, h.bufKV.value)
107}
108
109// SetByteRange sets 'Range: bytes=startPos-endPos' header.
110//
111// * If startPos is negative, then 'bytes=-startPos' value is set.
112// * If endPos is negative, then 'bytes=startPos-' value is set.
113func (h *RequestHeader) SetByteRange(startPos, endPos int) {
114 b := h.bufKV.value[:0]
115 b = append(b, strBytes...)
116 b = append(b, '=')
117 if startPos >= 0 {
118 b = AppendUint(b, startPos)
119 } else {
120 endPos = -startPos
121 }
122 b = append(b, '-')
123 if endPos >= 0 {
124 b = AppendUint(b, endPos)
125 }
126 h.bufKV.value = b
127
128 h.SetCanonical(strRange, h.bufKV.value)
129}
130
131// StatusCode returns response status code.
132func (h *ResponseHeader) StatusCode() int {
133 if h.statusCode == 0 {
134 return StatusOK
135 }
136 return h.statusCode
137}
138
139// SetStatusCode sets response status code.
140func (h *ResponseHeader) SetStatusCode(statusCode int) {
141 h.statusCode = statusCode
142}
143
144// StatusMessage returns response status message.
145func (h *ResponseHeader) StatusMessage() []byte {
146 return h.statusMessage
147}
148
149// SetStatusMessage sets response status message bytes.
150func (h *ResponseHeader) SetStatusMessage(statusMessage []byte) {
151 h.statusMessage = append(h.statusMessage[:0], statusMessage...)
152}
153
154// Protocol returns response protocol bytes.
155func (h *ResponseHeader) Protocol() []byte {
156 if len(h.protocol) > 0 {
157 return h.protocol
158 }
159 return strHTTP11
160}
161
162// SetProtocol sets response protocol bytes.
163func (h *ResponseHeader) SetProtocol(protocol []byte) {
164 h.protocol = append(h.protocol[:0], protocol...)
165}
166
167// SetLastModified sets 'Last-Modified' header to the given value.
168func (h *ResponseHeader) SetLastModified(t time.Time) {
169 h.bufKV.value = AppendHTTPDate(h.bufKV.value[:0], t)
170 h.SetCanonical(strLastModified, h.bufKV.value)
171}
172
173// ConnectionClose returns true if 'Connection: close' header is set.
174func (h *ResponseHeader) ConnectionClose() bool {
175 return h.connectionClose
176}
177
178// SetConnectionClose sets 'Connection: close' header.
179func (h *ResponseHeader) SetConnectionClose() {
180 h.connectionClose = true
181}
182
183// ResetConnectionClose clears 'Connection: close' header if it exists.
184func (h *ResponseHeader) ResetConnectionClose() {
185 if h.connectionClose {
186 h.connectionClose = false
187 h.h = delAllArgsBytes(h.h, strConnection)
188 }
189}
190
191// ConnectionClose returns true if 'Connection: close' header is set.
192func (h *RequestHeader) ConnectionClose() bool {
193 return h.connectionClose
194}
195
196// SetConnectionClose sets 'Connection: close' header.
197func (h *RequestHeader) SetConnectionClose() {
198 h.connectionClose = true
199}
200
201// ResetConnectionClose clears 'Connection: close' header if it exists.
202func (h *RequestHeader) ResetConnectionClose() {
203 if h.connectionClose {
204 h.connectionClose = false
205 h.h = delAllArgsBytes(h.h, strConnection)
206 }
207}
208
209// ConnectionUpgrade returns true if 'Connection: Upgrade' header is set.
210func (h *ResponseHeader) ConnectionUpgrade() bool {
211 return hasHeaderValue(h.Peek(HeaderConnection), strUpgrade)
212}
213
214// ConnectionUpgrade returns true if 'Connection: Upgrade' header is set.
215func (h *RequestHeader) ConnectionUpgrade() bool {
216 return hasHeaderValue(h.Peek(HeaderConnection), strUpgrade)
217}
218
219// PeekCookie is able to returns cookie by a given key from response.
220func (h *ResponseHeader) PeekCookie(key string) []byte {
221 return peekArgStr(h.cookies, key)
222}
223
224// ContentLength returns Content-Length header value.
225//
226// It may be negative:
227// -1 means Transfer-Encoding: chunked.
228// -2 means Transfer-Encoding: identity.
229func (h *ResponseHeader) ContentLength() int {
230 return h.contentLength
231}
232
233// SetContentLength sets Content-Length header value.
234//
235// Content-Length may be negative:
236// -1 means Transfer-Encoding: chunked.
237// -2 means Transfer-Encoding: identity.
238func (h *ResponseHeader) SetContentLength(contentLength int) {
239 if h.mustSkipContentLength() {
240 return
241 }
242 h.contentLength = contentLength
243 if contentLength >= 0 {
244 h.contentLengthBytes = AppendUint(h.contentLengthBytes[:0], contentLength)
245 h.h = delAllArgsBytes(h.h, strTransferEncoding)
246 } else {
247 h.contentLengthBytes = h.contentLengthBytes[:0]
248 value := strChunked
249 if contentLength == -2 {
250 h.SetConnectionClose()
251 value = strIdentity
252 }
253 h.h = setArgBytes(h.h, strTransferEncoding, value, argsHasValue)
254 }
255}
256
257func (h *ResponseHeader) mustSkipContentLength() bool {
258 // From http/1.1 specs:
259 // All 1xx (informational), 204 (no content), and 304 (not modified) responses MUST NOT include a message-body
260 statusCode := h.StatusCode()
261
262 // Fast path.
263 if statusCode < 100 || statusCode == StatusOK {
264 return false
265 }
266
267 // Slow path.
268 return statusCode == StatusNotModified || statusCode == StatusNoContent || statusCode < 200
269}
270
271// ContentLength returns Content-Length header value.
272//
273// It may be negative:
274// -1 means Transfer-Encoding: chunked.
275func (h *RequestHeader) ContentLength() int {
276 return h.realContentLength()
277}
278
279// realContentLength returns the actual Content-Length set in the request,
280// including positive lengths for GET/HEAD requests.
281func (h *RequestHeader) realContentLength() int {
282 return h.contentLength
283}
284
285// SetContentLength sets Content-Length header value.
286//
287// Negative content-length sets 'Transfer-Encoding: chunked' header.
288func (h *RequestHeader) SetContentLength(contentLength int) {
289 h.contentLength = contentLength
290 if contentLength >= 0 {
291 h.contentLengthBytes = AppendUint(h.contentLengthBytes[:0], contentLength)
292 h.h = delAllArgsBytes(h.h, strTransferEncoding)
293 } else {
294 h.contentLengthBytes = h.contentLengthBytes[:0]
295 h.h = setArgBytes(h.h, strTransferEncoding, strChunked, argsHasValue)
296 }
297}
298
299func (h *ResponseHeader) isCompressibleContentType() bool {
300 contentType := h.ContentType()
301 return bytes.HasPrefix(contentType, strTextSlash) ||
302 bytes.HasPrefix(contentType, strApplicationSlash) ||
303 bytes.HasPrefix(contentType, strImageSVG) ||
304 bytes.HasPrefix(contentType, strImageIcon) ||
305 bytes.HasPrefix(contentType, strFontSlash) ||
306 bytes.HasPrefix(contentType, strMultipartSlash)
307}
308
309// ContentType returns Content-Type header value.
310func (h *ResponseHeader) ContentType() []byte {
311 contentType := h.contentType
312 if !h.noDefaultContentType && len(h.contentType) == 0 {
313 contentType = defaultContentType
314 }
315 return contentType
316}
317
318// SetContentType sets Content-Type header value.
319func (h *ResponseHeader) SetContentType(contentType string) {
320 h.contentType = append(h.contentType[:0], contentType...)
321}
322
323// SetContentTypeBytes sets Content-Type header value.
324func (h *ResponseHeader) SetContentTypeBytes(contentType []byte) {
325 h.contentType = append(h.contentType[:0], contentType...)
326}
327
328// Server returns Server header value.
329func (h *ResponseHeader) Server() []byte {
330 return h.server
331}
332
333// SetServer sets Server header value.
334func (h *ResponseHeader) SetServer(server string) {
335 h.server = append(h.server[:0], server...)
336}
337
338// SetServerBytes sets Server header value.
339func (h *ResponseHeader) SetServerBytes(server []byte) {
340 h.server = append(h.server[:0], server...)
341}
342
343// ContentType returns Content-Type header value.
344func (h *RequestHeader) ContentType() []byte {
345 return h.contentType
346}
347
348// SetContentType sets Content-Type header value.
349func (h *RequestHeader) SetContentType(contentType string) {
350 h.contentType = append(h.contentType[:0], contentType...)
351}
352
353// SetContentTypeBytes sets Content-Type header value.
354func (h *RequestHeader) SetContentTypeBytes(contentType []byte) {
355 h.contentType = append(h.contentType[:0], contentType...)
356}
357
358// SetMultipartFormBoundary sets the following Content-Type:
359// 'multipart/form-data; boundary=...'
360// where ... is substituted by the given boundary.
361func (h *RequestHeader) SetMultipartFormBoundary(boundary string) {
362 b := h.bufKV.value[:0]
363 b = append(b, strMultipartFormData...)
364 b = append(b, ';', ' ')
365 b = append(b, strBoundary...)
366 b = append(b, '=')
367 b = append(b, boundary...)
368 h.bufKV.value = b
369
370 h.SetContentTypeBytes(h.bufKV.value)
371}
372
373// SetMultipartFormBoundaryBytes sets the following Content-Type:
374// 'multipart/form-data; boundary=...'
375// where ... is substituted by the given boundary.
376func (h *RequestHeader) SetMultipartFormBoundaryBytes(boundary []byte) {
377 b := h.bufKV.value[:0]
378 b = append(b, strMultipartFormData...)
379 b = append(b, ';', ' ')
380 b = append(b, strBoundary...)
381 b = append(b, '=')
382 b = append(b, boundary...)
383 h.bufKV.value = b
384
385 h.SetContentTypeBytes(h.bufKV.value)
386}
387
388// SetTrailer sets header Trailer value for chunked response
389// to indicate which headers will be sent after the body.
390//
391// Use Set to set the trailer header later.
392//
393// Trailers are only supported with chunked transfer.
394// Trailers allow the sender to include additional headers at the end of chunked messages.
395//
396// The following trailers are forbidden:
397// 1. necessary for message framing (e.g., Transfer-Encoding and Content-Length),
398// 2. routing (e.g., Host),
399// 3. request modifiers (e.g., controls and conditionals in Section 5 of [RFC7231]),
400// 4. authentication (e.g., see [RFC7235] and [RFC6265]),
401// 5. response control data (e.g., see Section 7.1 of [RFC7231]),
402// 6. determining how to process the payload (e.g., Content-Encoding, Content-Type, Content-Range, and Trailer)
403//
404// Return ErrBadTrailer if contain any forbidden trailers.
405func (h *ResponseHeader) SetTrailer(trailer string) error {
406 return h.SetTrailerBytes(s2b(trailer))
407}
408
409// SetTrailerBytes sets Trailer header value for chunked response
410// to indicate which headers will be sent after the body.
411//
412// Use Set to set the trailer header later.
413//
414// Trailers are only supported with chunked transfer.
415// Trailers allow the sender to include additional headers at the end of chunked messages.
416//
417// The following trailers are forbidden:
418// 1. necessary for message framing (e.g., Transfer-Encoding and Content-Length),
419// 2. routing (e.g., Host),
420// 3. request modifiers (e.g., controls and conditionals in Section 5 of [RFC7231]),
421// 4. authentication (e.g., see [RFC7235] and [RFC6265]),
422// 5. response control data (e.g., see Section 7.1 of [RFC7231]),
423// 6. determining how to process the payload (e.g., Content-Encoding, Content-Type, Content-Range, and Trailer)
424//
425// Return ErrBadTrailer if contain any forbidden trailers.
426func (h *ResponseHeader) SetTrailerBytes(trailer []byte) error {
427 h.trailer = h.trailer[:0]
428 return h.AddTrailerBytes(trailer)
429}
430
431// AddTrailer add Trailer header value for chunked response
432// to indicate which headers will be sent after the body.
433//
434// Use Set to set the trailer header later.
435//
436// Trailers are only supported with chunked transfer.
437// Trailers allow the sender to include additional headers at the end of chunked messages.
438//
439// The following trailers are forbidden:
440// 1. necessary for message framing (e.g., Transfer-Encoding and Content-Length),
441// 2. routing (e.g., Host),
442// 3. request modifiers (e.g., controls and conditionals in Section 5 of [RFC7231]),
443// 4. authentication (e.g., see [RFC7235] and [RFC6265]),
444// 5. response control data (e.g., see Section 7.1 of [RFC7231]),
445// 6. determining how to process the payload (e.g., Content-Encoding, Content-Type, Content-Range, and Trailer)
446//
447// Return ErrBadTrailer if contain any forbidden trailers.
448func (h *ResponseHeader) AddTrailer(trailer string) error {
449 return h.AddTrailerBytes(s2b(trailer))
450}
451
452var ErrBadTrailer = errors.New("contain forbidden trailer")
453
454// AddTrailerBytes add Trailer header value for chunked response
455// to indicate which headers will be sent after the body.
456//
457// Use Set to set the trailer header later.
458//
459// Trailers are only supported with chunked transfer.
460// Trailers allow the sender to include additional headers at the end of chunked messages.
461//
462// The following trailers are forbidden:
463// 1. necessary for message framing (e.g., Transfer-Encoding and Content-Length),
464// 2. routing (e.g., Host),
465// 3. request modifiers (e.g., controls and conditionals in Section 5 of [RFC7231]),
466// 4. authentication (e.g., see [RFC7235] and [RFC6265]),
467// 5. response control data (e.g., see Section 7.1 of [RFC7231]),
468// 6. determining how to process the payload (e.g., Content-Encoding, Content-Type, Content-Range, and Trailer)
469//
470// Return ErrBadTrailer if contain any forbidden trailers.
471func (h *ResponseHeader) AddTrailerBytes(trailer []byte) error {
472 var err error
473 for i := -1; i+1 < len(trailer); {
474 trailer = trailer[i+1:]
475 i = bytes.IndexByte(trailer, ',')
476 if i < 0 {
477 i = len(trailer)
478 }
479 key := trailer[:i]
480 for len(key) > 0 && key[0] == ' ' {
481 key = key[1:]
482 }
483 for len(key) > 0 && key[len(key)-1] == ' ' {
484 key = key[:len(key)-1]
485 }
486 // Forbidden by RFC 7230, section 4.1.2
487 if isBadTrailer(key) {
488 err = ErrBadTrailer
489 continue
490 }
491 h.bufKV.key = append(h.bufKV.key[:0], key...)
492 normalizeHeaderKey(h.bufKV.key, h.disableNormalizing)
493 h.trailer = appendArgBytes(h.trailer, h.bufKV.key, nil, argsNoValue)
494 }
495
496 return err
497}
498
499// MultipartFormBoundary returns boundary part
500// from 'multipart/form-data; boundary=...' Content-Type.
501func (h *RequestHeader) MultipartFormBoundary() []byte {
502 b := h.ContentType()
503 if !bytes.HasPrefix(b, strMultipartFormData) {
504 return nil
505 }
506 b = b[len(strMultipartFormData):]
507 if len(b) == 0 || b[0] != ';' {
508 return nil
509 }
510
511 var n int
512 for len(b) > 0 {
513 n++
514 for len(b) > n && b[n] == ' ' {
515 n++
516 }
517 b = b[n:]
518 if !bytes.HasPrefix(b, strBoundary) {
519 if n = bytes.IndexByte(b, ';'); n < 0 {
520 return nil
521 }
522 continue
523 }
524
525 b = b[len(strBoundary):]
526 if len(b) == 0 || b[0] != '=' {
527 return nil
528 }
529 b = b[1:]
530 if n = bytes.IndexByte(b, ';'); n >= 0 {
531 b = b[:n]
532 }
533 if len(b) > 1 && b[0] == '"' && b[len(b)-1] == '"' {
534 b = b[1 : len(b)-1]
535 }
536 return b
537 }
538 return nil
539}
540
541// Host returns Host header value.
542func (h *RequestHeader) Host() []byte {
543 return h.host
544}
545
546// SetHost sets Host header value.
547func (h *RequestHeader) SetHost(host string) {
548 h.host = append(h.host[:0], host...)
549}
550
551// SetHostBytes sets Host header value.
552func (h *RequestHeader) SetHostBytes(host []byte) {
553 h.host = append(h.host[:0], host...)
554}
555
556// UserAgent returns User-Agent header value.
557func (h *RequestHeader) UserAgent() []byte {
558 return h.userAgent
559}
560
561// SetUserAgent sets User-Agent header value.
562func (h *RequestHeader) SetUserAgent(userAgent string) {
563 h.userAgent = append(h.userAgent[:0], userAgent...)
564}
565
566// SetUserAgentBytes sets User-Agent header value.
567func (h *RequestHeader) SetUserAgentBytes(userAgent []byte) {
568 h.userAgent = append(h.userAgent[:0], userAgent...)
569}
570
571// Referer returns Referer header value.
572func (h *RequestHeader) Referer() []byte {
573 return h.PeekBytes(strReferer)
574}
575
576// SetReferer sets Referer header value.
577func (h *RequestHeader) SetReferer(referer string) {
578 h.SetBytesK(strReferer, referer)
579}
580
581// SetRefererBytes sets Referer header value.
582func (h *RequestHeader) SetRefererBytes(referer []byte) {
583 h.SetCanonical(strReferer, referer)
584}
585
586// Method returns HTTP request method.
587func (h *RequestHeader) Method() []byte {
588 if len(h.method) == 0 {
589 return []byte(MethodGet)
590 }
591 return h.method
592}
593
594// SetMethod sets HTTP request method.
595func (h *RequestHeader) SetMethod(method string) {
596 h.method = append(h.method[:0], method...)
597}
598
599// SetMethodBytes sets HTTP request method.
600func (h *RequestHeader) SetMethodBytes(method []byte) {
601 h.method = append(h.method[:0], method...)
602}
603
604// Protocol returns HTTP protocol.
605func (h *RequestHeader) Protocol() []byte {
606 if len(h.proto) == 0 {
607 return strHTTP11
608 }
609 return h.proto
610}
611
612// SetProtocol sets HTTP request protocol.
613func (h *RequestHeader) SetProtocol(method string) {
614 h.proto = append(h.proto[:0], method...)
615 h.noHTTP11 = !bytes.Equal(h.proto, strHTTP11)
616}
617
618// SetProtocolBytes sets HTTP request protocol.
619func (h *RequestHeader) SetProtocolBytes(method []byte) {
620 h.proto = append(h.proto[:0], method...)
621 h.noHTTP11 = !bytes.Equal(h.proto, strHTTP11)
622}
623
624// RequestURI returns RequestURI from the first HTTP request line.
625func (h *RequestHeader) RequestURI() []byte {
626 requestURI := h.requestURI
627 if len(requestURI) == 0 {
628 requestURI = strSlash
629 }
630 return requestURI
631}
632
633// SetRequestURI sets RequestURI for the first HTTP request line.
634// RequestURI must be properly encoded.
635// Use URI.RequestURI for constructing proper RequestURI if unsure.
636func (h *RequestHeader) SetRequestURI(requestURI string) {
637 h.requestURI = append(h.requestURI[:0], requestURI...)
638}
639
640// SetRequestURIBytes sets RequestURI for the first HTTP request line.
641// RequestURI must be properly encoded.
642// Use URI.RequestURI for constructing proper RequestURI if unsure.
643func (h *RequestHeader) SetRequestURIBytes(requestURI []byte) {
644 h.requestURI = append(h.requestURI[:0], requestURI...)
645}
646
647// SetTrailer sets Trailer header value for chunked request
648// to indicate which headers will be sent after the body.
649//
650// Use Set to set the trailer header later.
651//
652// Trailers are only supported with chunked transfer.
653// Trailers allow the sender to include additional headers at the end of chunked messages.
654//
655// The following trailers are forbidden:
656// 1. necessary for message framing (e.g., Transfer-Encoding and Content-Length),
657// 2. routing (e.g., Host),
658// 3. request modifiers (e.g., controls and conditionals in Section 5 of [RFC7231]),
659// 4. authentication (e.g., see [RFC7235] and [RFC6265]),
660// 5. response control data (e.g., see Section 7.1 of [RFC7231]),
661// 6. determining how to process the payload (e.g., Content-Encoding, Content-Type, Content-Range, and Trailer)
662//
663// Return ErrBadTrailer if contain any forbidden trailers.
664func (h *RequestHeader) SetTrailer(trailer string) error {
665 return h.SetTrailerBytes(s2b(trailer))
666}
667
668// SetTrailerBytes sets Trailer header value for chunked request
669// to indicate which headers will be sent after the body.
670//
671// Use Set to set the trailer header later.
672//
673// Trailers are only supported with chunked transfer.
674// Trailers allow the sender to include additional headers at the end of chunked messages.
675//
676// The following trailers are forbidden:
677// 1. necessary for message framing (e.g., Transfer-Encoding and Content-Length),
678// 2. routing (e.g., Host),
679// 3. request modifiers (e.g., controls and conditionals in Section 5 of [RFC7231]),
680// 4. authentication (e.g., see [RFC7235] and [RFC6265]),
681// 5. response control data (e.g., see Section 7.1 of [RFC7231]),
682// 6. determining how to process the payload (e.g., Content-Encoding, Content-Type, Content-Range, and Trailer)
683//
684// Return ErrBadTrailer if contain any forbidden trailers.
685func (h *RequestHeader) SetTrailerBytes(trailer []byte) error {
686 h.trailer = h.trailer[:0]
687 return h.AddTrailerBytes(trailer)
688}
689
690// AddTrailer add Trailer header value for chunked request
691// to indicate which headers will be sent after the body.
692//
693// Use Set to set the trailer header later.
694//
695// Trailers are only supported with chunked transfer.
696// Trailers allow the sender to include additional headers at the end of chunked messages.
697//
698// The following trailers are forbidden:
699// 1. necessary for message framing (e.g., Transfer-Encoding and Content-Length),
700// 2. routing (e.g., Host),
701// 3. request modifiers (e.g., controls and conditionals in Section 5 of [RFC7231]),
702// 4. authentication (e.g., see [RFC7235] and [RFC6265]),
703// 5. response control data (e.g., see Section 7.1 of [RFC7231]),
704// 6. determining how to process the payload (e.g., Content-Encoding, Content-Type, Content-Range, and Trailer)
705//
706// Return ErrBadTrailer if contain any forbidden trailers.
707func (h *RequestHeader) AddTrailer(trailer string) error {
708 return h.AddTrailerBytes(s2b(trailer))
709}
710
711// AddTrailerBytes add Trailer header value for chunked request
712// to indicate which headers will be sent after the body.
713//
714// Use Set to set the trailer header later.
715//
716// Trailers are only supported with chunked transfer.
717// Trailers allow the sender to include additional headers at the end of chunked messages.
718//
719// The following trailers are forbidden:
720// 1. necessary for message framing (e.g., Transfer-Encoding and Content-Length),
721// 2. routing (e.g., Host),
722// 3. request modifiers (e.g., controls and conditionals in Section 5 of [RFC7231]),
723// 4. authentication (e.g., see [RFC7235] and [RFC6265]),
724// 5. response control data (e.g., see Section 7.1 of [RFC7231]),
725// 6. determining how to process the payload (e.g., Content-Encoding, Content-Type, Content-Range, and Trailer)
726//
727// Return ErrBadTrailer if contain any forbidden trailers.
728func (h *RequestHeader) AddTrailerBytes(trailer []byte) error {
729 var err error
730 for i := -1; i+1 < len(trailer); {
731 trailer = trailer[i+1:]
732 i = bytes.IndexByte(trailer, ',')
733 if i < 0 {
734 i = len(trailer)
735 }
736 key := trailer[:i]
737 for len(key) > 0 && key[0] == ' ' {
738 key = key[1:]
739 }
740 for len(key) > 0 && key[len(key)-1] == ' ' {
741 key = key[:len(key)-1]
742 }
743 // Forbidden by RFC 7230, section 4.1.2
744 if isBadTrailer(key) {
745 err = ErrBadTrailer
746 continue
747 }
748 h.bufKV.key = append(h.bufKV.key[:0], key...)
749 normalizeHeaderKey(h.bufKV.key, h.disableNormalizing)
750 h.trailer = appendArgBytes(h.trailer, h.bufKV.key, nil, argsNoValue)
751 }
752
753 return err
754}
755
756// IsGet returns true if request method is GET.
757func (h *RequestHeader) IsGet() bool {
758 return string(h.Method()) == MethodGet
759}
760
761// IsPost returns true if request method is POST.
762func (h *RequestHeader) IsPost() bool {
763 return string(h.Method()) == MethodPost
764}
765
766// IsPut returns true if request method is PUT.
767func (h *RequestHeader) IsPut() bool {
768 return string(h.Method()) == MethodPut
769}
770
771// IsHead returns true if request method is HEAD.
772func (h *RequestHeader) IsHead() bool {
773 return string(h.Method()) == MethodHead
774}
775
776// IsDelete returns true if request method is DELETE.
777func (h *RequestHeader) IsDelete() bool {
778 return string(h.Method()) == MethodDelete
779}
780
781// IsConnect returns true if request method is CONNECT.
782func (h *RequestHeader) IsConnect() bool {
783 return string(h.Method()) == MethodConnect
784}
785
786// IsOptions returns true if request method is OPTIONS.
787func (h *RequestHeader) IsOptions() bool {
788 return string(h.Method()) == MethodOptions
789}
790
791// IsTrace returns true if request method is TRACE.
792func (h *RequestHeader) IsTrace() bool {
793 return string(h.Method()) == MethodTrace
794}
795
796// IsPatch returns true if request method is PATCH.
797func (h *RequestHeader) IsPatch() bool {
798 return string(h.Method()) == MethodPatch
799}
800
801// IsHTTP11 returns true if the request is HTTP/1.1.
802func (h *RequestHeader) IsHTTP11() bool {
803 return !h.noHTTP11
804}
805
806// IsHTTP11 returns true if the response is HTTP/1.1.
807func (h *ResponseHeader) IsHTTP11() bool {
808 return !h.noHTTP11
809}
810
811// HasAcceptEncoding returns true if the header contains
812// the given Accept-Encoding value.
813func (h *RequestHeader) HasAcceptEncoding(acceptEncoding string) bool {
814 h.bufKV.value = append(h.bufKV.value[:0], acceptEncoding...)
815 return h.HasAcceptEncodingBytes(h.bufKV.value)
816}
817
818// HasAcceptEncodingBytes returns true if the header contains
819// the given Accept-Encoding value.
820func (h *RequestHeader) HasAcceptEncodingBytes(acceptEncoding []byte) bool {
821 ae := h.peek(strAcceptEncoding)
822 n := bytes.Index(ae, acceptEncoding)
823 if n < 0 {
824 return false
825 }
826 b := ae[n+len(acceptEncoding):]
827 if len(b) > 0 && b[0] != ',' {
828 return false
829 }
830 if n == 0 {
831 return true
832 }
833 return ae[n-1] == ' '
834}
835
836// Len returns the number of headers set,
837// i.e. the number of times f is called in VisitAll.
838func (h *ResponseHeader) Len() int {
839 n := 0
840 h.VisitAll(func(k, v []byte) { n++ })
841 return n
842}
843
844// Len returns the number of headers set,
845// i.e. the number of times f is called in VisitAll.
846func (h *RequestHeader) Len() int {
847 n := 0
848 h.VisitAll(func(k, v []byte) { n++ })
849 return n
850}
851
852// DisableNormalizing disables header names' normalization.
853//
854// By default all the header names are normalized by uppercasing
855// the first letter and all the first letters following dashes,
856// while lowercasing all the other letters.
857// Examples:
858//
859// * CONNECTION -> Connection
860// * conteNT-tYPE -> Content-Type
861// * foo-bar-baz -> Foo-Bar-Baz
862//
863// Disable header names' normalization only if know what are you doing.
864func (h *RequestHeader) DisableNormalizing() {
865 h.disableNormalizing = true
866}
867
868// EnableNormalizing enables header names' normalization.
869//
870// Header names are normalized by uppercasing the first letter and
871// all the first letters following dashes, while lowercasing all
872// the other letters.
873// Examples:
874//
875// * CONNECTION -> Connection
876// * conteNT-tYPE -> Content-Type
877// * foo-bar-baz -> Foo-Bar-Baz
878//
879// This is enabled by default unless disabled using DisableNormalizing()
880func (h *RequestHeader) EnableNormalizing() {
881 h.disableNormalizing = false
882}
883
884// DisableNormalizing disables header names' normalization.
885//
886// By default all the header names are normalized by uppercasing
887// the first letter and all the first letters following dashes,
888// while lowercasing all the other letters.
889// Examples:
890//
891// * CONNECTION -> Connection
892// * conteNT-tYPE -> Content-Type
893// * foo-bar-baz -> Foo-Bar-Baz
894//
895// Disable header names' normalization only if know what are you doing.
896func (h *ResponseHeader) DisableNormalizing() {
897 h.disableNormalizing = true
898}
899
900// EnableNormalizing enables header names' normalization.
901//
902// Header names are normalized by uppercasing the first letter and
903// all the first letters following dashes, while lowercasing all
904// the other letters.
905// Examples:
906//
907// * CONNECTION -> Connection
908// * conteNT-tYPE -> Content-Type
909// * foo-bar-baz -> Foo-Bar-Baz
910//
911// This is enabled by default unless disabled using DisableNormalizing()
912func (h *ResponseHeader) EnableNormalizing() {
913 h.disableNormalizing = false
914}
915
916// SetNoDefaultContentType allows you to control if a default Content-Type header will be set (false) or not (true).
917func (h *ResponseHeader) SetNoDefaultContentType(noDefaultContentType bool) {
918 h.noDefaultContentType = noDefaultContentType
919}
920
921// Reset clears response header.
922func (h *ResponseHeader) Reset() {
923 h.disableNormalizing = false
924 h.SetNoDefaultContentType(false)
925 h.noDefaultDate = false
926 h.resetSkipNormalize()
927}
928
929func (h *ResponseHeader) resetSkipNormalize() {
930 h.noHTTP11 = false
931 h.connectionClose = false
932
933 h.statusCode = 0
934 h.statusMessage = h.statusMessage[:0]
935 h.protocol = h.protocol[:0]
936 h.contentLength = 0
937 h.contentLengthBytes = h.contentLengthBytes[:0]
938
939 h.contentType = h.contentType[:0]
940 h.server = h.server[:0]
941
942 h.h = h.h[:0]
943 h.cookies = h.cookies[:0]
944 h.trailer = h.trailer[:0]
945}
946
947// SetNoDefaultContentType allows you to control if a default Content-Type header will be set (false) or not (true).
948func (h *RequestHeader) SetNoDefaultContentType(noDefaultContentType bool) {
949 h.noDefaultContentType = noDefaultContentType
950}
951
952// Reset clears request header.
953func (h *RequestHeader) Reset() {
954 h.disableNormalizing = false
955 h.SetNoDefaultContentType(false)
956 h.resetSkipNormalize()
957}
958
959func (h *RequestHeader) resetSkipNormalize() {
960 h.noHTTP11 = false
961 h.connectionClose = false
962
963 h.contentLength = 0
964 h.contentLengthBytes = h.contentLengthBytes[:0]
965
966 h.method = h.method[:0]
967 h.proto = h.proto[:0]
968 h.requestURI = h.requestURI[:0]
969 h.host = h.host[:0]
970 h.contentType = h.contentType[:0]
971 h.userAgent = h.userAgent[:0]
972 h.trailer = h.trailer[:0]
973
974 h.h = h.h[:0]
975 h.cookies = h.cookies[:0]
976 h.cookiesCollected = false
977
978 h.rawHeaders = h.rawHeaders[:0]
979}
980
981// CopyTo copies all the headers to dst.
982func (h *ResponseHeader) CopyTo(dst *ResponseHeader) {
983 dst.Reset()
984
985 dst.disableNormalizing = h.disableNormalizing
986 dst.noHTTP11 = h.noHTTP11
987 dst.connectionClose = h.connectionClose
988 dst.noDefaultContentType = h.noDefaultContentType
989 dst.noDefaultDate = h.noDefaultDate
990
991 dst.statusCode = h.statusCode
992 dst.statusMessage = append(dst.statusMessage, h.statusMessage...)
993 dst.protocol = append(dst.protocol, h.protocol...)
994 dst.contentLength = h.contentLength
995 dst.contentLengthBytes = append(dst.contentLengthBytes, h.contentLengthBytes...)
996 dst.contentType = append(dst.contentType, h.contentType...)
997 dst.server = append(dst.server, h.server...)
998 dst.h = copyArgs(dst.h, h.h)
999 dst.cookies = copyArgs(dst.cookies, h.cookies)
1000 dst.trailer = copyArgs(dst.trailer, h.trailer)
1001}
1002
1003// CopyTo copies all the headers to dst.
1004func (h *RequestHeader) CopyTo(dst *RequestHeader) {
1005 dst.Reset()
1006
1007 dst.disableNormalizing = h.disableNormalizing
1008 dst.noHTTP11 = h.noHTTP11
1009 dst.connectionClose = h.connectionClose
1010
1011 dst.contentLength = h.contentLength
1012 dst.contentLengthBytes = append(dst.contentLengthBytes, h.contentLengthBytes...)
1013 dst.method = append(dst.method, h.method...)
1014 dst.proto = append(dst.proto, h.proto...)
1015 dst.requestURI = append(dst.requestURI, h.requestURI...)
1016 dst.host = append(dst.host, h.host...)
1017 dst.contentType = append(dst.contentType, h.contentType...)
1018 dst.userAgent = append(dst.userAgent, h.userAgent...)
1019 dst.trailer = append(dst.trailer, h.trailer...)
1020 dst.h = copyArgs(dst.h, h.h)
1021 dst.cookies = copyArgs(dst.cookies, h.cookies)
1022 dst.cookiesCollected = h.cookiesCollected
1023 dst.rawHeaders = append(dst.rawHeaders, h.rawHeaders...)
1024}
1025
1026// VisitAll calls f for each header.
1027//
1028// f must not retain references to key and/or value after returning.
1029// Copy key and/or value contents before returning if you need retaining them.
1030func (h *ResponseHeader) VisitAll(f func(key, value []byte)) {
1031 if len(h.contentLengthBytes) > 0 {
1032 f(strContentLength, h.contentLengthBytes)
1033 }
1034 contentType := h.ContentType()
1035 if len(contentType) > 0 {
1036 f(strContentType, contentType)
1037 }
1038 server := h.Server()
1039 if len(server) > 0 {
1040 f(strServer, server)
1041 }
1042 if len(h.cookies) > 0 {
1043 visitArgs(h.cookies, func(k, v []byte) {
1044 f(strSetCookie, v)
1045 })
1046 }
1047 if len(h.trailer) > 0 {
1048 f(strTrailer, appendArgsKeyBytes(nil, h.trailer, strCommaSpace))
1049 }
1050 visitArgs(h.h, f)
1051 if h.ConnectionClose() {
1052 f(strConnection, strClose)
1053 }
1054}
1055
1056// VisitAllTrailer calls f for each response Trailer.
1057//
1058// f must not retain references to value after returning.
1059func (h *ResponseHeader) VisitAllTrailer(f func(value []byte)) {
1060 visitArgsKey(h.trailer, f)
1061}
1062
1063// VisitAllTrailer calls f for each request Trailer.
1064//
1065// f must not retain references to value after returning.
1066func (h *RequestHeader) VisitAllTrailer(f func(value []byte)) {
1067 visitArgsKey(h.trailer, f)
1068}
1069
1070// VisitAllCookie calls f for each response cookie.
1071//
1072// Cookie name is passed in key and the whole Set-Cookie header value
1073// is passed in value on each f invocation. Value may be parsed
1074// with Cookie.ParseBytes().
1075//
1076// f must not retain references to key and/or value after returning.
1077func (h *ResponseHeader) VisitAllCookie(f func(key, value []byte)) {
1078 visitArgs(h.cookies, f)
1079}
1080
1081// VisitAllCookie calls f for each request cookie.
1082//
1083// f must not retain references to key and/or value after returning.
1084func (h *RequestHeader) VisitAllCookie(f func(key, value []byte)) {
1085 h.collectCookies()
1086 visitArgs(h.cookies, f)
1087}
1088
1089// VisitAll calls f for each header.
1090//
1091// f must not retain references to key and/or value after returning.
1092// Copy key and/or value contents before returning if you need retaining them.
1093//
1094// To get the headers in order they were received use VisitAllInOrder.
1095func (h *RequestHeader) VisitAll(f func(key, value []byte)) {
1096 host := h.Host()
1097 if len(host) > 0 {
1098 f(strHost, host)
1099 }
1100 if len(h.contentLengthBytes) > 0 {
1101 f(strContentLength, h.contentLengthBytes)
1102 }
1103 contentType := h.ContentType()
1104 if len(contentType) > 0 {
1105 f(strContentType, contentType)
1106 }
1107 userAgent := h.UserAgent()
1108 if len(userAgent) > 0 {
1109 f(strUserAgent, userAgent)
1110 }
1111 if len(h.trailer) > 0 {
1112 f(strTrailer, appendArgsKeyBytes(nil, h.trailer, strCommaSpace))
1113 }
1114
1115 h.collectCookies()
1116 if len(h.cookies) > 0 {
1117 h.bufKV.value = appendRequestCookieBytes(h.bufKV.value[:0], h.cookies)
1118 f(strCookie, h.bufKV.value)
1119 }
1120 visitArgs(h.h, f)
1121 if h.ConnectionClose() {
1122 f(strConnection, strClose)
1123 }
1124}
1125
1126// VisitAllInOrder calls f for each header in the order they were received.
1127//
1128// f must not retain references to key and/or value after returning.
1129// Copy key and/or value contents before returning if you need retaining them.
1130//
1131// This function is slightly slower than VisitAll because it has to reparse the
1132// raw headers to get the order.
1133func (h *RequestHeader) VisitAllInOrder(f func(key, value []byte)) {
1134 var s headerScanner
1135 s.b = h.rawHeaders
1136 s.disableNormalizing = h.disableNormalizing
1137 for s.next() {
1138 if len(s.key) > 0 {
1139 f(s.key, s.value)
1140 }
1141 }
1142}
1143
1144// Del deletes header with the given key.
1145func (h *ResponseHeader) Del(key string) {
1146 k := getHeaderKeyBytes(&h.bufKV, key, h.disableNormalizing)
1147 h.del(k)
1148}
1149
1150// DelBytes deletes header with the given key.
1151func (h *ResponseHeader) DelBytes(key []byte) {
1152 h.bufKV.key = append(h.bufKV.key[:0], key...)
1153 normalizeHeaderKey(h.bufKV.key, h.disableNormalizing)
1154 h.del(h.bufKV.key)
1155}
1156
1157func (h *ResponseHeader) del(key []byte) {
1158 switch string(key) {
1159 case HeaderContentType:
1160 h.contentType = h.contentType[:0]
1161 case HeaderServer:
1162 h.server = h.server[:0]
1163 case HeaderSetCookie:
1164 h.cookies = h.cookies[:0]
1165 case HeaderContentLength:
1166 h.contentLength = 0
1167 h.contentLengthBytes = h.contentLengthBytes[:0]
1168 case HeaderConnection:
1169 h.connectionClose = false
1170 case HeaderTrailer:
1171 h.trailer = h.trailer[:0]
1172 }
1173 h.h = delAllArgsBytes(h.h, key)
1174}
1175
1176// Del deletes header with the given key.
1177func (h *RequestHeader) Del(key string) {
1178 k := getHeaderKeyBytes(&h.bufKV, key, h.disableNormalizing)
1179 h.del(k)
1180}
1181
1182// DelBytes deletes header with the given key.
1183func (h *RequestHeader) DelBytes(key []byte) {
1184 h.bufKV.key = append(h.bufKV.key[:0], key...)
1185 normalizeHeaderKey(h.bufKV.key, h.disableNormalizing)
1186 h.del(h.bufKV.key)
1187}
1188
1189func (h *RequestHeader) del(key []byte) {
1190 switch string(key) {
1191 case HeaderHost:
1192 h.host = h.host[:0]
1193 case HeaderContentType:
1194 h.contentType = h.contentType[:0]
1195 case HeaderUserAgent:
1196 h.userAgent = h.userAgent[:0]
1197 case HeaderCookie:
1198 h.cookies = h.cookies[:0]
1199 case HeaderContentLength:
1200 h.contentLength = 0
1201 h.contentLengthBytes = h.contentLengthBytes[:0]
1202 case HeaderConnection:
1203 h.connectionClose = false
1204 case HeaderTrailer:
1205 h.trailer = h.trailer[:0]
1206 }
1207 h.h = delAllArgsBytes(h.h, key)
1208}
1209
1210// setSpecialHeader handles special headers and return true when a header is processed.
1211func (h *ResponseHeader) setSpecialHeader(key, value []byte) bool {
1212 if len(key) == 0 {
1213 return false
1214 }
1215
1216 switch key[0] | 0x20 {
1217 case 'c':
1218 if caseInsensitiveCompare(strContentType, key) {
1219 h.SetContentTypeBytes(value)
1220 return true
1221 } else if caseInsensitiveCompare(strContentLength, key) {
1222 if contentLength, err := parseContentLength(value); err == nil {
1223 h.contentLength = contentLength
1224 h.contentLengthBytes = append(h.contentLengthBytes[:0], value...)
1225 }
1226 return true
1227 } else if caseInsensitiveCompare(strConnection, key) {
1228 if bytes.Equal(strClose, value) {
1229 h.SetConnectionClose()
1230 } else {
1231 h.ResetConnectionClose()
1232 h.h = setArgBytes(h.h, key, value, argsHasValue)
1233 }
1234 return true
1235 }
1236 case 's':
1237 if caseInsensitiveCompare(strServer, key) {
1238 h.SetServerBytes(value)
1239 return true
1240 } else if caseInsensitiveCompare(strSetCookie, key) {
1241 var kv *argsKV
1242 h.cookies, kv = allocArg(h.cookies)
1243 kv.key = getCookieKey(kv.key, value)
1244 kv.value = append(kv.value[:0], value...)
1245 return true
1246 }
1247 case 't':
1248 if caseInsensitiveCompare(strTransferEncoding, key) {
1249 // Transfer-Encoding is managed automatically.
1250 return true
1251 } else if caseInsensitiveCompare(strTrailer, key) {
1252 _ = h.SetTrailerBytes(value)
1253 return true
1254 }
1255 case 'd':
1256 if caseInsensitiveCompare(strDate, key) {
1257 // Date is managed automatically.
1258 return true
1259 }
1260 }
1261
1262 return false
1263}
1264
1265// setSpecialHeader handles special headers and return true when a header is processed.
1266func (h *RequestHeader) setSpecialHeader(key, value []byte) bool {
1267 if len(key) == 0 {
1268 return false
1269 }
1270
1271 switch key[0] | 0x20 {
1272 case 'c':
1273 if caseInsensitiveCompare(strContentType, key) {
1274 h.SetContentTypeBytes(value)
1275 return true
1276 } else if caseInsensitiveCompare(strContentLength, key) {
1277 if contentLength, err := parseContentLength(value); err == nil {
1278 h.contentLength = contentLength
1279 h.contentLengthBytes = append(h.contentLengthBytes[:0], value...)
1280 }
1281 return true
1282 } else if caseInsensitiveCompare(strConnection, key) {
1283 if bytes.Equal(strClose, value) {
1284 h.SetConnectionClose()
1285 } else {
1286 h.ResetConnectionClose()
1287 h.h = setArgBytes(h.h, key, value, argsHasValue)
1288 }
1289 return true
1290 } else if caseInsensitiveCompare(strCookie, key) {
1291 h.collectCookies()
1292 h.cookies = parseRequestCookies(h.cookies, value)
1293 return true
1294 }
1295 case 't':
1296 if caseInsensitiveCompare(strTransferEncoding, key) {
1297 // Transfer-Encoding is managed automatically.
1298 return true
1299 } else if caseInsensitiveCompare(strTrailer, key) {
1300 _ = h.SetTrailerBytes(value)
1301 return true
1302 }
1303 case 'h':
1304 if caseInsensitiveCompare(strHost, key) {
1305 h.SetHostBytes(value)
1306 return true
1307 }
1308 case 'u':
1309 if caseInsensitiveCompare(strUserAgent, key) {
1310 h.SetUserAgentBytes(value)
1311 return true
1312 }
1313 }
1314
1315 return false
1316}
1317
1318// Add adds the given 'key: value' header.
1319//
1320// Multiple headers with the same key may be added with this function.
1321// Use Set for setting a single header for the given key.
1322//
1323// the Content-Type, Content-Length, Connection, Server, Set-Cookie,
1324// Transfer-Encoding and Date headers can only be set once and will
1325// overwrite the previous value.
1326//
1327// If the header is set as a Trailer (forbidden trailers will not be set, see AddTrailer for more details),
1328// it will be sent after the chunked response body.
1329func (h *ResponseHeader) Add(key, value string) {
1330 h.AddBytesKV(s2b(key), s2b(value))
1331}
1332
1333// AddBytesK adds the given 'key: value' header.
1334//
1335// Multiple headers with the same key may be added with this function.
1336// Use SetBytesK for setting a single header for the given key.
1337//
1338// the Content-Type, Content-Length, Connection, Server, Set-Cookie,
1339// Transfer-Encoding and Date headers can only be set once and will
1340// overwrite the previous value.
1341//
1342// If the header is set as a Trailer (forbidden trailers will not be set, see AddTrailer for more details),
1343// it will be sent after the chunked response body.
1344func (h *ResponseHeader) AddBytesK(key []byte, value string) {
1345 h.AddBytesKV(key, s2b(value))
1346}
1347
1348// AddBytesV adds the given 'key: value' header.
1349//
1350// Multiple headers with the same key may be added with this function.
1351// Use SetBytesV for setting a single header for the given key.
1352//
1353// the Content-Type, Content-Length, Connection, Server, Set-Cookie,
1354// Transfer-Encoding and Date headers can only be set once and will
1355// overwrite the previous value.
1356//
1357// If the header is set as a Trailer (forbidden trailers will not be set, see AddTrailer for more details),
1358// it will be sent after the chunked response body.
1359func (h *ResponseHeader) AddBytesV(key string, value []byte) {
1360 h.AddBytesKV(s2b(key), value)
1361}
1362
1363// AddBytesKV adds the given 'key: value' header.
1364//
1365// Multiple headers with the same key may be added with this function.
1366// Use SetBytesKV for setting a single header for the given key.
1367//
1368// the Content-Type, Content-Length, Connection, Server, Set-Cookie,
1369// Transfer-Encoding and Date headers can only be set once and will
1370// overwrite the previous value.
1371//
1372// If the header is set as a Trailer (forbidden trailers will not be set, see AddTrailer for more details),
1373// it will be sent after the chunked response body.
1374func (h *ResponseHeader) AddBytesKV(key, value []byte) {
1375 if h.setSpecialHeader(key, value) {
1376 return
1377 }
1378
1379 k := getHeaderKeyBytes(&h.bufKV, b2s(key), h.disableNormalizing)
1380 h.h = appendArgBytes(h.h, k, value, argsHasValue)
1381}
1382
1383// Set sets the given 'key: value' header.
1384//
1385// If the header is set as a Trailer (forbidden trailers will not be set, see SetTrailer for more details),
1386// it will be sent after the chunked response body.
1387//
1388// Use Add for setting multiple header values under the same key.
1389func (h *ResponseHeader) Set(key, value string) {
1390 initHeaderKV(&h.bufKV, key, value, h.disableNormalizing)
1391 h.SetCanonical(h.bufKV.key, h.bufKV.value)
1392}
1393
1394// SetBytesK sets the given 'key: value' header.
1395//
1396// If the header is set as a Trailer (forbidden trailers will not be set, see SetTrailer for more details),
1397// it will be sent after the chunked response body.
1398//
1399// Use AddBytesK for setting multiple header values under the same key.
1400func (h *ResponseHeader) SetBytesK(key []byte, value string) {
1401 h.bufKV.value = append(h.bufKV.value[:0], value...)
1402 h.SetBytesKV(key, h.bufKV.value)
1403}
1404
1405// SetBytesV sets the given 'key: value' header.
1406//
1407// If the header is set as a Trailer (forbidden trailers will not be set, see SetTrailer for more details),
1408// it will be sent after the chunked response body.
1409//
1410// Use AddBytesV for setting multiple header values under the same key.
1411func (h *ResponseHeader) SetBytesV(key string, value []byte) {
1412 k := getHeaderKeyBytes(&h.bufKV, key, h.disableNormalizing)
1413 h.SetCanonical(k, value)
1414}
1415
1416// SetBytesKV sets the given 'key: value' header.
1417//
1418// If the header is set as a Trailer (forbidden trailers will not be set, see SetTrailer for more details),
1419// it will be sent after the chunked response body.
1420//
1421// Use AddBytesKV for setting multiple header values under the same key.
1422func (h *ResponseHeader) SetBytesKV(key, value []byte) {
1423 h.bufKV.key = append(h.bufKV.key[:0], key...)
1424 normalizeHeaderKey(h.bufKV.key, h.disableNormalizing)
1425 h.SetCanonical(h.bufKV.key, value)
1426}
1427
1428// SetCanonical sets the given 'key: value' header assuming that
1429// key is in canonical form.
1430//
1431// If the header is set as a Trailer (forbidden trailers will not be set, see SetTrailer for more details),
1432// it will be sent after the chunked response body.
1433func (h *ResponseHeader) SetCanonical(key, value []byte) {
1434 if h.setSpecialHeader(key, value) {
1435 return
1436 }
1437
1438 h.h = setArgBytes(h.h, key, value, argsHasValue)
1439}
1440
1441// SetCookie sets the given response cookie.
1442//
1443// It is save re-using the cookie after the function returns.
1444func (h *ResponseHeader) SetCookie(cookie *Cookie) {
1445 h.cookies = setArgBytes(h.cookies, cookie.Key(), cookie.Cookie(), argsHasValue)
1446}
1447
1448// SetCookie sets 'key: value' cookies.
1449func (h *RequestHeader) SetCookie(key, value string) {
1450 h.collectCookies()
1451 h.cookies = setArg(h.cookies, key, value, argsHasValue)
1452}
1453
1454// SetCookieBytesK sets 'key: value' cookies.
1455func (h *RequestHeader) SetCookieBytesK(key []byte, value string) {
1456 h.SetCookie(b2s(key), value)
1457}
1458
1459// SetCookieBytesKV sets 'key: value' cookies.
1460func (h *RequestHeader) SetCookieBytesKV(key, value []byte) {
1461 h.SetCookie(b2s(key), b2s(value))
1462}
1463
1464// DelClientCookie instructs the client to remove the given cookie.
1465// This doesn't work for a cookie with specific domain or path,
1466// you should delete it manually like:
1467//
1468// c := AcquireCookie()
1469// c.SetKey(key)
1470// c.SetDomain("example.com")
1471// c.SetPath("/path")
1472// c.SetExpire(CookieExpireDelete)
1473// h.SetCookie(c)
1474// ReleaseCookie(c)
1475//
1476// Use DelCookie if you want just removing the cookie from response header.
1477func (h *ResponseHeader) DelClientCookie(key string) {
1478 h.DelCookie(key)
1479
1480 c := AcquireCookie()
1481 c.SetKey(key)
1482 c.SetExpire(CookieExpireDelete)
1483 h.SetCookie(c)
1484 ReleaseCookie(c)
1485}
1486
1487// DelClientCookieBytes instructs the client to remove the given cookie.
1488// This doesn't work for a cookie with specific domain or path,
1489// you should delete it manually like:
1490//
1491// c := AcquireCookie()
1492// c.SetKey(key)
1493// c.SetDomain("example.com")
1494// c.SetPath("/path")
1495// c.SetExpire(CookieExpireDelete)
1496// h.SetCookie(c)
1497// ReleaseCookie(c)
1498//
1499// Use DelCookieBytes if you want just removing the cookie from response header.
1500func (h *ResponseHeader) DelClientCookieBytes(key []byte) {
1501 h.DelClientCookie(b2s(key))
1502}
1503
1504// DelCookie removes cookie under the given key from response header.
1505//
1506// Note that DelCookie doesn't remove the cookie from the client.
1507// Use DelClientCookie instead.
1508func (h *ResponseHeader) DelCookie(key string) {
1509 h.cookies = delAllArgs(h.cookies, key)
1510}
1511
1512// DelCookieBytes removes cookie under the given key from response header.
1513//
1514// Note that DelCookieBytes doesn't remove the cookie from the client.
1515// Use DelClientCookieBytes instead.
1516func (h *ResponseHeader) DelCookieBytes(key []byte) {
1517 h.DelCookie(b2s(key))
1518}
1519
1520// DelCookie removes cookie under the given key.
1521func (h *RequestHeader) DelCookie(key string) {
1522 h.collectCookies()
1523 h.cookies = delAllArgs(h.cookies, key)
1524}
1525
1526// DelCookieBytes removes cookie under the given key.
1527func (h *RequestHeader) DelCookieBytes(key []byte) {
1528 h.DelCookie(b2s(key))
1529}
1530
1531// DelAllCookies removes all the cookies from response headers.
1532func (h *ResponseHeader) DelAllCookies() {
1533 h.cookies = h.cookies[:0]
1534}
1535
1536// DelAllCookies removes all the cookies from request headers.
1537func (h *RequestHeader) DelAllCookies() {
1538 h.collectCookies()
1539 h.cookies = h.cookies[:0]
1540}
1541
1542// Add adds the given 'key: value' header.
1543//
1544// Multiple headers with the same key may be added with this function.
1545// Use Set for setting a single header for the given key.
1546//
1547// If the header is set as a Trailer (forbidden trailers will not be set, see AddTrailer for more details),
1548// it will be sent after the chunked request body.
1549func (h *RequestHeader) Add(key, value string) {
1550 h.AddBytesKV(s2b(key), s2b(value))
1551}
1552
1553// AddBytesK adds the given 'key: value' header.
1554//
1555// Multiple headers with the same key may be added with this function.
1556// Use SetBytesK for setting a single header for the given key.
1557//
1558// If the header is set as a Trailer (forbidden trailers will not be set, see AddTrailer for more details),
1559// it will be sent after the chunked request body.
1560func (h *RequestHeader) AddBytesK(key []byte, value string) {
1561 h.AddBytesKV(key, s2b(value))
1562}
1563
1564// AddBytesV adds the given 'key: value' header.
1565//
1566// Multiple headers with the same key may be added with this function.
1567// Use SetBytesV for setting a single header for the given key.
1568//
1569// If the header is set as a Trailer (forbidden trailers will not be set, see AddTrailer for more details),
1570// it will be sent after the chunked request body.
1571func (h *RequestHeader) AddBytesV(key string, value []byte) {
1572 h.AddBytesKV(s2b(key), value)
1573}
1574
1575// AddBytesKV adds the given 'key: value' header.
1576//
1577// Multiple headers with the same key may be added with this function.
1578// Use SetBytesKV for setting a single header for the given key.
1579//
1580// the Content-Type, Content-Length, Connection, Cookie,
1581// Transfer-Encoding, Host and User-Agent headers can only be set once
1582// and will overwrite the previous value.
1583//
1584// If the header is set as a Trailer (forbidden trailers will not be set, see AddTrailer for more details),
1585// it will be sent after the chunked request body.
1586func (h *RequestHeader) AddBytesKV(key, value []byte) {
1587 if h.setSpecialHeader(key, value) {
1588 return
1589 }
1590
1591 k := getHeaderKeyBytes(&h.bufKV, b2s(key), h.disableNormalizing)
1592 h.h = appendArgBytes(h.h, k, value, argsHasValue)
1593}
1594
1595// Set sets the given 'key: value' header.
1596//
1597// If the header is set as a Trailer (forbidden trailers will not be set, see SetTrailer for more details),
1598// it will be sent after the chunked request body.
1599//
1600// Use Add for setting multiple header values under the same key.
1601func (h *RequestHeader) Set(key, value string) {
1602 initHeaderKV(&h.bufKV, key, value, h.disableNormalizing)
1603 h.SetCanonical(h.bufKV.key, h.bufKV.value)
1604}
1605
1606// SetBytesK sets the given 'key: value' header.
1607//
1608// If the header is set as a Trailer (forbidden trailers will not be set, see SetTrailer for more details),
1609// it will be sent after the chunked request body.
1610//
1611// Use AddBytesK for setting multiple header values under the same key.
1612func (h *RequestHeader) SetBytesK(key []byte, value string) {
1613 h.bufKV.value = append(h.bufKV.value[:0], value...)
1614 h.SetBytesKV(key, h.bufKV.value)
1615}
1616
1617// SetBytesV sets the given 'key: value' header.
1618//
1619// If the header is set as a Trailer (forbidden trailers will not be set, see SetTrailer for more details),
1620// it will be sent after the chunked request body.
1621//
1622// Use AddBytesV for setting multiple header values under the same key.
1623func (h *RequestHeader) SetBytesV(key string, value []byte) {
1624 k := getHeaderKeyBytes(&h.bufKV, key, h.disableNormalizing)
1625 h.SetCanonical(k, value)
1626}
1627
1628// SetBytesKV sets the given 'key: value' header.
1629//
1630// If the header is set as a Trailer (forbidden trailers will not be set, see SetTrailer for more details),
1631// it will be sent after the chunked request body.
1632//
1633// Use AddBytesKV for setting multiple header values under the same key.
1634func (h *RequestHeader) SetBytesKV(key, value []byte) {
1635 h.bufKV.key = append(h.bufKV.key[:0], key...)
1636 normalizeHeaderKey(h.bufKV.key, h.disableNormalizing)
1637 h.SetCanonical(h.bufKV.key, value)
1638}
1639
1640// SetCanonical sets the given 'key: value' header assuming that
1641// key is in canonical form.
1642//
1643// If the header is set as a Trailer (forbidden trailers will not be set, see SetTrailer for more details),
1644// it will be sent after the chunked request body.
1645func (h *RequestHeader) SetCanonical(key, value []byte) {
1646 if h.setSpecialHeader(key, value) {
1647 return
1648 }
1649
1650 h.h = setArgBytes(h.h, key, value, argsHasValue)
1651}
1652
1653// Peek returns header value for the given key.
1654//
1655// The returned value is valid until the response is released,
1656// either though ReleaseResponse or your request handler returning.
1657// Do not store references to the returned value. Make copies instead.
1658func (h *ResponseHeader) Peek(key string) []byte {
1659 k := getHeaderKeyBytes(&h.bufKV, key, h.disableNormalizing)
1660 return h.peek(k)
1661}
1662
1663// PeekBytes returns header value for the given key.
1664//
1665// The returned value is valid until the response is released,
1666// either though ReleaseResponse or your request handler returning.
1667// Do not store references to returned value. Make copies instead.
1668func (h *ResponseHeader) PeekBytes(key []byte) []byte {
1669 h.bufKV.key = append(h.bufKV.key[:0], key...)
1670 normalizeHeaderKey(h.bufKV.key, h.disableNormalizing)
1671 return h.peek(h.bufKV.key)
1672}
1673
1674// Peek returns header value for the given key.
1675//
1676// The returned value is valid until the request is released,
1677// either though ReleaseRequest or your request handler returning.
1678// Do not store references to returned value. Make copies instead.
1679func (h *RequestHeader) Peek(key string) []byte {
1680 k := getHeaderKeyBytes(&h.bufKV, key, h.disableNormalizing)
1681 return h.peek(k)
1682}
1683
1684// PeekBytes returns header value for the given key.
1685//
1686// The returned value is valid until the request is released,
1687// either though ReleaseRequest or your request handler returning.
1688// Do not store references to returned value. Make copies instead.
1689func (h *RequestHeader) PeekBytes(key []byte) []byte {
1690 h.bufKV.key = append(h.bufKV.key[:0], key...)
1691 normalizeHeaderKey(h.bufKV.key, h.disableNormalizing)
1692 return h.peek(h.bufKV.key)
1693}
1694
1695func (h *ResponseHeader) peek(key []byte) []byte {
1696 switch string(key) {
1697 case HeaderContentType:
1698 return h.ContentType()
1699 case HeaderServer:
1700 return h.Server()
1701 case HeaderConnection:
1702 if h.ConnectionClose() {
1703 return strClose
1704 }
1705 return peekArgBytes(h.h, key)
1706 case HeaderContentLength:
1707 return h.contentLengthBytes
1708 case HeaderSetCookie:
1709 return appendResponseCookieBytes(nil, h.cookies)
1710 case HeaderTrailer:
1711 return appendArgsKeyBytes(nil, h.trailer, strCommaSpace)
1712 default:
1713 return peekArgBytes(h.h, key)
1714 }
1715}
1716
1717func (h *RequestHeader) peek(key []byte) []byte {
1718 switch string(key) {
1719 case HeaderHost:
1720 return h.Host()
1721 case HeaderContentType:
1722 return h.ContentType()
1723 case HeaderUserAgent:
1724 return h.UserAgent()
1725 case HeaderConnection:
1726 if h.ConnectionClose() {
1727 return strClose
1728 }
1729 return peekArgBytes(h.h, key)
1730 case HeaderContentLength:
1731 return h.contentLengthBytes
1732 case HeaderCookie:
1733 if h.cookiesCollected {
1734 return appendRequestCookieBytes(nil, h.cookies)
1735 }
1736 return peekArgBytes(h.h, key)
1737 case HeaderTrailer:
1738 return appendArgsKeyBytes(nil, h.trailer, strCommaSpace)
1739 default:
1740 return peekArgBytes(h.h, key)
1741 }
1742}
1743
1744// Cookie returns cookie for the given key.
1745func (h *RequestHeader) Cookie(key string) []byte {
1746 h.collectCookies()
1747 return peekArgStr(h.cookies, key)
1748}
1749
1750// CookieBytes returns cookie for the given key.
1751func (h *RequestHeader) CookieBytes(key []byte) []byte {
1752 h.collectCookies()
1753 return peekArgBytes(h.cookies, key)
1754}
1755
1756// Cookie fills cookie for the given cookie.Key.
1757//
1758// Returns false if cookie with the given cookie.Key is missing.
1759func (h *ResponseHeader) Cookie(cookie *Cookie) bool {
1760 v := peekArgBytes(h.cookies, cookie.Key())
1761 if v == nil {
1762 return false
1763 }
1764 cookie.ParseBytes(v) //nolint:errcheck
1765 return true
1766}
1767
1768// Read reads response header from r.
1769//
1770// io.EOF is returned if r is closed before reading the first header byte.
1771func (h *ResponseHeader) Read(r *bufio.Reader) error {
1772 n := 1
1773 for {
1774 err := h.tryRead(r, n)
1775 if err == nil {
1776 return nil
1777 }
1778 if err != errNeedMore {
1779 h.resetSkipNormalize()
1780 return err
1781 }
1782 n = r.Buffered() + 1
1783 }
1784}
1785
1786func (h *ResponseHeader) tryRead(r *bufio.Reader, n int) error {
1787 h.resetSkipNormalize()
1788 b, err := r.Peek(n)
1789 if len(b) == 0 {
1790 // Return ErrTimeout on any timeout.
1791 if x, ok := err.(interface{ Timeout() bool }); ok && x.Timeout() {
1792 return ErrTimeout
1793 }
1794 // treat all other errors on the first byte read as EOF
1795 if n == 1 || err == io.EOF {
1796 return io.EOF
1797 }
1798
1799 // This is for go 1.6 bug. See https://github.com/golang/go/issues/14121 .
1800 if err == bufio.ErrBufferFull {
1801 if h.secureErrorLogMessage {
1802 return &ErrSmallBuffer{
1803 error: fmt.Errorf("error when reading response headers"),
1804 }
1805 }
1806 return &ErrSmallBuffer{
1807 error: fmt.Errorf("error when reading response headers: %w", errSmallBuffer),
1808 }
1809 }
1810
1811 return fmt.Errorf("error when reading response headers: %w", err)
1812 }
1813 b = mustPeekBuffered(r)
1814 headersLen, errParse := h.parse(b)
1815 if errParse != nil {
1816 return headerError("response", err, errParse, b, h.secureErrorLogMessage)
1817 }
1818 mustDiscard(r, headersLen)
1819 return nil
1820}
1821
1822// ReadTrailer reads response trailer header from r.
1823//
1824// io.EOF is returned if r is closed before reading the first byte.
1825func (h *ResponseHeader) ReadTrailer(r *bufio.Reader) error {
1826 n := 1
1827 for {
1828 err := h.tryReadTrailer(r, n)
1829 if err == nil {
1830 return nil
1831 }
1832 if err != errNeedMore {
1833 return err
1834 }
1835 n = r.Buffered() + 1
1836 }
1837}
1838
1839func (h *ResponseHeader) tryReadTrailer(r *bufio.Reader, n int) error {
1840 b, err := r.Peek(n)
1841 if len(b) == 0 {
1842 // Return ErrTimeout on any timeout.
1843 if x, ok := err.(interface{ Timeout() bool }); ok && x.Timeout() {
1844 return ErrTimeout
1845 }
1846
1847 if n == 1 || err == io.EOF {
1848 return io.EOF
1849 }
1850
1851 // This is for go 1.6 bug. See https://github.com/golang/go/issues/14121 .
1852 if err == bufio.ErrBufferFull {
1853 if h.secureErrorLogMessage {
1854 return &ErrSmallBuffer{
1855 error: fmt.Errorf("error when reading response trailer"),
1856 }
1857 }
1858 return &ErrSmallBuffer{
1859 error: fmt.Errorf("error when reading response trailer: %w", errSmallBuffer),
1860 }
1861 }
1862
1863 return fmt.Errorf("error when reading response trailer: %w", err)
1864 }
1865 b = mustPeekBuffered(r)
1866 headersLen, errParse := h.parseTrailer(b)
1867 if errParse != nil {
1868 if err == io.EOF {
1869 return err
1870 }
1871 return headerError("response", err, errParse, b, h.secureErrorLogMessage)
1872 }
1873 mustDiscard(r, headersLen)
1874 return nil
1875}
1876
1877func headerError(typ string, err, errParse error, b []byte, secureErrorLogMessage bool) error {
1878 if errParse != errNeedMore {
1879 return headerErrorMsg(typ, errParse, b, secureErrorLogMessage)
1880 }
1881 if err == nil {
1882 return errNeedMore
1883 }
1884
1885 // Buggy servers may leave trailing CRLFs after http body.
1886 // Treat this case as EOF.
1887 if isOnlyCRLF(b) {
1888 return io.EOF
1889 }
1890
1891 if err != bufio.ErrBufferFull {
1892 return headerErrorMsg(typ, err, b, secureErrorLogMessage)
1893 }
1894 return &ErrSmallBuffer{
1895 error: headerErrorMsg(typ, errSmallBuffer, b, secureErrorLogMessage),
1896 }
1897}
1898
1899func headerErrorMsg(typ string, err error, b []byte, secureErrorLogMessage bool) error {
1900 if secureErrorLogMessage {
1901 return fmt.Errorf("error when reading %s headers: %w. Buffer size=%d", typ, err, len(b))
1902 }
1903 return fmt.Errorf("error when reading %s headers: %w. Buffer size=%d, contents: %s", typ, err, len(b), bufferSnippet(b))
1904}
1905
1906// Read reads request header from r.
1907//
1908// io.EOF is returned if r is closed before reading the first header byte.
1909func (h *RequestHeader) Read(r *bufio.Reader) error {
1910 return h.readLoop(r, true)
1911}
1912
1913// readLoop reads request header from r optionally loops until it has enough data.
1914//
1915// io.EOF is returned if r is closed before reading the first header byte.
1916func (h *RequestHeader) readLoop(r *bufio.Reader, waitForMore bool) error {
1917 n := 1
1918 for {
1919 err := h.tryRead(r, n)
1920 if err == nil {
1921 return nil
1922 }
1923 if !waitForMore || err != errNeedMore {
1924 h.resetSkipNormalize()
1925 return err
1926 }
1927 n = r.Buffered() + 1
1928 }
1929}
1930
1931// ReadTrailer reads request trailer header from r.
1932//
1933// io.EOF is returned if r is closed before reading the first byte.
1934func (h *RequestHeader) ReadTrailer(r *bufio.Reader) error {
1935 n := 1
1936 for {
1937 err := h.tryReadTrailer(r, n)
1938 if err == nil {
1939 return nil
1940 }
1941 if err != errNeedMore {
1942 return err
1943 }
1944 n = r.Buffered() + 1
1945 }
1946}
1947
1948func (h *RequestHeader) tryReadTrailer(r *bufio.Reader, n int) error {
1949 b, err := r.Peek(n)
1950 if len(b) == 0 {
1951 // Return ErrTimeout on any timeout.
1952 if x, ok := err.(interface{ Timeout() bool }); ok && x.Timeout() {
1953 return ErrTimeout
1954 }
1955
1956 if n == 1 || err == io.EOF {
1957 return io.EOF
1958 }
1959
1960 // This is for go 1.6 bug. See https://github.com/golang/go/issues/14121 .
1961 if err == bufio.ErrBufferFull {
1962 if h.secureErrorLogMessage {
1963 return &ErrSmallBuffer{
1964 error: fmt.Errorf("error when reading request trailer"),
1965 }
1966 }
1967 return &ErrSmallBuffer{
1968 error: fmt.Errorf("error when reading request trailer: %w", errSmallBuffer),
1969 }
1970 }
1971
1972 return fmt.Errorf("error when reading request trailer: %w", err)
1973 }
1974 b = mustPeekBuffered(r)
1975 headersLen, errParse := h.parseTrailer(b)
1976 if errParse != nil {
1977 if err == io.EOF {
1978 return err
1979 }
1980 return headerError("request", err, errParse, b, h.secureErrorLogMessage)
1981 }
1982 mustDiscard(r, headersLen)
1983 return nil
1984}
1985
1986func (h *RequestHeader) tryRead(r *bufio.Reader, n int) error {
1987 h.resetSkipNormalize()
1988 b, err := r.Peek(n)
1989 if len(b) == 0 {
1990 if err == io.EOF {
1991 return err
1992 }
1993
1994 if err == nil {
1995 panic("bufio.Reader.Peek() returned nil, nil")
1996 }
1997
1998 // This is for go 1.6 bug. See https://github.com/golang/go/issues/14121 .
1999 if err == bufio.ErrBufferFull {
2000 return &ErrSmallBuffer{
2001 error: fmt.Errorf("error when reading request headers: %w (n=%d, r.Buffered()=%d)", errSmallBuffer, n, r.Buffered()),
2002 }
2003 }
2004
2005 // n == 1 on the first read for the request.
2006 if n == 1 {
2007 // We didn't read a single byte.
2008 return ErrNothingRead{err}
2009 }
2010
2011 return fmt.Errorf("error when reading request headers: %w", err)
2012 }
2013 b = mustPeekBuffered(r)
2014 headersLen, errParse := h.parse(b)
2015 if errParse != nil {
2016 return headerError("request", err, errParse, b, h.secureErrorLogMessage)
2017 }
2018 mustDiscard(r, headersLen)
2019 return nil
2020}
2021
2022func bufferSnippet(b []byte) string {
2023 n := len(b)
2024 start := 200
2025 end := n - start
2026 if start >= end {
2027 start = n
2028 end = n
2029 }
2030 bStart, bEnd := b[:start], b[end:]
2031 if len(bEnd) == 0 {
2032 return fmt.Sprintf("%q", b)
2033 }
2034 return fmt.Sprintf("%q...%q", bStart, bEnd)
2035}
2036
2037func isOnlyCRLF(b []byte) bool {
2038 for _, ch := range b {
2039 if ch != rChar && ch != nChar {
2040 return false
2041 }
2042 }
2043 return true
2044}
2045
2046func updateServerDate() {
2047 refreshServerDate()
2048 go func() {
2049 for {
2050 time.Sleep(time.Second)
2051 refreshServerDate()
2052 }
2053 }()
2054}
2055
2056var (
2057 serverDate atomic.Value
2058 serverDateOnce sync.Once // serverDateOnce.Do(updateServerDate)
2059)
2060
2061func refreshServerDate() {
2062 b := AppendHTTPDate(nil, time.Now())
2063 serverDate.Store(b)
2064}
2065
2066// Write writes response header to w.
2067func (h *ResponseHeader) Write(w *bufio.Writer) error {
2068 _, err := w.Write(h.Header())
2069 return err
2070}
2071
2072// WriteTo writes response header to w.
2073//
2074// WriteTo implements io.WriterTo interface.
2075func (h *ResponseHeader) WriteTo(w io.Writer) (int64, error) {
2076 n, err := w.Write(h.Header())
2077 return int64(n), err
2078}
2079
2080// Header returns response header representation.
2081//
2082// Headers that set as Trailer will not represent. Use TrailerHeader for trailers.
2083//
2084// The returned value is valid until the request is released,
2085// either though ReleaseRequest or your request handler returning.
2086// Do not store references to returned value. Make copies instead.
2087func (h *ResponseHeader) Header() []byte {
2088 h.bufKV.value = h.AppendBytes(h.bufKV.value[:0])
2089 return h.bufKV.value
2090}
2091
2092// writeTrailer writes response trailer to w.
2093func (h *ResponseHeader) writeTrailer(w *bufio.Writer) error {
2094 _, err := w.Write(h.TrailerHeader())
2095 return err
2096}
2097
2098// TrailerHeader returns response trailer header representation.
2099//
2100// Trailers will only be received with chunked transfer.
2101//
2102// The returned value is valid until the request is released,
2103// either though ReleaseRequest or your request handler returning.
2104// Do not store references to returned value. Make copies instead.
2105func (h *ResponseHeader) TrailerHeader() []byte {
2106 h.bufKV.value = h.bufKV.value[:0]
2107 for _, t := range h.trailer {
2108 value := h.peek(t.key)
2109 h.bufKV.value = appendHeaderLine(h.bufKV.value, t.key, value)
2110 }
2111 h.bufKV.value = append(h.bufKV.value, strCRLF...)
2112 return h.bufKV.value
2113}
2114
2115// String returns response header representation.
2116func (h *ResponseHeader) String() string {
2117 return string(h.Header())
2118}
2119
2120// appendStatusLine appends the response status line to dst and returns
2121// the extended dst.
2122func (h *ResponseHeader) appendStatusLine(dst []byte) []byte {
2123 statusCode := h.StatusCode()
2124 if statusCode < 0 {
2125 statusCode = StatusOK
2126 }
2127 return formatStatusLine(dst, h.Protocol(), statusCode, h.StatusMessage())
2128}
2129
2130// AppendBytes appends response header representation to dst and returns
2131// the extended dst.
2132func (h *ResponseHeader) AppendBytes(dst []byte) []byte {
2133 dst = h.appendStatusLine(dst[:0])
2134
2135 server := h.Server()
2136 if len(server) != 0 {
2137 dst = appendHeaderLine(dst, strServer, server)
2138 }
2139
2140 if !h.noDefaultDate {
2141 serverDateOnce.Do(updateServerDate)
2142 dst = appendHeaderLine(dst, strDate, serverDate.Load().([]byte))
2143 }
2144
2145 // Append Content-Type only for non-zero responses
2146 // or if it is explicitly set.
2147 // See https://github.com/valyala/fasthttp/issues/28 .
2148 if h.ContentLength() != 0 || len(h.contentType) > 0 {
2149 contentType := h.ContentType()
2150 if len(contentType) > 0 {
2151 dst = appendHeaderLine(dst, strContentType, contentType)
2152 }
2153 }
2154
2155 if len(h.contentLengthBytes) > 0 {
2156 dst = appendHeaderLine(dst, strContentLength, h.contentLengthBytes)
2157 }
2158
2159 for i, n := 0, len(h.h); i < n; i++ {
2160 kv := &h.h[i]
2161
2162 // Exclude trailer from header
2163 exclude := false
2164 for _, t := range h.trailer {
2165 if bytes.Equal(kv.key, t.key) {
2166 exclude = true
2167 break
2168 }
2169 }
2170 if !exclude && (h.noDefaultDate || !bytes.Equal(kv.key, strDate)) {
2171 dst = appendHeaderLine(dst, kv.key, kv.value)
2172 }
2173 }
2174
2175 if len(h.trailer) > 0 {
2176 dst = appendHeaderLine(dst, strTrailer, appendArgsKeyBytes(nil, h.trailer, strCommaSpace))
2177 }
2178
2179 n := len(h.cookies)
2180 if n > 0 {
2181 for i := 0; i < n; i++ {
2182 kv := &h.cookies[i]
2183 dst = appendHeaderLine(dst, strSetCookie, kv.value)
2184 }
2185 }
2186
2187 if h.ConnectionClose() {
2188 dst = appendHeaderLine(dst, strConnection, strClose)
2189 }
2190
2191 return append(dst, strCRLF...)
2192}
2193
2194// Write writes request header to w.
2195func (h *RequestHeader) Write(w *bufio.Writer) error {
2196 _, err := w.Write(h.Header())
2197 return err
2198}
2199
2200// WriteTo writes request header to w.
2201//
2202// WriteTo implements io.WriterTo interface.
2203func (h *RequestHeader) WriteTo(w io.Writer) (int64, error) {
2204 n, err := w.Write(h.Header())
2205 return int64(n), err
2206}
2207
2208// Header returns request header representation.
2209//
2210// Headers that set as Trailer will not represent. Use TrailerHeader for trailers.
2211//
2212// The returned value is valid until the request is released,
2213// either though ReleaseRequest or your request handler returning.
2214// Do not store references to returned value. Make copies instead.
2215func (h *RequestHeader) Header() []byte {
2216 h.bufKV.value = h.AppendBytes(h.bufKV.value[:0])
2217 return h.bufKV.value
2218}
2219
2220// writeTrailer writes request trailer to w.
2221func (h *RequestHeader) writeTrailer(w *bufio.Writer) error {
2222 _, err := w.Write(h.TrailerHeader())
2223 return err
2224}
2225
2226// TrailerHeader returns request trailer header representation.
2227//
2228// Trailers will only be received with chunked transfer.
2229//
2230// The returned value is valid until the request is released,
2231// either though ReleaseRequest or your request handler returning.
2232// Do not store references to returned value. Make copies instead.
2233func (h *RequestHeader) TrailerHeader() []byte {
2234 h.bufKV.value = h.bufKV.value[:0]
2235 for _, t := range h.trailer {
2236 value := h.peek(t.key)
2237 h.bufKV.value = appendHeaderLine(h.bufKV.value, t.key, value)
2238 }
2239 h.bufKV.value = append(h.bufKV.value, strCRLF...)
2240 return h.bufKV.value
2241}
2242
2243// RawHeaders returns raw header key/value bytes.
2244//
2245// Depending on server configuration, header keys may be normalized to
2246// capital-case in place.
2247//
2248// This copy is set aside during parsing, so empty slice is returned for all
2249// cases where parsing did not happen. Similarly, request line is not stored
2250// during parsing and can not be returned.
2251//
2252// The slice is not safe to use after the handler returns.
2253func (h *RequestHeader) RawHeaders() []byte {
2254 return h.rawHeaders
2255}
2256
2257// String returns request header representation.
2258func (h *RequestHeader) String() string {
2259 return string(h.Header())
2260}
2261
2262// AppendBytes appends request header representation to dst and returns
2263// the extended dst.
2264func (h *RequestHeader) AppendBytes(dst []byte) []byte {
2265 dst = append(dst, h.Method()...)
2266 dst = append(dst, ' ')
2267 dst = append(dst, h.RequestURI()...)
2268 dst = append(dst, ' ')
2269 dst = append(dst, h.Protocol()...)
2270 dst = append(dst, strCRLF...)
2271
2272 userAgent := h.UserAgent()
2273 if len(userAgent) > 0 {
2274 dst = appendHeaderLine(dst, strUserAgent, userAgent)
2275 }
2276
2277 host := h.Host()
2278 if len(host) > 0 {
2279 dst = appendHeaderLine(dst, strHost, host)
2280 }
2281
2282 contentType := h.ContentType()
2283 if !h.noDefaultContentType && len(contentType) == 0 && !h.ignoreBody() {
2284 contentType = strDefaultContentType
2285 }
2286 if len(contentType) > 0 {
2287 dst = appendHeaderLine(dst, strContentType, contentType)
2288 }
2289 if len(h.contentLengthBytes) > 0 {
2290 dst = appendHeaderLine(dst, strContentLength, h.contentLengthBytes)
2291 }
2292
2293 for i, n := 0, len(h.h); i < n; i++ {
2294 kv := &h.h[i]
2295 // Exclude trailer from header
2296 exclude := false
2297 for _, t := range h.trailer {
2298 if bytes.Equal(kv.key, t.key) {
2299 exclude = true
2300 break
2301 }
2302 }
2303 if !exclude {
2304 dst = appendHeaderLine(dst, kv.key, kv.value)
2305 }
2306 }
2307
2308 if len(h.trailer) > 0 {
2309 dst = appendHeaderLine(dst, strTrailer, appendArgsKeyBytes(nil, h.trailer, strCommaSpace))
2310 }
2311
2312 // there is no need in h.collectCookies() here, since if cookies aren't collected yet,
2313 // they all are located in h.h.
2314 n := len(h.cookies)
2315 if n > 0 {
2316 dst = append(dst, strCookie...)
2317 dst = append(dst, strColonSpace...)
2318 dst = appendRequestCookieBytes(dst, h.cookies)
2319 dst = append(dst, strCRLF...)
2320 }
2321
2322 if h.ConnectionClose() {
2323 dst = appendHeaderLine(dst, strConnection, strClose)
2324 }
2325
2326 return append(dst, strCRLF...)
2327}
2328
2329func appendHeaderLine(dst, key, value []byte) []byte {
2330 dst = append(dst, key...)
2331 dst = append(dst, strColonSpace...)
2332 dst = append(dst, value...)
2333 return append(dst, strCRLF...)
2334}
2335
2336func (h *ResponseHeader) parse(buf []byte) (int, error) {
2337 m, err := h.parseFirstLine(buf)
2338 if err != nil {
2339 return 0, err
2340 }
2341 n, err := h.parseHeaders(buf[m:])
2342 if err != nil {
2343 return 0, err
2344 }
2345 return m + n, nil
2346}
2347
2348func (h *ResponseHeader) parseTrailer(buf []byte) (int, error) {
2349 // Skip any 0 length chunk.
2350 if buf[0] == '0' {
2351 skip := len(strCRLF) + 1
2352 if len(buf) < skip {
2353 return 0, io.EOF
2354 }
2355 buf = buf[skip:]
2356 }
2357
2358 var s headerScanner
2359 s.b = buf
2360 s.disableNormalizing = h.disableNormalizing
2361 var err error
2362 for s.next() {
2363 if len(s.key) > 0 {
2364 if bytes.IndexByte(s.key, ' ') != -1 || bytes.IndexByte(s.key, '\t') != -1 {
2365 err = fmt.Errorf("invalid trailer key %q", s.key)
2366 continue
2367 }
2368 // Forbidden by RFC 7230, section 4.1.2
2369 if isBadTrailer(s.key) {
2370 err = fmt.Errorf("forbidden trailer key %q", s.key)
2371 continue
2372 }
2373 }
2374 h.h = appendArgBytes(h.h, s.key, s.value, argsHasValue)
2375 }
2376 if s.err != nil {
2377 return 0, s.err
2378 }
2379 if err != nil {
2380 return 0, err
2381 }
2382 return s.hLen, nil
2383}
2384
2385func (h *RequestHeader) ignoreBody() bool {
2386 return h.IsGet() || h.IsHead()
2387}
2388
2389func (h *RequestHeader) parse(buf []byte) (int, error) {
2390 m, err := h.parseFirstLine(buf)
2391 if err != nil {
2392 return 0, err
2393 }
2394
2395 h.rawHeaders, _, err = readRawHeaders(h.rawHeaders[:0], buf[m:])
2396 if err != nil {
2397 return 0, err
2398 }
2399 var n int
2400 n, err = h.parseHeaders(buf[m:])
2401 if err != nil {
2402 return 0, err
2403 }
2404 return m + n, nil
2405}
2406
2407func (h *RequestHeader) parseTrailer(buf []byte) (int, error) {
2408 // Skip any 0 length chunk.
2409 if buf[0] == '0' {
2410 skip := len(strCRLF) + 1
2411 if len(buf) < skip {
2412 return 0, io.EOF
2413 }
2414 buf = buf[skip:]
2415 }
2416
2417 var s headerScanner
2418 s.b = buf
2419 s.disableNormalizing = h.disableNormalizing
2420 var err error
2421 for s.next() {
2422 if len(s.key) > 0 {
2423 if bytes.IndexByte(s.key, ' ') != -1 || bytes.IndexByte(s.key, '\t') != -1 {
2424 err = fmt.Errorf("invalid trailer key %q", s.key)
2425 continue
2426 }
2427 // Forbidden by RFC 7230, section 4.1.2
2428 if isBadTrailer(s.key) {
2429 err = fmt.Errorf("forbidden trailer key %q", s.key)
2430 continue
2431 }
2432 h.h = appendArgBytes(h.h, s.key, s.value, argsHasValue)
2433 }
2434 }
2435 if s.err != nil {
2436 return 0, s.err
2437 }
2438 if err != nil {
2439 return 0, err
2440 }
2441 return s.hLen, nil
2442}
2443
2444func isBadTrailer(key []byte) bool {
2445 if len(key) == 0 {
2446 return true
2447 }
2448
2449 switch key[0] | 0x20 {
2450 case 'a':
2451 return caseInsensitiveCompare(key, strAuthorization)
2452 case 'c':
2453 if len(key) > len(HeaderContentType) && caseInsensitiveCompare(key[:8], strContentType[:8]) {
2454 // skip compare prefix 'Content-'
2455 return caseInsensitiveCompare(key[8:], strContentEncoding[8:]) ||
2456 caseInsensitiveCompare(key[8:], strContentLength[8:]) ||
2457 caseInsensitiveCompare(key[8:], strContentType[8:]) ||
2458 caseInsensitiveCompare(key[8:], strContentRange[8:])
2459 }
2460 return caseInsensitiveCompare(key, strConnection)
2461 case 'e':
2462 return caseInsensitiveCompare(key, strExpect)
2463 case 'h':
2464 return caseInsensitiveCompare(key, strHost)
2465 case 'k':
2466 return caseInsensitiveCompare(key, strKeepAlive)
2467 case 'm':
2468 return caseInsensitiveCompare(key, strMaxForwards)
2469 case 'p':
2470 if len(key) > len(HeaderProxyConnection) && caseInsensitiveCompare(key[:6], strProxyConnection[:6]) {
2471 // skip compare prefix 'Proxy-'
2472 return caseInsensitiveCompare(key[6:], strProxyConnection[6:]) ||
2473 caseInsensitiveCompare(key[6:], strProxyAuthenticate[6:]) ||
2474 caseInsensitiveCompare(key[6:], strProxyAuthorization[6:])
2475 }
2476 case 'r':
2477 return caseInsensitiveCompare(key, strRange)
2478 case 't':
2479 return caseInsensitiveCompare(key, strTE) ||
2480 caseInsensitiveCompare(key, strTrailer) ||
2481 caseInsensitiveCompare(key, strTransferEncoding)
2482 case 'w':
2483 return caseInsensitiveCompare(key, strWWWAuthenticate)
2484 }
2485 return false
2486}
2487
2488func (h *ResponseHeader) parseFirstLine(buf []byte) (int, error) {
2489 bNext := buf
2490 var b []byte
2491 var err error
2492 for len(b) == 0 {
2493 if b, bNext, err = nextLine(bNext); err != nil {
2494 return 0, err
2495 }
2496 }
2497
2498 // parse protocol
2499 n := bytes.IndexByte(b, ' ')
2500 if n < 0 {
2501 if h.secureErrorLogMessage {
2502 return 0, fmt.Errorf("cannot find whitespace in the first line of response")
2503 }
2504 return 0, fmt.Errorf("cannot find whitespace in the first line of response %q", buf)
2505 }
2506 h.noHTTP11 = !bytes.Equal(b[:n], strHTTP11)
2507 b = b[n+1:]
2508
2509 // parse status code
2510 h.statusCode, n, err = parseUintBuf(b)
2511 if err != nil {
2512 if h.secureErrorLogMessage {
2513 return 0, fmt.Errorf("cannot parse response status code: %w", err)
2514 }
2515 return 0, fmt.Errorf("cannot parse response status code: %w. Response %q", err, buf)
2516 }
2517 if len(b) > n && b[n] != ' ' {
2518 if h.secureErrorLogMessage {
2519 return 0, fmt.Errorf("unexpected char at the end of status code")
2520 }
2521 return 0, fmt.Errorf("unexpected char at the end of status code. Response %q", buf)
2522 }
2523 if len(b) > n+1 {
2524 h.SetStatusMessage(b[n+1:])
2525 }
2526
2527 return len(buf) - len(bNext), nil
2528}
2529
2530func (h *RequestHeader) parseFirstLine(buf []byte) (int, error) {
2531 bNext := buf
2532 var b []byte
2533 var err error
2534 for len(b) == 0 {
2535 if b, bNext, err = nextLine(bNext); err != nil {
2536 return 0, err
2537 }
2538 }
2539
2540 // parse method
2541 n := bytes.IndexByte(b, ' ')
2542 if n <= 0 {
2543 if h.secureErrorLogMessage {
2544 return 0, fmt.Errorf("cannot find http request method")
2545 }
2546 return 0, fmt.Errorf("cannot find http request method in %q", buf)
2547 }
2548 h.method = append(h.method[:0], b[:n]...)
2549 b = b[n+1:]
2550
2551 protoStr := strHTTP11
2552 // parse requestURI
2553 n = bytes.LastIndexByte(b, ' ')
2554 if n < 0 {
2555 h.noHTTP11 = true
2556 n = len(b)
2557 protoStr = strHTTP10
2558 } else if n == 0 {
2559 if h.secureErrorLogMessage {
2560 return 0, fmt.Errorf("requestURI cannot be empty")
2561 }
2562 return 0, fmt.Errorf("requestURI cannot be empty in %q", buf)
2563 } else if !bytes.Equal(b[n+1:], strHTTP11) {
2564 h.noHTTP11 = true
2565 protoStr = b[n+1:]
2566 }
2567
2568 h.proto = append(h.proto[:0], protoStr...)
2569 h.requestURI = append(h.requestURI[:0], b[:n]...)
2570
2571 return len(buf) - len(bNext), nil
2572}
2573
2574func readRawHeaders(dst, buf []byte) ([]byte, int, error) {
2575 n := bytes.IndexByte(buf, nChar)
2576 if n < 0 {
2577 return dst[:0], 0, errNeedMore
2578 }
2579 if (n == 1 && buf[0] == rChar) || n == 0 {
2580 // empty headers
2581 return dst, n + 1, nil
2582 }
2583
2584 n++
2585 b := buf
2586 m := n
2587 for {
2588 b = b[m:]
2589 m = bytes.IndexByte(b, nChar)
2590 if m < 0 {
2591 return dst, 0, errNeedMore
2592 }
2593 m++
2594 n += m
2595 if (m == 2 && b[0] == rChar) || m == 1 {
2596 dst = append(dst, buf[:n]...)
2597 return dst, n, nil
2598 }
2599 }
2600}
2601
2602func (h *ResponseHeader) parseHeaders(buf []byte) (int, error) {
2603 // 'identity' content-length by default
2604 h.contentLength = -2
2605
2606 var s headerScanner
2607 s.b = buf
2608 s.disableNormalizing = h.disableNormalizing
2609 var err error
2610 var kv *argsKV
2611 for s.next() {
2612 if len(s.key) > 0 {
2613 switch s.key[0] | 0x20 {
2614 case 'c':
2615 if caseInsensitiveCompare(s.key, strContentType) {
2616 h.contentType = append(h.contentType[:0], s.value...)
2617 continue
2618 }
2619 if caseInsensitiveCompare(s.key, strContentLength) {
2620 if h.contentLength != -1 {
2621 if h.contentLength, err = parseContentLength(s.value); err != nil {
2622 h.contentLength = -2
2623 } else {
2624 h.contentLengthBytes = append(h.contentLengthBytes[:0], s.value...)
2625 }
2626 }
2627 continue
2628 }
2629 if caseInsensitiveCompare(s.key, strConnection) {
2630 if bytes.Equal(s.value, strClose) {
2631 h.connectionClose = true
2632 } else {
2633 h.connectionClose = false
2634 h.h = appendArgBytes(h.h, s.key, s.value, argsHasValue)
2635 }
2636 continue
2637 }
2638 case 's':
2639 if caseInsensitiveCompare(s.key, strServer) {
2640 h.server = append(h.server[:0], s.value...)
2641 continue
2642 }
2643 if caseInsensitiveCompare(s.key, strSetCookie) {
2644 h.cookies, kv = allocArg(h.cookies)
2645 kv.key = getCookieKey(kv.key, s.value)
2646 kv.value = append(kv.value[:0], s.value...)
2647 continue
2648 }
2649 case 't':
2650 if caseInsensitiveCompare(s.key, strTransferEncoding) {
2651 if len(s.value) > 0 && !bytes.Equal(s.value, strIdentity) {
2652 h.contentLength = -1
2653 h.h = setArgBytes(h.h, strTransferEncoding, strChunked, argsHasValue)
2654 }
2655 continue
2656 }
2657 if caseInsensitiveCompare(s.key, strTrailer) {
2658 err = h.SetTrailerBytes(s.value)
2659 continue
2660 }
2661 }
2662 h.h = appendArgBytes(h.h, s.key, s.value, argsHasValue)
2663 }
2664 }
2665 if s.err != nil {
2666 h.connectionClose = true
2667 return 0, s.err
2668 }
2669
2670 if h.contentLength < 0 {
2671 h.contentLengthBytes = h.contentLengthBytes[:0]
2672 }
2673 if h.contentLength == -2 && !h.ConnectionUpgrade() && !h.mustSkipContentLength() {
2674 h.h = setArgBytes(h.h, strTransferEncoding, strIdentity, argsHasValue)
2675 h.connectionClose = true
2676 }
2677 if h.noHTTP11 && !h.connectionClose {
2678 // close connection for non-http/1.1 response unless 'Connection: keep-alive' is set.
2679 v := peekArgBytes(h.h, strConnection)
2680 h.connectionClose = !hasHeaderValue(v, strKeepAlive)
2681 }
2682
2683 return len(buf) - len(s.b), err
2684}
2685
2686func (h *RequestHeader) parseHeaders(buf []byte) (int, error) {
2687 h.contentLength = -2
2688
2689 var s headerScanner
2690 s.b = buf
2691 s.disableNormalizing = h.disableNormalizing
2692 var err error
2693 for s.next() {
2694 if len(s.key) > 0 {
2695 // Spaces between the header key and colon are not allowed.
2696 // See RFC 7230, Section 3.2.4.
2697 if bytes.IndexByte(s.key, ' ') != -1 || bytes.IndexByte(s.key, '\t') != -1 {
2698 err = fmt.Errorf("invalid header key %q", s.key)
2699 continue
2700 }
2701
2702 switch s.key[0] | 0x20 {
2703 case 'h':
2704 if caseInsensitiveCompare(s.key, strHost) {
2705 h.host = append(h.host[:0], s.value...)
2706 continue
2707 }
2708 case 'u':
2709 if caseInsensitiveCompare(s.key, strUserAgent) {
2710 h.userAgent = append(h.userAgent[:0], s.value...)
2711 continue
2712 }
2713 case 'c':
2714 if caseInsensitiveCompare(s.key, strContentType) {
2715 h.contentType = append(h.contentType[:0], s.value...)
2716 continue
2717 }
2718 if caseInsensitiveCompare(s.key, strContentLength) {
2719 if h.contentLength != -1 {
2720 var nerr error
2721 if h.contentLength, nerr = parseContentLength(s.value); nerr != nil {
2722 if err == nil {
2723 err = nerr
2724 }
2725 h.contentLength = -2
2726 } else {
2727 h.contentLengthBytes = append(h.contentLengthBytes[:0], s.value...)
2728 }
2729 }
2730 continue
2731 }
2732 if caseInsensitiveCompare(s.key, strConnection) {
2733 if bytes.Equal(s.value, strClose) {
2734 h.connectionClose = true
2735 } else {
2736 h.connectionClose = false
2737 h.h = appendArgBytes(h.h, s.key, s.value, argsHasValue)
2738 }
2739 continue
2740 }
2741 case 't':
2742 if caseInsensitiveCompare(s.key, strTransferEncoding) {
2743 if !bytes.Equal(s.value, strIdentity) {
2744 h.contentLength = -1
2745 h.h = setArgBytes(h.h, strTransferEncoding, strChunked, argsHasValue)
2746 }
2747 continue
2748 }
2749 if caseInsensitiveCompare(s.key, strTrailer) {
2750 if nerr := h.SetTrailerBytes(s.value); nerr != nil {
2751 if err == nil {
2752 err = nerr
2753 }
2754 }
2755 continue
2756 }
2757 }
2758 }
2759 h.h = appendArgBytes(h.h, s.key, s.value, argsHasValue)
2760 }
2761 if s.err != nil && err == nil {
2762 err = s.err
2763 }
2764 if err != nil {
2765 h.connectionClose = true
2766 return 0, err
2767 }
2768
2769 if h.contentLength < 0 {
2770 h.contentLengthBytes = h.contentLengthBytes[:0]
2771 }
2772 if h.noHTTP11 && !h.connectionClose {
2773 // close connection for non-http/1.1 request unless 'Connection: keep-alive' is set.
2774 v := peekArgBytes(h.h, strConnection)
2775 h.connectionClose = !hasHeaderValue(v, strKeepAlive)
2776 }
2777 return s.hLen, nil
2778}
2779
2780func (h *RequestHeader) collectCookies() {
2781 if h.cookiesCollected {
2782 return
2783 }
2784
2785 for i, n := 0, len(h.h); i < n; i++ {
2786 kv := &h.h[i]
2787 if caseInsensitiveCompare(kv.key, strCookie) {
2788 h.cookies = parseRequestCookies(h.cookies, kv.value)
2789 tmp := *kv
2790 copy(h.h[i:], h.h[i+1:])
2791 n--
2792 i--
2793 h.h[n] = tmp
2794 h.h = h.h[:n]
2795 }
2796 }
2797 h.cookiesCollected = true
2798}
2799
2800var errNonNumericChars = errors.New("non-numeric chars found")
2801
2802func parseContentLength(b []byte) (int, error) {
2803 v, n, err := parseUintBuf(b)
2804 if err != nil {
2805 return -1, fmt.Errorf("cannot parse Content-Length: %w", err)
2806 }
2807 if n != len(b) {
2808 return -1, fmt.Errorf("cannot parse Content-Length: %w", errNonNumericChars)
2809 }
2810 return v, nil
2811}
2812
2813type headerScanner struct {
2814 b []byte
2815 key []byte
2816 value []byte
2817 err error
2818
2819 // hLen stores header subslice len
2820 hLen int
2821
2822 disableNormalizing bool
2823
2824 // by checking whether the next line contains a colon or not to tell
2825 // it's a header entry or a multi line value of current header entry.
2826 // the side effect of this operation is that we know the index of the
2827 // next colon and new line, so this can be used during next iteration,
2828 // instead of find them again.
2829 nextColon int
2830 nextNewLine int
2831
2832 initialized bool
2833}
2834
2835func (s *headerScanner) next() bool {
2836 if !s.initialized {
2837 s.nextColon = -1
2838 s.nextNewLine = -1
2839 s.initialized = true
2840 }
2841 bLen := len(s.b)
2842 if bLen >= 2 && s.b[0] == rChar && s.b[1] == nChar {
2843 s.b = s.b[2:]
2844 s.hLen += 2
2845 return false
2846 }
2847 if bLen >= 1 && s.b[0] == nChar {
2848 s.b = s.b[1:]
2849 s.hLen++
2850 return false
2851 }
2852 var n int
2853 if s.nextColon >= 0 {
2854 n = s.nextColon
2855 s.nextColon = -1
2856 } else {
2857 n = bytes.IndexByte(s.b, ':')
2858
2859 // There can't be a \n inside the header name, check for this.
2860 x := bytes.IndexByte(s.b, nChar)
2861 if x < 0 {
2862 // A header name should always at some point be followed by a \n
2863 // even if it's the one that terminates the header block.
2864 s.err = errNeedMore
2865 return false
2866 }
2867 if x < n {
2868 // There was a \n before the :
2869 s.err = errInvalidName
2870 return false
2871 }
2872 }
2873 if n < 0 {
2874 s.err = errNeedMore
2875 return false
2876 }
2877 s.key = s.b[:n]
2878 normalizeHeaderKey(s.key, s.disableNormalizing)
2879 n++
2880 for len(s.b) > n && s.b[n] == ' ' {
2881 n++
2882 // the newline index is a relative index, and lines below trimed `s.b` by `n`,
2883 // so the relative newline index also shifted forward. it's safe to decrease
2884 // to a minus value, it means it's invalid, and will find the newline again.
2885 s.nextNewLine--
2886 }
2887 s.hLen += n
2888 s.b = s.b[n:]
2889 if s.nextNewLine >= 0 {
2890 n = s.nextNewLine
2891 s.nextNewLine = -1
2892 } else {
2893 n = bytes.IndexByte(s.b, nChar)
2894 }
2895 if n < 0 {
2896 s.err = errNeedMore
2897 return false
2898 }
2899 isMultiLineValue := false
2900 for {
2901 if n+1 >= len(s.b) {
2902 break
2903 }
2904 if s.b[n+1] != ' ' && s.b[n+1] != '\t' {
2905 break
2906 }
2907 d := bytes.IndexByte(s.b[n+1:], nChar)
2908 if d <= 0 {
2909 break
2910 } else if d == 1 && s.b[n+1] == rChar {
2911 break
2912 }
2913 e := n + d + 1
2914 if c := bytes.IndexByte(s.b[n+1:e], ':'); c >= 0 {
2915 s.nextColon = c
2916 s.nextNewLine = d - c - 1
2917 break
2918 }
2919 isMultiLineValue = true
2920 n = e
2921 }
2922 if n >= len(s.b) {
2923 s.err = errNeedMore
2924 return false
2925 }
2926 oldB := s.b
2927 s.value = s.b[:n]
2928 s.hLen += n + 1
2929 s.b = s.b[n+1:]
2930
2931 if n > 0 && s.value[n-1] == rChar {
2932 n--
2933 }
2934 for n > 0 && s.value[n-1] == ' ' {
2935 n--
2936 }
2937 s.value = s.value[:n]
2938 if isMultiLineValue {
2939 s.value, s.b, s.hLen = normalizeHeaderValue(s.value, oldB, s.hLen)
2940 }
2941 return true
2942}
2943
2944type headerValueScanner struct {
2945 b []byte
2946 value []byte
2947}
2948
2949func (s *headerValueScanner) next() bool {
2950 b := s.b
2951 if len(b) == 0 {
2952 return false
2953 }
2954 n := bytes.IndexByte(b, ',')
2955 if n < 0 {
2956 s.value = stripSpace(b)
2957 s.b = b[len(b):]
2958 return true
2959 }
2960 s.value = stripSpace(b[:n])
2961 s.b = b[n+1:]
2962 return true
2963}
2964
2965func stripSpace(b []byte) []byte {
2966 for len(b) > 0 && b[0] == ' ' {
2967 b = b[1:]
2968 }
2969 for len(b) > 0 && b[len(b)-1] == ' ' {
2970 b = b[:len(b)-1]
2971 }
2972 return b
2973}
2974
2975func hasHeaderValue(s, value []byte) bool {
2976 var vs headerValueScanner
2977 vs.b = s
2978 for vs.next() {
2979 if caseInsensitiveCompare(vs.value, value) {
2980 return true
2981 }
2982 }
2983 return false
2984}
2985
2986func nextLine(b []byte) ([]byte, []byte, error) {
2987 nNext := bytes.IndexByte(b, nChar)
2988 if nNext < 0 {
2989 return nil, nil, errNeedMore
2990 }
2991 n := nNext
2992 if n > 0 && b[n-1] == rChar {
2993 n--
2994 }
2995 return b[:n], b[nNext+1:], nil
2996}
2997
2998func initHeaderKV(kv *argsKV, key, value string, disableNormalizing bool) {
2999 kv.key = getHeaderKeyBytes(kv, key, disableNormalizing)
3000 // https://tools.ietf.org/html/rfc7230#section-3.2.4
3001 kv.value = append(kv.value[:0], value...)
3002 kv.value = removeNewLines(kv.value)
3003}
3004
3005func getHeaderKeyBytes(kv *argsKV, key string, disableNormalizing bool) []byte {
3006 kv.key = append(kv.key[:0], key...)
3007 normalizeHeaderKey(kv.key, disableNormalizing)
3008 return kv.key
3009}
3010
3011func normalizeHeaderValue(ov, ob []byte, headerLength int) (nv, nb []byte, nhl int) {
3012 nv = ov
3013 length := len(ov)
3014 if length <= 0 {
3015 return
3016 }
3017 write := 0
3018 shrunk := 0
3019 lineStart := false
3020 for read := 0; read < length; read++ {
3021 c := ov[read]
3022 if c == rChar || c == nChar {
3023 shrunk++
3024 if c == nChar {
3025 lineStart = true
3026 }
3027 continue
3028 } else if lineStart && c == '\t' {
3029 c = ' '
3030 } else {
3031 lineStart = false
3032 }
3033 nv[write] = c
3034 write++
3035 }
3036
3037 nv = nv[:write]
3038 copy(ob[write:], ob[write+shrunk:])
3039
3040 // Check if we need to skip \r\n or just \n
3041 skip := 0
3042 if ob[write] == rChar {
3043 if ob[write+1] == nChar {
3044 skip += 2
3045 } else {
3046 skip++
3047 }
3048 } else if ob[write] == nChar {
3049 skip++
3050 }
3051
3052 nb = ob[write+skip : len(ob)-shrunk]
3053 nhl = headerLength - shrunk
3054 return
3055}
3056
3057func normalizeHeaderKey(b []byte, disableNormalizing bool) {
3058 if disableNormalizing {
3059 return
3060 }
3061
3062 n := len(b)
3063 if n == 0 {
3064 return
3065 }
3066
3067 b[0] = toUpperTable[b[0]]
3068 for i := 1; i < n; i++ {
3069 p := &b[i]
3070 if *p == '-' {
3071 i++
3072 if i < n {
3073 b[i] = toUpperTable[b[i]]
3074 }
3075 continue
3076 }
3077 *p = toLowerTable[*p]
3078 }
3079}
3080
3081// removeNewLines will replace `\r` and `\n` with an empty space
3082func removeNewLines(raw []byte) []byte {
3083 // check if a `\r` is present and save the position.
3084 // if no `\r` is found, check if a `\n` is present.
3085 foundR := bytes.IndexByte(raw, rChar)
3086 foundN := bytes.IndexByte(raw, nChar)
3087 start := 0
3088
3089 if foundN != -1 {
3090 if foundR > foundN {
3091 start = foundN
3092 } else if foundR != -1 {
3093 start = foundR
3094 }
3095 } else if foundR != -1 {
3096 start = foundR
3097 } else {
3098 return raw
3099 }
3100
3101 for i := start; i < len(raw); i++ {
3102 switch raw[i] {
3103 case rChar, nChar:
3104 raw[i] = ' '
3105 default:
3106 continue
3107 }
3108 }
3109 return raw
3110}
3111
3112// AppendNormalizedHeaderKey appends normalized header key (name) to dst
3113// and returns the resulting dst.
3114//
3115// Normalized header key starts with uppercase letter. The first letters
3116// after dashes are also uppercased. All the other letters are lowercased.
3117// Examples:
3118//
3119// * coNTENT-TYPe -> Content-Type
3120// * HOST -> Host
3121// * foo-bar-baz -> Foo-Bar-Baz
3122func AppendNormalizedHeaderKey(dst []byte, key string) []byte {
3123 dst = append(dst, key...)
3124 normalizeHeaderKey(dst[len(dst)-len(key):], false)
3125 return dst
3126}
3127
3128// AppendNormalizedHeaderKeyBytes appends normalized header key (name) to dst
3129// and returns the resulting dst.
3130//
3131// Normalized header key starts with uppercase letter. The first letters
3132// after dashes are also uppercased. All the other letters are lowercased.
3133// Examples:
3134//
3135// * coNTENT-TYPe -> Content-Type
3136// * HOST -> Host
3137// * foo-bar-baz -> Foo-Bar-Baz
3138func AppendNormalizedHeaderKeyBytes(dst, key []byte) []byte {
3139 return AppendNormalizedHeaderKey(dst, b2s(key))
3140}
3141
3142func appendArgsKeyBytes(dst []byte, args []argsKV, sep []byte) []byte {
3143 for i, n := 0, len(args); i < n; i++ {
3144 kv := &args[i]
3145 dst = append(dst, kv.key...)
3146 if i+1 < n {
3147 dst = append(dst, sep...)
3148 }
3149 }
3150 return dst
3151}
3152
3153var (
3154 errNeedMore = errors.New("need more data: cannot find trailing lf")
3155 errInvalidName = errors.New("invalid header name")
3156 errSmallBuffer = errors.New("small read buffer. Increase ReadBufferSize")
3157)
3158
3159// ErrNothingRead is returned when a keep-alive connection is closed,
3160// either because the remote closed it or because of a read timeout.
3161type ErrNothingRead struct {
3162 error
3163}
3164
3165// ErrSmallBuffer is returned when the provided buffer size is too small
3166// for reading request and/or response headers.
3167//
3168// ReadBufferSize value from Server or clients should reduce the number
3169// of such errors.
3170type ErrSmallBuffer struct {
3171 error
3172}
3173
3174func mustPeekBuffered(r *bufio.Reader) []byte {
3175 buf, err := r.Peek(r.Buffered())
3176 if len(buf) == 0 || err != nil {
3177 panic(fmt.Sprintf("bufio.Reader.Peek() returned unexpected data (%q, %v)", buf, err))
3178 }
3179 return buf
3180}
3181
3182func mustDiscard(r *bufio.Reader, n int) {
3183 if _, err := r.Discard(n); err != nil {
3184 panic(fmt.Sprintf("bufio.Reader.Discard(%d) failed: %s", n, err))
3185 }
3186}
Note: See TracBrowser for help on using the repository browser.