1package fasthttp 2 3import ( 4 "bufio" 5 "bytes" 6 "errors" 7 "fmt" 8 "io" 9 "sync/atomic" 10 "time" 11) 12 13// ResponseHeader represents HTTP response header. 14// 15// It is forbidden copying ResponseHeader instances. 16// Create new instances instead and use CopyTo. 17// 18// ResponseHeader instance MUST NOT be used from concurrently running 19// goroutines. 20type ResponseHeader struct { 21 noCopy noCopy 22 23 disableNormalizing bool 24 noHTTP11 bool 25 connectionClose bool 26 noDefaultContentType bool 27 28 statusCode int 29 contentLength int 30 contentLengthBytes []byte 31 32 contentType []byte 33 server []byte 34 35 h []argsKV 36 bufKV argsKV 37 38 cookies []argsKV 39} 40 41// RequestHeader represents HTTP request header. 42// 43// It is forbidden copying RequestHeader instances. 44// Create new instances instead and use CopyTo. 45// 46// RequestHeader instance MUST NOT be used from concurrently running 47// goroutines. 48type RequestHeader struct { 49 noCopy noCopy 50 51 disableNormalizing bool 52 noHTTP11 bool 53 connectionClose bool 54 55 // These two fields have been moved close to other bool fields 56 // for reducing RequestHeader object size. 57 cookiesCollected bool 58 rawHeadersParsed bool 59 60 contentLength int 61 contentLengthBytes []byte 62 63 method []byte 64 requestURI []byte 65 host []byte 66 contentType []byte 67 userAgent []byte 68 69 h []argsKV 70 bufKV argsKV 71 72 cookies []argsKV 73 74 rawHeaders []byte 75 76 // stores an immutable copy of headers as they were received from the 77 // wire. 78 rawHeadersCopy []byte 79} 80 81// SetContentRange sets 'Content-Range: bytes startPos-endPos/contentLength' 82// header. 83func (h *ResponseHeader) SetContentRange(startPos, endPos, contentLength int) { 84 b := h.bufKV.value[:0] 85 b = append(b, strBytes...) 86 b = append(b, ' ') 87 b = AppendUint(b, startPos) 88 b = append(b, '-') 89 b = AppendUint(b, endPos) 90 b = append(b, '/') 91 b = AppendUint(b, contentLength) 92 h.bufKV.value = b 93 94 h.SetCanonical(strContentRange, h.bufKV.value) 95} 96 97// SetByteRange sets 'Range: bytes=startPos-endPos' header. 98// 99// * If startPos is negative, then 'bytes=-startPos' value is set. 100// * If endPos is negative, then 'bytes=startPos-' value is set. 101func (h *RequestHeader) SetByteRange(startPos, endPos int) { 102 h.parseRawHeaders() 103 104 b := h.bufKV.value[:0] 105 b = append(b, strBytes...) 106 b = append(b, '=') 107 if startPos >= 0 { 108 b = AppendUint(b, startPos) 109 } else { 110 endPos = -startPos 111 } 112 b = append(b, '-') 113 if endPos >= 0 { 114 b = AppendUint(b, endPos) 115 } 116 h.bufKV.value = b 117 118 h.SetCanonical(strRange, h.bufKV.value) 119} 120 121// StatusCode returns response status code. 122func (h *ResponseHeader) StatusCode() int { 123 if h.statusCode == 0 { 124 return StatusOK 125 } 126 return h.statusCode 127} 128 129// SetStatusCode sets response status code. 130func (h *ResponseHeader) SetStatusCode(statusCode int) { 131 h.statusCode = statusCode 132} 133 134// SetLastModified sets 'Last-Modified' header to the given value. 135func (h *ResponseHeader) SetLastModified(t time.Time) { 136 h.bufKV.value = AppendHTTPDate(h.bufKV.value[:0], t) 137 h.SetCanonical(strLastModified, h.bufKV.value) 138} 139 140// ConnectionClose returns true if 'Connection: close' header is set. 141func (h *ResponseHeader) ConnectionClose() bool { 142 return h.connectionClose 143} 144 145// SetConnectionClose sets 'Connection: close' header. 146func (h *ResponseHeader) SetConnectionClose() { 147 h.connectionClose = true 148} 149 150// ResetConnectionClose clears 'Connection: close' header if it exists. 151func (h *ResponseHeader) ResetConnectionClose() { 152 if h.connectionClose { 153 h.connectionClose = false 154 h.h = delAllArgsBytes(h.h, strConnection) 155 } 156} 157 158// ConnectionClose returns true if 'Connection: close' header is set. 159func (h *RequestHeader) ConnectionClose() bool { 160 h.parseRawHeaders() 161 return h.connectionClose 162} 163 164// SetConnectionClose sets 'Connection: close' header. 165func (h *RequestHeader) SetConnectionClose() { 166 // h.parseRawHeaders() isn't called for performance reasons. 167 h.connectionClose = true 168} 169 170// ResetConnectionClose clears 'Connection: close' header if it exists. 171func (h *RequestHeader) ResetConnectionClose() { 172 h.parseRawHeaders() 173 if h.connectionClose { 174 h.connectionClose = false 175 h.h = delAllArgsBytes(h.h, strConnection) 176 } 177} 178 179// ConnectionUpgrade returns true if 'Connection: Upgrade' header is set. 180func (h *ResponseHeader) ConnectionUpgrade() bool { 181 return hasHeaderValue(h.Peek("Connection"), strUpgrade) 182} 183 184// ConnectionUpgrade returns true if 'Connection: Upgrade' header is set. 185func (h *RequestHeader) ConnectionUpgrade() bool { 186 h.parseRawHeaders() 187 return hasHeaderValue(h.Peek("Connection"), strUpgrade) 188} 189 190// PeekCookie is able to returns cookie by a given key from response. 191func (h *ResponseHeader) PeekCookie(key string) []byte { 192 return peekArgStr(h.cookies, key) 193} 194 195// ContentLength returns Content-Length header value. 196// 197// It may be negative: 198// -1 means Transfer-Encoding: chunked. 199// -2 means Transfer-Encoding: identity. 200func (h *ResponseHeader) ContentLength() int { 201 return h.contentLength 202} 203 204// SetContentLength sets Content-Length header value. 205// 206// Content-Length may be negative: 207// -1 means Transfer-Encoding: chunked. 208// -2 means Transfer-Encoding: identity. 209func (h *ResponseHeader) SetContentLength(contentLength int) { 210 if h.mustSkipContentLength() { 211 return 212 } 213 h.contentLength = contentLength 214 if contentLength >= 0 { 215 h.contentLengthBytes = AppendUint(h.contentLengthBytes[:0], contentLength) 216 h.h = delAllArgsBytes(h.h, strTransferEncoding) 217 } else { 218 h.contentLengthBytes = h.contentLengthBytes[:0] 219 value := strChunked 220 if contentLength == -2 { 221 h.SetConnectionClose() 222 value = strIdentity 223 } 224 h.h = setArgBytes(h.h, strTransferEncoding, value, argsHasValue) 225 } 226} 227 228func (h *ResponseHeader) mustSkipContentLength() bool { 229 // From http/1.1 specs: 230 // All 1xx (informational), 204 (no content), and 304 (not modified) responses MUST NOT include a message-body 231 statusCode := h.StatusCode() 232 233 // Fast path. 234 if statusCode < 100 || statusCode == StatusOK { 235 return false 236 } 237 238 // Slow path. 239 return statusCode == StatusNotModified || statusCode == StatusNoContent || statusCode < 200 240} 241 242// ContentLength returns Content-Length header value. 243// 244// It may be negative: 245// -1 means Transfer-Encoding: chunked. 246func (h *RequestHeader) ContentLength() int { 247 if h.ignoreBody() { 248 return 0 249 } 250 return h.realContentLength() 251} 252 253// realContentLength returns the actual Content-Length set in the request, 254// including positive lengths for GET/HEAD requests. 255func (h *RequestHeader) realContentLength() int { 256 h.parseRawHeaders() 257 return h.contentLength 258} 259 260// SetContentLength sets Content-Length header value. 261// 262// Negative content-length sets 'Transfer-Encoding: chunked' header. 263func (h *RequestHeader) SetContentLength(contentLength int) { 264 h.parseRawHeaders() 265 h.contentLength = contentLength 266 if contentLength >= 0 { 267 h.contentLengthBytes = AppendUint(h.contentLengthBytes[:0], contentLength) 268 h.h = delAllArgsBytes(h.h, strTransferEncoding) 269 } else { 270 h.contentLengthBytes = h.contentLengthBytes[:0] 271 h.h = setArgBytes(h.h, strTransferEncoding, strChunked, argsHasValue) 272 } 273} 274 275func (h *ResponseHeader) isCompressibleContentType() bool { 276 contentType := h.ContentType() 277 return bytes.HasPrefix(contentType, strTextSlash) || 278 bytes.HasPrefix(contentType, strApplicationSlash) 279} 280 281// ContentType returns Content-Type header value. 282func (h *ResponseHeader) ContentType() []byte { 283 contentType := h.contentType 284 if !h.noDefaultContentType && len(h.contentType) == 0 { 285 contentType = defaultContentType 286 } 287 return contentType 288} 289 290// SetContentType sets Content-Type header value. 291func (h *ResponseHeader) SetContentType(contentType string) { 292 h.contentType = append(h.contentType[:0], contentType...) 293} 294 295// SetContentTypeBytes sets Content-Type header value. 296func (h *ResponseHeader) SetContentTypeBytes(contentType []byte) { 297 h.contentType = append(h.contentType[:0], contentType...) 298} 299 300// Server returns Server header value. 301func (h *ResponseHeader) Server() []byte { 302 return h.server 303} 304 305// SetServer sets Server header value. 306func (h *ResponseHeader) SetServer(server string) { 307 h.server = append(h.server[:0], server...) 308} 309 310// SetServerBytes sets Server header value. 311func (h *ResponseHeader) SetServerBytes(server []byte) { 312 h.server = append(h.server[:0], server...) 313} 314 315// ContentType returns Content-Type header value. 316func (h *RequestHeader) ContentType() []byte { 317 h.parseRawHeaders() 318 return h.contentType 319} 320 321// SetContentType sets Content-Type header value. 322func (h *RequestHeader) SetContentType(contentType string) { 323 h.parseRawHeaders() 324 h.contentType = append(h.contentType[:0], contentType...) 325} 326 327// SetContentTypeBytes sets Content-Type header value. 328func (h *RequestHeader) SetContentTypeBytes(contentType []byte) { 329 h.parseRawHeaders() 330 h.contentType = append(h.contentType[:0], contentType...) 331} 332 333// SetMultipartFormBoundary sets the following Content-Type: 334// 'multipart/form-data; boundary=...' 335// where ... is substituted by the given boundary. 336func (h *RequestHeader) SetMultipartFormBoundary(boundary string) { 337 h.parseRawHeaders() 338 339 b := h.bufKV.value[:0] 340 b = append(b, strMultipartFormData...) 341 b = append(b, ';', ' ') 342 b = append(b, strBoundary...) 343 b = append(b, '=') 344 b = append(b, boundary...) 345 h.bufKV.value = b 346 347 h.SetContentTypeBytes(h.bufKV.value) 348} 349 350// SetMultipartFormBoundaryBytes sets the following Content-Type: 351// 'multipart/form-data; boundary=...' 352// where ... is substituted by the given boundary. 353func (h *RequestHeader) SetMultipartFormBoundaryBytes(boundary []byte) { 354 h.parseRawHeaders() 355 356 b := h.bufKV.value[:0] 357 b = append(b, strMultipartFormData...) 358 b = append(b, ';', ' ') 359 b = append(b, strBoundary...) 360 b = append(b, '=') 361 b = append(b, boundary...) 362 h.bufKV.value = b 363 364 h.SetContentTypeBytes(h.bufKV.value) 365} 366 367// MultipartFormBoundary returns boundary part 368// from 'multipart/form-data; boundary=...' Content-Type. 369func (h *RequestHeader) MultipartFormBoundary() []byte { 370 b := h.ContentType() 371 if !bytes.HasPrefix(b, strMultipartFormData) { 372 return nil 373 } 374 b = b[len(strMultipartFormData):] 375 if len(b) == 0 || b[0] != ';' { 376 return nil 377 } 378 379 var n int 380 for len(b) > 0 { 381 n++ 382 for len(b) > n && b[n] == ' ' { 383 n++ 384 } 385 b = b[n:] 386 if !bytes.HasPrefix(b, strBoundary) { 387 if n = bytes.IndexByte(b, ';'); n < 0 { 388 return nil 389 } 390 continue 391 } 392 393 b = b[len(strBoundary):] 394 if len(b) == 0 || b[0] != '=' { 395 return nil 396 } 397 b = b[1:] 398 if n = bytes.IndexByte(b, ';'); n >= 0 { 399 b = b[:n] 400 } 401 if len(b) > 1 && b[0] == '"' && b[len(b)-1] == '"' { 402 b = b[1 : len(b)-1] 403 } 404 return b 405 } 406 return nil 407} 408 409// Host returns Host header value. 410func (h *RequestHeader) Host() []byte { 411 if len(h.host) > 0 { 412 return h.host 413 } 414 if !h.rawHeadersParsed { 415 // fast path without employing full headers parsing. 416 host := peekRawHeader(h.rawHeaders, strHost) 417 if len(host) > 0 { 418 h.host = append(h.host[:0], host...) 419 return h.host 420 } 421 } 422 423 // slow path. 424 h.parseRawHeaders() 425 return h.host 426} 427 428// SetHost sets Host header value. 429func (h *RequestHeader) SetHost(host string) { 430 h.parseRawHeaders() 431 h.host = append(h.host[:0], host...) 432} 433 434// SetHostBytes sets Host header value. 435func (h *RequestHeader) SetHostBytes(host []byte) { 436 h.parseRawHeaders() 437 h.host = append(h.host[:0], host...) 438} 439 440// UserAgent returns User-Agent header value. 441func (h *RequestHeader) UserAgent() []byte { 442 h.parseRawHeaders() 443 return h.userAgent 444} 445 446// SetUserAgent sets User-Agent header value. 447func (h *RequestHeader) SetUserAgent(userAgent string) { 448 h.parseRawHeaders() 449 h.userAgent = append(h.userAgent[:0], userAgent...) 450} 451 452// SetUserAgentBytes sets User-Agent header value. 453func (h *RequestHeader) SetUserAgentBytes(userAgent []byte) { 454 h.parseRawHeaders() 455 h.userAgent = append(h.userAgent[:0], userAgent...) 456} 457 458// Referer returns Referer header value. 459func (h *RequestHeader) Referer() []byte { 460 return h.PeekBytes(strReferer) 461} 462 463// SetReferer sets Referer header value. 464func (h *RequestHeader) SetReferer(referer string) { 465 h.SetBytesK(strReferer, referer) 466} 467 468// SetRefererBytes sets Referer header value. 469func (h *RequestHeader) SetRefererBytes(referer []byte) { 470 h.SetCanonical(strReferer, referer) 471} 472 473// Method returns HTTP request method. 474func (h *RequestHeader) Method() []byte { 475 if len(h.method) == 0 { 476 return strGet 477 } 478 return h.method 479} 480 481// SetMethod sets HTTP request method. 482func (h *RequestHeader) SetMethod(method string) { 483 h.method = append(h.method[:0], method...) 484} 485 486// SetMethodBytes sets HTTP request method. 487func (h *RequestHeader) SetMethodBytes(method []byte) { 488 h.method = append(h.method[:0], method...) 489} 490 491// RequestURI returns RequestURI from the first HTTP request line. 492func (h *RequestHeader) RequestURI() []byte { 493 requestURI := h.requestURI 494 if len(requestURI) == 0 { 495 requestURI = strSlash 496 } 497 return requestURI 498} 499 500// SetRequestURI sets RequestURI for the first HTTP request line. 501// RequestURI must be properly encoded. 502// Use URI.RequestURI for constructing proper RequestURI if unsure. 503func (h *RequestHeader) SetRequestURI(requestURI string) { 504 h.requestURI = append(h.requestURI[:0], requestURI...) 505} 506 507// SetRequestURIBytes sets RequestURI for the first HTTP request line. 508// RequestURI must be properly encoded. 509// Use URI.RequestURI for constructing proper RequestURI if unsure. 510func (h *RequestHeader) SetRequestURIBytes(requestURI []byte) { 511 h.requestURI = append(h.requestURI[:0], requestURI...) 512} 513 514// IsGet returns true if request method is GET. 515func (h *RequestHeader) IsGet() bool { 516 return bytes.Equal(h.Method(), strGet) 517} 518 519// IsPost returns true if request method is POST. 520func (h *RequestHeader) IsPost() bool { 521 return bytes.Equal(h.Method(), strPost) 522} 523 524// IsPut returns true if request method is PUT. 525func (h *RequestHeader) IsPut() bool { 526 return bytes.Equal(h.Method(), strPut) 527} 528 529// IsHead returns true if request method is HEAD. 530func (h *RequestHeader) IsHead() bool { 531 return bytes.Equal(h.Method(), strHead) 532} 533 534// IsDelete returns true if request method is DELETE. 535func (h *RequestHeader) IsDelete() bool { 536 return bytes.Equal(h.Method(), strDelete) 537} 538 539// IsConnect returns true if request method is CONNECT. 540func (h *RequestHeader) IsConnect() bool { 541 return bytes.Equal(h.Method(), strConnect) 542} 543 544// IsOptions returns true if request method is OPTIONS. 545func (h *RequestHeader) IsOptions() bool { 546 return bytes.Equal(h.Method(), strOptions) 547} 548 549// IsTrace returns true if request method is TRACE. 550func (h *RequestHeader) IsTrace() bool { 551 return bytes.Equal(h.Method(), strTrace) 552} 553 554// IsPatch returns true if request method is PATCH. 555func (h *RequestHeader) IsPatch() bool { 556 return bytes.Equal(h.Method(), strPatch) 557} 558 559// IsHTTP11 returns true if the request is HTTP/1.1. 560func (h *RequestHeader) IsHTTP11() bool { 561 return !h.noHTTP11 562} 563 564// IsHTTP11 returns true if the response is HTTP/1.1. 565func (h *ResponseHeader) IsHTTP11() bool { 566 return !h.noHTTP11 567} 568 569// HasAcceptEncoding returns true if the header contains 570// the given Accept-Encoding value. 571func (h *RequestHeader) HasAcceptEncoding(acceptEncoding string) bool { 572 h.bufKV.value = append(h.bufKV.value[:0], acceptEncoding...) 573 return h.HasAcceptEncodingBytes(h.bufKV.value) 574} 575 576// HasAcceptEncodingBytes returns true if the header contains 577// the given Accept-Encoding value. 578func (h *RequestHeader) HasAcceptEncodingBytes(acceptEncoding []byte) bool { 579 ae := h.peek(strAcceptEncoding) 580 n := bytes.Index(ae, acceptEncoding) 581 if n < 0 { 582 return false 583 } 584 b := ae[n+len(acceptEncoding):] 585 if len(b) > 0 && b[0] != ',' { 586 return false 587 } 588 if n == 0 { 589 return true 590 } 591 return ae[n-1] == ' ' 592} 593 594// Len returns the number of headers set, 595// i.e. the number of times f is called in VisitAll. 596func (h *ResponseHeader) Len() int { 597 n := 0 598 h.VisitAll(func(k, v []byte) { n++ }) 599 return n 600} 601 602// Len returns the number of headers set, 603// i.e. the number of times f is called in VisitAll. 604func (h *RequestHeader) Len() int { 605 n := 0 606 h.VisitAll(func(k, v []byte) { n++ }) 607 return n 608} 609 610// DisableNormalizing disables header names' normalization. 611// 612// By default all the header names are normalized by uppercasing 613// the first letter and all the first letters following dashes, 614// while lowercasing all the other letters. 615// Examples: 616// 617// * CONNECTION -> Connection 618// * conteNT-tYPE -> Content-Type 619// * foo-bar-baz -> Foo-Bar-Baz 620// 621// Disable header names' normalization only if know what are you doing. 622func (h *RequestHeader) DisableNormalizing() { 623 h.disableNormalizing = true 624} 625 626// DisableNormalizing disables header names' normalization. 627// 628// By default all the header names are normalized by uppercasing 629// the first letter and all the first letters following dashes, 630// while lowercasing all the other letters. 631// Examples: 632// 633// * CONNECTION -> Connection 634// * conteNT-tYPE -> Content-Type 635// * foo-bar-baz -> Foo-Bar-Baz 636// 637// Disable header names' normalization only if know what are you doing. 638func (h *ResponseHeader) DisableNormalizing() { 639 h.disableNormalizing = true 640} 641 642// Reset clears response header. 643func (h *ResponseHeader) Reset() { 644 h.disableNormalizing = false 645 h.noDefaultContentType = false 646 h.resetSkipNormalize() 647} 648 649func (h *ResponseHeader) resetSkipNormalize() { 650 h.noHTTP11 = false 651 h.connectionClose = false 652 653 h.statusCode = 0 654 h.contentLength = 0 655 h.contentLengthBytes = h.contentLengthBytes[:0] 656 657 h.contentType = h.contentType[:0] 658 h.server = h.server[:0] 659 660 h.h = h.h[:0] 661 h.cookies = h.cookies[:0] 662} 663 664// Reset clears request header. 665func (h *RequestHeader) Reset() { 666 h.disableNormalizing = false 667 h.resetSkipNormalize() 668} 669 670func (h *RequestHeader) resetSkipNormalize() { 671 h.noHTTP11 = false 672 h.connectionClose = false 673 674 h.contentLength = 0 675 h.contentLengthBytes = h.contentLengthBytes[:0] 676 677 h.method = h.method[:0] 678 h.requestURI = h.requestURI[:0] 679 h.host = h.host[:0] 680 h.contentType = h.contentType[:0] 681 h.userAgent = h.userAgent[:0] 682 683 h.h = h.h[:0] 684 h.cookies = h.cookies[:0] 685 h.cookiesCollected = false 686 687 h.rawHeaders = h.rawHeaders[:0] 688 h.rawHeadersParsed = false 689} 690 691// CopyTo copies all the headers to dst. 692func (h *ResponseHeader) CopyTo(dst *ResponseHeader) { 693 dst.Reset() 694 695 dst.disableNormalizing = h.disableNormalizing 696 dst.noHTTP11 = h.noHTTP11 697 dst.connectionClose = h.connectionClose 698 dst.noDefaultContentType = h.noDefaultContentType 699 700 dst.statusCode = h.statusCode 701 dst.contentLength = h.contentLength 702 dst.contentLengthBytes = append(dst.contentLengthBytes[:0], h.contentLengthBytes...) 703 dst.contentType = append(dst.contentType[:0], h.contentType...) 704 dst.server = append(dst.server[:0], h.server...) 705 dst.h = copyArgs(dst.h, h.h) 706 dst.cookies = copyArgs(dst.cookies, h.cookies) 707} 708 709// CopyTo copies all the headers to dst. 710func (h *RequestHeader) CopyTo(dst *RequestHeader) { 711 dst.Reset() 712 713 dst.disableNormalizing = h.disableNormalizing 714 dst.noHTTP11 = h.noHTTP11 715 dst.connectionClose = h.connectionClose 716 717 dst.contentLength = h.contentLength 718 dst.contentLengthBytes = append(dst.contentLengthBytes[:0], h.contentLengthBytes...) 719 dst.method = append(dst.method[:0], h.method...) 720 dst.requestURI = append(dst.requestURI[:0], h.requestURI...) 721 dst.host = append(dst.host[:0], h.host...) 722 dst.contentType = append(dst.contentType[:0], h.contentType...) 723 dst.userAgent = append(dst.userAgent[:0], h.userAgent...) 724 dst.h = copyArgs(dst.h, h.h) 725 dst.cookies = copyArgs(dst.cookies, h.cookies) 726 dst.cookiesCollected = h.cookiesCollected 727 dst.rawHeaders = append(dst.rawHeaders[:0], h.rawHeaders...) 728 dst.rawHeadersParsed = h.rawHeadersParsed 729 dst.rawHeadersCopy = append(dst.rawHeadersCopy[:0], h.rawHeadersCopy...) 730} 731 732// VisitAll calls f for each header. 733// 734// f must not retain references to key and/or value after returning. 735// Copy key and/or value contents before returning if you need retaining them. 736func (h *ResponseHeader) VisitAll(f func(key, value []byte)) { 737 if len(h.contentLengthBytes) > 0 { 738 f(strContentLength, h.contentLengthBytes) 739 } 740 contentType := h.ContentType() 741 if len(contentType) > 0 { 742 f(strContentType, contentType) 743 } 744 server := h.Server() 745 if len(server) > 0 { 746 f(strServer, server) 747 } 748 if len(h.cookies) > 0 { 749 visitArgs(h.cookies, func(k, v []byte) { 750 f(strSetCookie, v) 751 }) 752 } 753 visitArgs(h.h, f) 754 if h.ConnectionClose() { 755 f(strConnection, strClose) 756 } 757} 758 759// VisitAllCookie calls f for each response cookie. 760// 761// Cookie name is passed in key and the whole Set-Cookie header value 762// is passed in value on each f invocation. Value may be parsed 763// with Cookie.ParseBytes(). 764// 765// f must not retain references to key and/or value after returning. 766func (h *ResponseHeader) VisitAllCookie(f func(key, value []byte)) { 767 visitArgs(h.cookies, f) 768} 769 770// VisitAllCookie calls f for each request cookie. 771// 772// f must not retain references to key and/or value after returning. 773func (h *RequestHeader) VisitAllCookie(f func(key, value []byte)) { 774 h.parseRawHeaders() 775 h.collectCookies() 776 visitArgs(h.cookies, f) 777} 778 779// VisitAll calls f for each header. 780// 781// f must not retain references to key and/or value after returning. 782// Copy key and/or value contents before returning if you need retaining them. 783// 784// To get the headers in order they were received use VisitAllInOrder. 785func (h *RequestHeader) VisitAll(f func(key, value []byte)) { 786 h.parseRawHeaders() 787 host := h.Host() 788 if len(host) > 0 { 789 f(strHost, host) 790 } 791 if len(h.contentLengthBytes) > 0 { 792 f(strContentLength, h.contentLengthBytes) 793 } 794 contentType := h.ContentType() 795 if len(contentType) > 0 { 796 f(strContentType, contentType) 797 } 798 userAgent := h.UserAgent() 799 if len(userAgent) > 0 { 800 f(strUserAgent, userAgent) 801 } 802 803 h.collectCookies() 804 if len(h.cookies) > 0 { 805 h.bufKV.value = appendRequestCookieBytes(h.bufKV.value[:0], h.cookies) 806 f(strCookie, h.bufKV.value) 807 } 808 visitArgs(h.h, f) 809 if h.ConnectionClose() { 810 f(strConnection, strClose) 811 } 812} 813 814// VisitAllInOrder calls f for each header in the order they were received. 815// 816// f must not retain references to key and/or value after returning. 817// Copy key and/or value contents before returning if you need retaining them. 818// 819// This function is slightly slower than VisitAll because it has to reparse the 820// raw headers to get the order. 821func (h *RequestHeader) VisitAllInOrder(f func(key, value []byte)) { 822 h.parseRawHeaders() 823 var s headerScanner 824 s.b = h.rawHeaders 825 s.disableNormalizing = h.disableNormalizing 826 for s.next() { 827 if len(s.key) > 0 { 828 f(s.key, s.value) 829 } 830 } 831} 832 833// Del deletes header with the given key. 834func (h *ResponseHeader) Del(key string) { 835 k := getHeaderKeyBytes(&h.bufKV, key, h.disableNormalizing) 836 h.del(k) 837} 838 839// DelBytes deletes header with the given key. 840func (h *ResponseHeader) DelBytes(key []byte) { 841 h.bufKV.key = append(h.bufKV.key[:0], key...) 842 normalizeHeaderKey(h.bufKV.key, h.disableNormalizing) 843 h.del(h.bufKV.key) 844} 845 846func (h *ResponseHeader) del(key []byte) { 847 switch string(key) { 848 case "Content-Type": 849 h.contentType = h.contentType[:0] 850 case "Server": 851 h.server = h.server[:0] 852 case "Set-Cookie": 853 h.cookies = h.cookies[:0] 854 case "Content-Length": 855 h.contentLength = 0 856 h.contentLengthBytes = h.contentLengthBytes[:0] 857 case "Connection": 858 h.connectionClose = false 859 } 860 h.h = delAllArgsBytes(h.h, key) 861} 862 863// Del deletes header with the given key. 864func (h *RequestHeader) Del(key string) { 865 h.parseRawHeaders() 866 k := getHeaderKeyBytes(&h.bufKV, key, h.disableNormalizing) 867 h.del(k) 868} 869 870// DelBytes deletes header with the given key. 871func (h *RequestHeader) DelBytes(key []byte) { 872 h.parseRawHeaders() 873 h.bufKV.key = append(h.bufKV.key[:0], key...) 874 normalizeHeaderKey(h.bufKV.key, h.disableNormalizing) 875 h.del(h.bufKV.key) 876} 877 878func (h *RequestHeader) del(key []byte) { 879 switch string(key) { 880 case "Host": 881 h.host = h.host[:0] 882 case "Content-Type": 883 h.contentType = h.contentType[:0] 884 case "User-Agent": 885 h.userAgent = h.userAgent[:0] 886 case "Cookie": 887 h.cookies = h.cookies[:0] 888 case "Content-Length": 889 h.contentLength = 0 890 h.contentLengthBytes = h.contentLengthBytes[:0] 891 case "Connection": 892 h.connectionClose = false 893 } 894 h.h = delAllArgsBytes(h.h, key) 895} 896 897// Add adds the given 'key: value' header. 898// 899// Multiple headers with the same key may be added with this function. 900// Use Set for setting a single header for the given key. 901func (h *ResponseHeader) Add(key, value string) { 902 k := getHeaderKeyBytes(&h.bufKV, key, h.disableNormalizing) 903 h.h = appendArg(h.h, b2s(k), value, argsHasValue) 904} 905 906// AddBytesK adds the given 'key: value' header. 907// 908// Multiple headers with the same key may be added with this function. 909// Use SetBytesK for setting a single header for the given key. 910func (h *ResponseHeader) AddBytesK(key []byte, value string) { 911 h.Add(b2s(key), value) 912} 913 914// AddBytesV adds the given 'key: value' header. 915// 916// Multiple headers with the same key may be added with this function. 917// Use SetBytesV for setting a single header for the given key. 918func (h *ResponseHeader) AddBytesV(key string, value []byte) { 919 h.Add(key, b2s(value)) 920} 921 922// AddBytesKV adds the given 'key: value' header. 923// 924// Multiple headers with the same key may be added with this function. 925// Use SetBytesKV for setting a single header for the given key. 926func (h *ResponseHeader) AddBytesKV(key, value []byte) { 927 h.Add(b2s(key), b2s(value)) 928} 929 930// Set sets the given 'key: value' header. 931// 932// Use Add for setting multiple header values under the same key. 933func (h *ResponseHeader) Set(key, value string) { 934 initHeaderKV(&h.bufKV, key, value, h.disableNormalizing) 935 h.SetCanonical(h.bufKV.key, h.bufKV.value) 936} 937 938// SetBytesK sets the given 'key: value' header. 939// 940// Use AddBytesK for setting multiple header values under the same key. 941func (h *ResponseHeader) SetBytesK(key []byte, value string) { 942 h.bufKV.value = append(h.bufKV.value[:0], value...) 943 h.SetBytesKV(key, h.bufKV.value) 944} 945 946// SetBytesV sets the given 'key: value' header. 947// 948// Use AddBytesV for setting multiple header values under the same key. 949func (h *ResponseHeader) SetBytesV(key string, value []byte) { 950 k := getHeaderKeyBytes(&h.bufKV, key, h.disableNormalizing) 951 h.SetCanonical(k, value) 952} 953 954// SetBytesKV sets the given 'key: value' header. 955// 956// Use AddBytesKV for setting multiple header values under the same key. 957func (h *ResponseHeader) SetBytesKV(key, value []byte) { 958 h.bufKV.key = append(h.bufKV.key[:0], key...) 959 normalizeHeaderKey(h.bufKV.key, h.disableNormalizing) 960 h.SetCanonical(h.bufKV.key, value) 961} 962 963// SetCanonical sets the given 'key: value' header assuming that 964// key is in canonical form. 965func (h *ResponseHeader) SetCanonical(key, value []byte) { 966 switch string(key) { 967 case "Content-Type": 968 h.SetContentTypeBytes(value) 969 case "Server": 970 h.SetServerBytes(value) 971 case "Set-Cookie": 972 var kv *argsKV 973 h.cookies, kv = allocArg(h.cookies) 974 kv.key = getCookieKey(kv.key, value) 975 kv.value = append(kv.value[:0], value...) 976 case "Content-Length": 977 if contentLength, err := parseContentLength(value); err == nil { 978 h.contentLength = contentLength 979 h.contentLengthBytes = append(h.contentLengthBytes[:0], value...) 980 } 981 case "Connection": 982 if bytes.Equal(strClose, value) { 983 h.SetConnectionClose() 984 } else { 985 h.ResetConnectionClose() 986 h.h = setArgBytes(h.h, key, value, argsHasValue) 987 } 988 case "Transfer-Encoding": 989 // Transfer-Encoding is managed automatically. 990 case "Date": 991 // Date is managed automatically. 992 default: 993 h.h = setArgBytes(h.h, key, value, argsHasValue) 994 } 995} 996 997// SetCookie sets the given response cookie. 998// 999// It is save re-using the cookie after the function returns. 1000func (h *ResponseHeader) SetCookie(cookie *Cookie) { 1001 h.cookies = setArgBytes(h.cookies, cookie.Key(), cookie.Cookie(), argsHasValue) 1002} 1003 1004// SetCookie sets 'key: value' cookies. 1005func (h *RequestHeader) SetCookie(key, value string) { 1006 h.parseRawHeaders() 1007 h.collectCookies() 1008 h.cookies = setArg(h.cookies, key, value, argsHasValue) 1009} 1010 1011// SetCookieBytesK sets 'key: value' cookies. 1012func (h *RequestHeader) SetCookieBytesK(key []byte, value string) { 1013 h.SetCookie(b2s(key), value) 1014} 1015 1016// SetCookieBytesKV sets 'key: value' cookies. 1017func (h *RequestHeader) SetCookieBytesKV(key, value []byte) { 1018 h.SetCookie(b2s(key), b2s(value)) 1019} 1020 1021// DelClientCookie instructs the client to remove the given cookie. 1022// 1023// Use DelCookie if you want just removing the cookie from response header. 1024func (h *ResponseHeader) DelClientCookie(key string) { 1025 h.DelCookie(key) 1026 1027 c := AcquireCookie() 1028 c.SetKey(key) 1029 c.SetExpire(CookieExpireDelete) 1030 h.SetCookie(c) 1031 ReleaseCookie(c) 1032} 1033 1034// DelClientCookieBytes instructs the client to remove the given cookie. 1035// 1036// Use DelCookieBytes if you want just removing the cookie from response header. 1037func (h *ResponseHeader) DelClientCookieBytes(key []byte) { 1038 h.DelClientCookie(b2s(key)) 1039} 1040 1041// DelCookie removes cookie under the given key from response header. 1042// 1043// Note that DelCookie doesn't remove the cookie from the client. 1044// Use DelClientCookie instead. 1045func (h *ResponseHeader) DelCookie(key string) { 1046 h.cookies = delAllArgs(h.cookies, key) 1047} 1048 1049// DelCookieBytes removes cookie under the given key from response header. 1050// 1051// Note that DelCookieBytes doesn't remove the cookie from the client. 1052// Use DelClientCookieBytes instead. 1053func (h *ResponseHeader) DelCookieBytes(key []byte) { 1054 h.DelCookie(b2s(key)) 1055} 1056 1057// DelCookie removes cookie under the given key. 1058func (h *RequestHeader) DelCookie(key string) { 1059 h.parseRawHeaders() 1060 h.collectCookies() 1061 h.cookies = delAllArgs(h.cookies, key) 1062} 1063 1064// DelCookieBytes removes cookie under the given key. 1065func (h *RequestHeader) DelCookieBytes(key []byte) { 1066 h.DelCookie(b2s(key)) 1067} 1068 1069// DelAllCookies removes all the cookies from response headers. 1070func (h *ResponseHeader) DelAllCookies() { 1071 h.cookies = h.cookies[:0] 1072} 1073 1074// DelAllCookies removes all the cookies from request headers. 1075func (h *RequestHeader) DelAllCookies() { 1076 h.parseRawHeaders() 1077 h.collectCookies() 1078 h.cookies = h.cookies[:0] 1079} 1080 1081// Add adds the given 'key: value' header. 1082// 1083// Multiple headers with the same key may be added with this function. 1084// Use Set for setting a single header for the given key. 1085func (h *RequestHeader) Add(key, value string) { 1086 k := getHeaderKeyBytes(&h.bufKV, key, h.disableNormalizing) 1087 h.h = appendArg(h.h, b2s(k), value, argsHasValue) 1088} 1089 1090// AddBytesK adds the given 'key: value' header. 1091// 1092// Multiple headers with the same key may be added with this function. 1093// Use SetBytesK for setting a single header for the given key. 1094func (h *RequestHeader) AddBytesK(key []byte, value string) { 1095 h.Add(b2s(key), value) 1096} 1097 1098// AddBytesV adds the given 'key: value' header. 1099// 1100// Multiple headers with the same key may be added with this function. 1101// Use SetBytesV for setting a single header for the given key. 1102func (h *RequestHeader) AddBytesV(key string, value []byte) { 1103 h.Add(key, b2s(value)) 1104} 1105 1106// AddBytesKV adds the given 'key: value' header. 1107// 1108// Multiple headers with the same key may be added with this function. 1109// Use SetBytesKV for setting a single header for the given key. 1110func (h *RequestHeader) AddBytesKV(key, value []byte) { 1111 h.Add(b2s(key), b2s(value)) 1112} 1113 1114// Set sets the given 'key: value' header. 1115// 1116// Use Add for setting multiple header values under the same key. 1117func (h *RequestHeader) Set(key, value string) { 1118 initHeaderKV(&h.bufKV, key, value, h.disableNormalizing) 1119 h.SetCanonical(h.bufKV.key, h.bufKV.value) 1120} 1121 1122// SetBytesK sets the given 'key: value' header. 1123// 1124// Use AddBytesK for setting multiple header values under the same key. 1125func (h *RequestHeader) SetBytesK(key []byte, value string) { 1126 h.bufKV.value = append(h.bufKV.value[:0], value...) 1127 h.SetBytesKV(key, h.bufKV.value) 1128} 1129 1130// SetBytesV sets the given 'key: value' header. 1131// 1132// Use AddBytesV for setting multiple header values under the same key. 1133func (h *RequestHeader) SetBytesV(key string, value []byte) { 1134 k := getHeaderKeyBytes(&h.bufKV, key, h.disableNormalizing) 1135 h.SetCanonical(k, value) 1136} 1137 1138// SetBytesKV sets the given 'key: value' header. 1139// 1140// Use AddBytesKV for setting multiple header values under the same key. 1141func (h *RequestHeader) SetBytesKV(key, value []byte) { 1142 h.bufKV.key = append(h.bufKV.key[:0], key...) 1143 normalizeHeaderKey(h.bufKV.key, h.disableNormalizing) 1144 h.SetCanonical(h.bufKV.key, value) 1145} 1146 1147// SetCanonical sets the given 'key: value' header assuming that 1148// key is in canonical form. 1149func (h *RequestHeader) SetCanonical(key, value []byte) { 1150 h.parseRawHeaders() 1151 switch string(key) { 1152 case "Host": 1153 h.SetHostBytes(value) 1154 case "Content-Type": 1155 h.SetContentTypeBytes(value) 1156 case "User-Agent": 1157 h.SetUserAgentBytes(value) 1158 case "Cookie": 1159 h.collectCookies() 1160 h.cookies = parseRequestCookies(h.cookies, value) 1161 case "Content-Length": 1162 if contentLength, err := parseContentLength(value); err == nil { 1163 h.contentLength = contentLength 1164 h.contentLengthBytes = append(h.contentLengthBytes[:0], value...) 1165 } 1166 case "Connection": 1167 if bytes.Equal(strClose, value) { 1168 h.SetConnectionClose() 1169 } else { 1170 h.ResetConnectionClose() 1171 h.h = setArgBytes(h.h, key, value, argsHasValue) 1172 } 1173 case "Transfer-Encoding": 1174 // Transfer-Encoding is managed automatically. 1175 default: 1176 h.h = setArgBytes(h.h, key, value, argsHasValue) 1177 } 1178} 1179 1180// Peek returns header value for the given key. 1181// 1182// Returned value is valid until the next call to ResponseHeader. 1183// Do not store references to returned value. Make copies instead. 1184func (h *ResponseHeader) Peek(key string) []byte { 1185 k := getHeaderKeyBytes(&h.bufKV, key, h.disableNormalizing) 1186 return h.peek(k) 1187} 1188 1189// PeekBytes returns header value for the given key. 1190// 1191// Returned value is valid until the next call to ResponseHeader. 1192// Do not store references to returned value. Make copies instead. 1193func (h *ResponseHeader) PeekBytes(key []byte) []byte { 1194 h.bufKV.key = append(h.bufKV.key[:0], key...) 1195 normalizeHeaderKey(h.bufKV.key, h.disableNormalizing) 1196 return h.peek(h.bufKV.key) 1197} 1198 1199// Peek returns header value for the given key. 1200// 1201// Returned value is valid until the next call to RequestHeader. 1202// Do not store references to returned value. Make copies instead. 1203func (h *RequestHeader) Peek(key string) []byte { 1204 k := getHeaderKeyBytes(&h.bufKV, key, h.disableNormalizing) 1205 return h.peek(k) 1206} 1207 1208// PeekBytes returns header value for the given key. 1209// 1210// Returned value is valid until the next call to RequestHeader. 1211// Do not store references to returned value. Make copies instead. 1212func (h *RequestHeader) PeekBytes(key []byte) []byte { 1213 h.bufKV.key = append(h.bufKV.key[:0], key...) 1214 normalizeHeaderKey(h.bufKV.key, h.disableNormalizing) 1215 return h.peek(h.bufKV.key) 1216} 1217 1218func (h *ResponseHeader) peek(key []byte) []byte { 1219 switch string(key) { 1220 case "Content-Type": 1221 return h.ContentType() 1222 case "Server": 1223 return h.Server() 1224 case "Connection": 1225 if h.ConnectionClose() { 1226 return strClose 1227 } 1228 return peekArgBytes(h.h, key) 1229 case "Content-Length": 1230 return h.contentLengthBytes 1231 case "Set-Cookie": 1232 return appendResponseCookieBytes(nil, h.cookies) 1233 default: 1234 return peekArgBytes(h.h, key) 1235 } 1236} 1237 1238func (h *RequestHeader) peek(key []byte) []byte { 1239 h.parseRawHeaders() 1240 switch string(key) { 1241 case "Host": 1242 return h.Host() 1243 case "Content-Type": 1244 return h.ContentType() 1245 case "User-Agent": 1246 return h.UserAgent() 1247 case "Connection": 1248 if h.ConnectionClose() { 1249 return strClose 1250 } 1251 return peekArgBytes(h.h, key) 1252 case "Content-Length": 1253 return h.contentLengthBytes 1254 case "Cookie": 1255 if h.cookiesCollected { 1256 return appendRequestCookieBytes(nil, h.cookies) 1257 } else { 1258 return peekArgBytes(h.h, key) 1259 } 1260 default: 1261 return peekArgBytes(h.h, key) 1262 } 1263} 1264 1265// Cookie returns cookie for the given key. 1266func (h *RequestHeader) Cookie(key string) []byte { 1267 h.parseRawHeaders() 1268 h.collectCookies() 1269 return peekArgStr(h.cookies, key) 1270} 1271 1272// CookieBytes returns cookie for the given key. 1273func (h *RequestHeader) CookieBytes(key []byte) []byte { 1274 h.parseRawHeaders() 1275 h.collectCookies() 1276 return peekArgBytes(h.cookies, key) 1277} 1278 1279// Cookie fills cookie for the given cookie.Key. 1280// 1281// Returns false if cookie with the given cookie.Key is missing. 1282func (h *ResponseHeader) Cookie(cookie *Cookie) bool { 1283 v := peekArgBytes(h.cookies, cookie.Key()) 1284 if v == nil { 1285 return false 1286 } 1287 cookie.ParseBytes(v) 1288 return true 1289} 1290 1291// Read reads response header from r. 1292// 1293// io.EOF is returned if r is closed before reading the first header byte. 1294func (h *ResponseHeader) Read(r *bufio.Reader) error { 1295 n := 1 1296 for { 1297 err := h.tryRead(r, n) 1298 if err == nil { 1299 return nil 1300 } 1301 if err != errNeedMore { 1302 h.resetSkipNormalize() 1303 return err 1304 } 1305 n = r.Buffered() + 1 1306 } 1307} 1308 1309func (h *ResponseHeader) tryRead(r *bufio.Reader, n int) error { 1310 h.resetSkipNormalize() 1311 b, err := r.Peek(n) 1312 if len(b) == 0 { 1313 // treat all errors on the first byte read as EOF 1314 if n == 1 || err == io.EOF { 1315 return io.EOF 1316 } 1317 1318 // This is for go 1.6 bug. See https://github.com/golang/go/issues/14121 . 1319 if err == bufio.ErrBufferFull { 1320 return &ErrSmallBuffer{ 1321 error: fmt.Errorf("error when reading response headers: %s", errSmallBuffer), 1322 } 1323 } 1324 1325 return fmt.Errorf("error when reading response headers: %s", err) 1326 } 1327 b = mustPeekBuffered(r) 1328 headersLen, errParse := h.parse(b) 1329 if errParse != nil { 1330 return headerError("response", err, errParse, b) 1331 } 1332 mustDiscard(r, headersLen) 1333 return nil 1334} 1335 1336func headerError(typ string, err, errParse error, b []byte) error { 1337 if errParse != errNeedMore { 1338 return headerErrorMsg(typ, errParse, b) 1339 } 1340 if err == nil { 1341 return errNeedMore 1342 } 1343 1344 // Buggy servers may leave trailing CRLFs after http body. 1345 // Treat this case as EOF. 1346 if isOnlyCRLF(b) { 1347 return io.EOF 1348 } 1349 1350 if err != bufio.ErrBufferFull { 1351 return headerErrorMsg(typ, err, b) 1352 } 1353 return &ErrSmallBuffer{ 1354 error: headerErrorMsg(typ, errSmallBuffer, b), 1355 } 1356} 1357 1358func headerErrorMsg(typ string, err error, b []byte) error { 1359 return fmt.Errorf("error when reading %s headers: %s. Buffer size=%d, contents: %s", typ, err, len(b), bufferSnippet(b)) 1360} 1361 1362// Read reads request header from r. 1363// 1364// io.EOF is returned if r is closed before reading the first header byte. 1365func (h *RequestHeader) Read(r *bufio.Reader) error { 1366 n := 1 1367 for { 1368 err := h.tryRead(r, n) 1369 if err == nil { 1370 return nil 1371 } 1372 if err != errNeedMore { 1373 h.resetSkipNormalize() 1374 return err 1375 } 1376 n = r.Buffered() + 1 1377 } 1378} 1379 1380func (h *RequestHeader) tryRead(r *bufio.Reader, n int) error { 1381 h.resetSkipNormalize() 1382 b, err := r.Peek(n) 1383 if len(b) == 0 { 1384 if err == io.EOF { 1385 return err 1386 } 1387 1388 if err == nil { 1389 panic("bufio.Reader.Peek() returned nil, nil") 1390 } 1391 1392 // This is for go 1.6 bug. See https://github.com/golang/go/issues/14121 . 1393 if err == bufio.ErrBufferFull { 1394 return &ErrSmallBuffer{ 1395 error: fmt.Errorf("error when reading request headers: %s", errSmallBuffer), 1396 } 1397 } 1398 1399 if n == 1 { 1400 // We didn't read a single byte. 1401 return errNothingRead 1402 } 1403 1404 return fmt.Errorf("error when reading request headers: %s", err) 1405 } 1406 b = mustPeekBuffered(r) 1407 headersLen, errParse := h.parse(b) 1408 if errParse != nil { 1409 return headerError("request", err, errParse, b) 1410 } 1411 mustDiscard(r, headersLen) 1412 return nil 1413} 1414 1415func bufferSnippet(b []byte) string { 1416 n := len(b) 1417 start := 200 1418 end := n - start 1419 if start >= end { 1420 start = n 1421 end = n 1422 } 1423 bStart, bEnd := b[:start], b[end:] 1424 if len(bEnd) == 0 { 1425 return fmt.Sprintf("%q", b) 1426 } 1427 return fmt.Sprintf("%q...%q", bStart, bEnd) 1428} 1429 1430func isOnlyCRLF(b []byte) bool { 1431 for _, ch := range b { 1432 if ch != '\r' && ch != '\n' { 1433 return false 1434 } 1435 } 1436 return true 1437} 1438 1439func init() { 1440 refreshServerDate() 1441 go func() { 1442 for { 1443 time.Sleep(time.Second) 1444 refreshServerDate() 1445 } 1446 }() 1447} 1448 1449var serverDate atomic.Value 1450 1451func refreshServerDate() { 1452 b := AppendHTTPDate(nil, time.Now()) 1453 serverDate.Store(b) 1454} 1455 1456// Write writes response header to w. 1457func (h *ResponseHeader) Write(w *bufio.Writer) error { 1458 _, err := w.Write(h.Header()) 1459 return err 1460} 1461 1462// WriteTo writes response header to w. 1463// 1464// WriteTo implements io.WriterTo interface. 1465func (h *ResponseHeader) WriteTo(w io.Writer) (int64, error) { 1466 n, err := w.Write(h.Header()) 1467 return int64(n), err 1468} 1469 1470// Header returns response header representation. 1471// 1472// The returned value is valid until the next call to ResponseHeader methods. 1473func (h *ResponseHeader) Header() []byte { 1474 h.bufKV.value = h.AppendBytes(h.bufKV.value[:0]) 1475 return h.bufKV.value 1476} 1477 1478// String returns response header representation. 1479func (h *ResponseHeader) String() string { 1480 return string(h.Header()) 1481} 1482 1483// AppendBytes appends response header representation to dst and returns 1484// the extended dst. 1485func (h *ResponseHeader) AppendBytes(dst []byte) []byte { 1486 statusCode := h.StatusCode() 1487 if statusCode < 0 { 1488 statusCode = StatusOK 1489 } 1490 dst = append(dst, statusLine(statusCode)...) 1491 1492 server := h.Server() 1493 if len(server) != 0 { 1494 dst = appendHeaderLine(dst, strServer, server) 1495 } 1496 dst = appendHeaderLine(dst, strDate, serverDate.Load().([]byte)) 1497 1498 // Append Content-Type only for non-zero responses 1499 // or if it is explicitly set. 1500 // See https://github.com/valyala/fasthttp/issues/28 . 1501 if h.ContentLength() != 0 || len(h.contentType) > 0 { 1502 dst = appendHeaderLine(dst, strContentType, h.ContentType()) 1503 } 1504 1505 if len(h.contentLengthBytes) > 0 { 1506 dst = appendHeaderLine(dst, strContentLength, h.contentLengthBytes) 1507 } 1508 1509 for i, n := 0, len(h.h); i < n; i++ { 1510 kv := &h.h[i] 1511 if !bytes.Equal(kv.key, strDate) { 1512 dst = appendHeaderLine(dst, kv.key, kv.value) 1513 } 1514 } 1515 1516 n := len(h.cookies) 1517 if n > 0 { 1518 for i := 0; i < n; i++ { 1519 kv := &h.cookies[i] 1520 dst = appendHeaderLine(dst, strSetCookie, kv.value) 1521 } 1522 } 1523 1524 if h.ConnectionClose() { 1525 dst = appendHeaderLine(dst, strConnection, strClose) 1526 } 1527 1528 return append(dst, strCRLF...) 1529} 1530 1531// Write writes request header to w. 1532func (h *RequestHeader) Write(w *bufio.Writer) error { 1533 _, err := w.Write(h.Header()) 1534 return err 1535} 1536 1537// WriteTo writes request header to w. 1538// 1539// WriteTo implements io.WriterTo interface. 1540func (h *RequestHeader) WriteTo(w io.Writer) (int64, error) { 1541 n, err := w.Write(h.Header()) 1542 return int64(n), err 1543} 1544 1545// Header returns request header representation. 1546// 1547// The returned representation is valid until the next call to RequestHeader methods. 1548func (h *RequestHeader) Header() []byte { 1549 h.bufKV.value = h.AppendBytes(h.bufKV.value[:0]) 1550 return h.bufKV.value 1551} 1552 1553// RawHeaders returns raw header key/value bytes. 1554// 1555// Depending on server configuration, header keys may be normalized to 1556// capital-case in place. 1557// 1558// This copy is set aside during parsing, so empty slice is returned for all 1559// cases where parsing did not happen. Similarly, request line is not stored 1560// during parsing and can not be returned. 1561// 1562// The slice is not safe to use after the handler returns. 1563func (h *RequestHeader) RawHeaders() []byte { 1564 return h.rawHeadersCopy 1565} 1566 1567// String returns request header representation. 1568func (h *RequestHeader) String() string { 1569 return string(h.Header()) 1570} 1571 1572// AppendBytes appends request header representation to dst and returns 1573// the extended dst. 1574func (h *RequestHeader) AppendBytes(dst []byte) []byte { 1575 // there is no need in h.parseRawHeaders() here - raw headers are specially handled below. 1576 dst = append(dst, h.Method()...) 1577 dst = append(dst, ' ') 1578 dst = append(dst, h.RequestURI()...) 1579 dst = append(dst, ' ') 1580 dst = append(dst, strHTTP11...) 1581 dst = append(dst, strCRLF...) 1582 1583 if !h.rawHeadersParsed && len(h.rawHeaders) > 0 { 1584 return append(dst, h.rawHeaders...) 1585 } 1586 1587 userAgent := h.UserAgent() 1588 if len(userAgent) > 0 { 1589 dst = appendHeaderLine(dst, strUserAgent, userAgent) 1590 } 1591 1592 host := h.Host() 1593 if len(host) > 0 { 1594 dst = appendHeaderLine(dst, strHost, host) 1595 } 1596 1597 contentType := h.ContentType() 1598 if !h.ignoreBody() { 1599 if len(contentType) == 0 { 1600 contentType = strPostArgsContentType 1601 } 1602 dst = appendHeaderLine(dst, strContentType, contentType) 1603 1604 if len(h.contentLengthBytes) > 0 { 1605 dst = appendHeaderLine(dst, strContentLength, h.contentLengthBytes) 1606 } 1607 } else if len(contentType) > 0 { 1608 dst = appendHeaderLine(dst, strContentType, contentType) 1609 } 1610 1611 for i, n := 0, len(h.h); i < n; i++ { 1612 kv := &h.h[i] 1613 dst = appendHeaderLine(dst, kv.key, kv.value) 1614 } 1615 1616 // there is no need in h.collectCookies() here, since if cookies aren't collected yet, 1617 // they all are located in h.h. 1618 n := len(h.cookies) 1619 if n > 0 { 1620 dst = append(dst, strCookie...) 1621 dst = append(dst, strColonSpace...) 1622 dst = appendRequestCookieBytes(dst, h.cookies) 1623 dst = append(dst, strCRLF...) 1624 } 1625 1626 if h.ConnectionClose() { 1627 dst = appendHeaderLine(dst, strConnection, strClose) 1628 } 1629 1630 return append(dst, strCRLF...) 1631} 1632 1633func appendHeaderLine(dst, key, value []byte) []byte { 1634 dst = append(dst, key...) 1635 dst = append(dst, strColonSpace...) 1636 dst = append(dst, value...) 1637 return append(dst, strCRLF...) 1638} 1639 1640func (h *ResponseHeader) parse(buf []byte) (int, error) { 1641 m, err := h.parseFirstLine(buf) 1642 if err != nil { 1643 return 0, err 1644 } 1645 n, err := h.parseHeaders(buf[m:]) 1646 if err != nil { 1647 return 0, err 1648 } 1649 return m + n, nil 1650} 1651 1652func (h *RequestHeader) ignoreBody() bool { 1653 return h.IsGet() || h.IsHead() 1654} 1655 1656func (h *RequestHeader) parse(buf []byte) (int, error) { 1657 m, err := h.parseFirstLine(buf) 1658 if err != nil { 1659 return 0, err 1660 } 1661 1662 var n int 1663 var rawHeaders []byte 1664 rawHeaders, n, err = readRawHeaders(h.rawHeaders[:0], buf[m:]) 1665 if err != nil { 1666 return 0, err 1667 } 1668 h.rawHeadersCopy = append(h.rawHeadersCopy[:0], rawHeaders...) 1669 if !h.ignoreBody() || h.noHTTP11 { 1670 n, err = h.parseHeaders(buf[m:]) 1671 if err != nil { 1672 return 0, err 1673 } 1674 h.rawHeaders = append(h.rawHeaders[:0], buf[m:m+n]...) 1675 h.rawHeadersParsed = true 1676 } else { 1677 h.rawHeaders = rawHeaders 1678 } 1679 return m + n, nil 1680} 1681 1682func (h *ResponseHeader) parseFirstLine(buf []byte) (int, error) { 1683 bNext := buf 1684 var b []byte 1685 var err error 1686 for len(b) == 0 { 1687 if b, bNext, err = nextLine(bNext); err != nil { 1688 return 0, err 1689 } 1690 } 1691 1692 // parse protocol 1693 n := bytes.IndexByte(b, ' ') 1694 if n < 0 { 1695 return 0, fmt.Errorf("cannot find whitespace in the first line of response %q", buf) 1696 } 1697 h.noHTTP11 = !bytes.Equal(b[:n], strHTTP11) 1698 b = b[n+1:] 1699 1700 // parse status code 1701 h.statusCode, n, err = parseUintBuf(b) 1702 if err != nil { 1703 return 0, fmt.Errorf("cannot parse response status code: %s. Response %q", err, buf) 1704 } 1705 if len(b) > n && b[n] != ' ' { 1706 return 0, fmt.Errorf("unexpected char at the end of status code. Response %q", buf) 1707 } 1708 1709 return len(buf) - len(bNext), nil 1710} 1711 1712func (h *RequestHeader) parseFirstLine(buf []byte) (int, error) { 1713 bNext := buf 1714 var b []byte 1715 var err error 1716 for len(b) == 0 { 1717 if b, bNext, err = nextLine(bNext); err != nil { 1718 return 0, err 1719 } 1720 } 1721 1722 // parse method 1723 n := bytes.IndexByte(b, ' ') 1724 if n <= 0 { 1725 return 0, fmt.Errorf("cannot find http request method in %q", buf) 1726 } 1727 h.method = append(h.method[:0], b[:n]...) 1728 b = b[n+1:] 1729 1730 // parse requestURI 1731 n = bytes.LastIndexByte(b, ' ') 1732 if n < 0 { 1733 h.noHTTP11 = true 1734 n = len(b) 1735 } else if n == 0 { 1736 return 0, fmt.Errorf("requestURI cannot be empty in %q", buf) 1737 } else if !bytes.Equal(b[n+1:], strHTTP11) { 1738 h.noHTTP11 = true 1739 } 1740 h.requestURI = append(h.requestURI[:0], b[:n]...) 1741 1742 return len(buf) - len(bNext), nil 1743} 1744 1745func peekRawHeader(buf, key []byte) []byte { 1746 n := bytes.Index(buf, key) 1747 if n < 0 { 1748 return nil 1749 } 1750 if n > 0 && buf[n-1] != '\n' { 1751 return nil 1752 } 1753 n += len(key) 1754 if n >= len(buf) { 1755 return nil 1756 } 1757 if buf[n] != ':' { 1758 return nil 1759 } 1760 n++ 1761 if buf[n] != ' ' { 1762 return nil 1763 } 1764 n++ 1765 buf = buf[n:] 1766 n = bytes.IndexByte(buf, '\n') 1767 if n < 0 { 1768 return nil 1769 } 1770 if n > 0 && buf[n-1] == '\r' { 1771 n-- 1772 } 1773 return buf[:n] 1774} 1775 1776func readRawHeaders(dst, buf []byte) ([]byte, int, error) { 1777 n := bytes.IndexByte(buf, '\n') 1778 if n < 0 { 1779 return nil, 0, errNeedMore 1780 } 1781 if (n == 1 && buf[0] == '\r') || n == 0 { 1782 // empty headers 1783 return dst, n + 1, nil 1784 } 1785 1786 n++ 1787 b := buf 1788 m := n 1789 for { 1790 b = b[m:] 1791 m = bytes.IndexByte(b, '\n') 1792 if m < 0 { 1793 return nil, 0, errNeedMore 1794 } 1795 m++ 1796 n += m 1797 if (m == 2 && b[0] == '\r') || m == 1 { 1798 dst = append(dst, buf[:n]...) 1799 return dst, n, nil 1800 } 1801 } 1802} 1803 1804func (h *ResponseHeader) parseHeaders(buf []byte) (int, error) { 1805 // 'identity' content-length by default 1806 h.contentLength = -2 1807 1808 var s headerScanner 1809 s.b = buf 1810 s.disableNormalizing = h.disableNormalizing 1811 var err error 1812 var kv *argsKV 1813 for s.next() { 1814 if len(s.key) > 0 { 1815 switch s.key[0] | 0x20 { 1816 case 'c': 1817 if caseInsensitiveCompare(s.key, strContentType) { 1818 h.contentType = append(h.contentType[:0], s.value...) 1819 continue 1820 } 1821 if caseInsensitiveCompare(s.key, strContentLength) { 1822 if h.contentLength != -1 { 1823 if h.contentLength, err = parseContentLength(s.value); err != nil { 1824 h.contentLength = -2 1825 } else { 1826 h.contentLengthBytes = append(h.contentLengthBytes[:0], s.value...) 1827 } 1828 } 1829 continue 1830 } 1831 if caseInsensitiveCompare(s.key, strConnection) { 1832 if bytes.Equal(s.value, strClose) { 1833 h.connectionClose = true 1834 } else { 1835 h.connectionClose = false 1836 h.h = appendArgBytes(h.h, s.key, s.value, argsHasValue) 1837 } 1838 continue 1839 } 1840 case 's': 1841 if caseInsensitiveCompare(s.key, strServer) { 1842 h.server = append(h.server[:0], s.value...) 1843 continue 1844 } 1845 if caseInsensitiveCompare(s.key, strSetCookie) { 1846 h.cookies, kv = allocArg(h.cookies) 1847 kv.key = getCookieKey(kv.key, s.value) 1848 kv.value = append(kv.value[:0], s.value...) 1849 continue 1850 } 1851 case 't': 1852 if caseInsensitiveCompare(s.key, strTransferEncoding) { 1853 if !bytes.Equal(s.value, strIdentity) { 1854 h.contentLength = -1 1855 h.h = setArgBytes(h.h, strTransferEncoding, strChunked, argsHasValue) 1856 } 1857 continue 1858 } 1859 } 1860 h.h = appendArgBytes(h.h, s.key, s.value, argsHasValue) 1861 } 1862 } 1863 if s.err != nil { 1864 h.connectionClose = true 1865 return 0, s.err 1866 } 1867 1868 if h.contentLength < 0 { 1869 h.contentLengthBytes = h.contentLengthBytes[:0] 1870 } 1871 if h.contentLength == -2 && !h.ConnectionUpgrade() && !h.mustSkipContentLength() { 1872 h.h = setArgBytes(h.h, strTransferEncoding, strIdentity, argsHasValue) 1873 h.connectionClose = true 1874 } 1875 if h.noHTTP11 && !h.connectionClose { 1876 // close connection for non-http/1.1 response unless 'Connection: keep-alive' is set. 1877 v := peekArgBytes(h.h, strConnection) 1878 h.connectionClose = !hasHeaderValue(v, strKeepAlive) 1879 } 1880 1881 return len(buf) - len(s.b), nil 1882} 1883 1884func (h *RequestHeader) parseHeaders(buf []byte) (int, error) { 1885 h.contentLength = -2 1886 1887 var s headerScanner 1888 s.b = buf 1889 s.disableNormalizing = h.disableNormalizing 1890 var err error 1891 for s.next() { 1892 if len(s.key) > 0 { 1893 switch s.key[0] | 0x20 { 1894 case 'h': 1895 if caseInsensitiveCompare(s.key, strHost) { 1896 h.host = append(h.host[:0], s.value...) 1897 continue 1898 } 1899 case 'u': 1900 if caseInsensitiveCompare(s.key, strUserAgent) { 1901 h.userAgent = append(h.userAgent[:0], s.value...) 1902 continue 1903 } 1904 case 'c': 1905 if caseInsensitiveCompare(s.key, strContentType) { 1906 h.contentType = append(h.contentType[:0], s.value...) 1907 continue 1908 } 1909 if caseInsensitiveCompare(s.key, strContentLength) { 1910 if h.contentLength != -1 { 1911 if h.contentLength, err = parseContentLength(s.value); err != nil { 1912 h.contentLength = -2 1913 } else { 1914 h.contentLengthBytes = append(h.contentLengthBytes[:0], s.value...) 1915 } 1916 } 1917 continue 1918 } 1919 if caseInsensitiveCompare(s.key, strConnection) { 1920 if bytes.Equal(s.value, strClose) { 1921 h.connectionClose = true 1922 } else { 1923 h.connectionClose = false 1924 h.h = appendArgBytes(h.h, s.key, s.value, argsHasValue) 1925 } 1926 continue 1927 } 1928 case 't': 1929 if caseInsensitiveCompare(s.key, strTransferEncoding) { 1930 if !bytes.Equal(s.value, strIdentity) { 1931 h.contentLength = -1 1932 h.h = setArgBytes(h.h, strTransferEncoding, strChunked, argsHasValue) 1933 } 1934 continue 1935 } 1936 } 1937 } 1938 h.h = appendArgBytes(h.h, s.key, s.value, argsHasValue) 1939 } 1940 if s.err != nil { 1941 h.connectionClose = true 1942 return 0, s.err 1943 } 1944 1945 if h.contentLength < 0 { 1946 h.contentLengthBytes = h.contentLengthBytes[:0] 1947 } 1948 if h.noHTTP11 && !h.connectionClose { 1949 // close connection for non-http/1.1 request unless 'Connection: keep-alive' is set. 1950 v := peekArgBytes(h.h, strConnection) 1951 h.connectionClose = !hasHeaderValue(v, strKeepAlive) 1952 } 1953 return s.hLen, nil 1954} 1955 1956func (h *RequestHeader) parseRawHeaders() { 1957 if h.rawHeadersParsed { 1958 return 1959 } 1960 h.rawHeadersParsed = true 1961 if len(h.rawHeaders) == 0 { 1962 return 1963 } 1964 h.parseHeaders(h.rawHeaders) 1965} 1966 1967func (h *RequestHeader) collectCookies() { 1968 if h.cookiesCollected { 1969 return 1970 } 1971 1972 for i, n := 0, len(h.h); i < n; i++ { 1973 kv := &h.h[i] 1974 if bytes.Equal(kv.key, strCookie) { 1975 h.cookies = parseRequestCookies(h.cookies, kv.value) 1976 tmp := *kv 1977 copy(h.h[i:], h.h[i+1:]) 1978 n-- 1979 i-- 1980 h.h[n] = tmp 1981 h.h = h.h[:n] 1982 } 1983 } 1984 h.cookiesCollected = true 1985} 1986 1987func parseContentLength(b []byte) (int, error) { 1988 v, n, err := parseUintBuf(b) 1989 if err != nil { 1990 return -1, err 1991 } 1992 if n != len(b) { 1993 return -1, fmt.Errorf("non-numeric chars at the end of Content-Length") 1994 } 1995 return v, nil 1996} 1997 1998type headerScanner struct { 1999 b []byte 2000 key []byte 2001 value []byte 2002 err error 2003 2004 // hLen stores header subslice len 2005 hLen int 2006 2007 disableNormalizing bool 2008} 2009 2010func (s *headerScanner) next() bool { 2011 bLen := len(s.b) 2012 if bLen >= 2 && s.b[0] == '\r' && s.b[1] == '\n' { 2013 s.b = s.b[2:] 2014 s.hLen += 2 2015 return false 2016 } 2017 if bLen >= 1 && s.b[0] == '\n' { 2018 s.b = s.b[1:] 2019 s.hLen++ 2020 return false 2021 } 2022 n := bytes.IndexByte(s.b, ':') 2023 if n < 0 { 2024 s.err = errNeedMore 2025 return false 2026 } 2027 s.key = s.b[:n] 2028 normalizeHeaderKey(s.key, s.disableNormalizing) 2029 n++ 2030 for len(s.b) > n && s.b[n] == ' ' { 2031 n++ 2032 } 2033 s.hLen += n 2034 s.b = s.b[n:] 2035 n = bytes.IndexByte(s.b, '\n') 2036 if n < 0 { 2037 s.err = errNeedMore 2038 return false 2039 } 2040 s.value = s.b[:n] 2041 s.hLen += n + 1 2042 s.b = s.b[n+1:] 2043 2044 if n > 0 && s.value[n-1] == '\r' { 2045 n-- 2046 } 2047 for n > 0 && s.value[n-1] == ' ' { 2048 n-- 2049 } 2050 s.value = s.value[:n] 2051 return true 2052} 2053 2054type headerValueScanner struct { 2055 b []byte 2056 value []byte 2057} 2058 2059func (s *headerValueScanner) next() bool { 2060 b := s.b 2061 if len(b) == 0 { 2062 return false 2063 } 2064 n := bytes.IndexByte(b, ',') 2065 if n < 0 { 2066 s.value = stripSpace(b) 2067 s.b = b[len(b):] 2068 return true 2069 } 2070 s.value = stripSpace(b[:n]) 2071 s.b = b[n+1:] 2072 return true 2073} 2074 2075func stripSpace(b []byte) []byte { 2076 for len(b) > 0 && b[0] == ' ' { 2077 b = b[1:] 2078 } 2079 for len(b) > 0 && b[len(b)-1] == ' ' { 2080 b = b[:len(b)-1] 2081 } 2082 return b 2083} 2084 2085func hasHeaderValue(s, value []byte) bool { 2086 var vs headerValueScanner 2087 vs.b = s 2088 for vs.next() { 2089 if caseInsensitiveCompare(vs.value, value) { 2090 return true 2091 } 2092 } 2093 return false 2094} 2095 2096func nextLine(b []byte) ([]byte, []byte, error) { 2097 nNext := bytes.IndexByte(b, '\n') 2098 if nNext < 0 { 2099 return nil, nil, errNeedMore 2100 } 2101 n := nNext 2102 if n > 0 && b[n-1] == '\r' { 2103 n-- 2104 } 2105 return b[:n], b[nNext+1:], nil 2106} 2107 2108func initHeaderKV(kv *argsKV, key, value string, disableNormalizing bool) { 2109 kv.key = getHeaderKeyBytes(kv, key, disableNormalizing) 2110 kv.value = append(kv.value[:0], value...) 2111} 2112 2113func getHeaderKeyBytes(kv *argsKV, key string, disableNormalizing bool) []byte { 2114 kv.key = append(kv.key[:0], key...) 2115 normalizeHeaderKey(kv.key, disableNormalizing) 2116 return kv.key 2117} 2118 2119func normalizeHeaderKey(b []byte, disableNormalizing bool) { 2120 if disableNormalizing { 2121 return 2122 } 2123 2124 n := len(b) 2125 if n == 0 { 2126 return 2127 } 2128 2129 b[0] = toUpperTable[b[0]] 2130 for i := 1; i < n; i++ { 2131 p := &b[i] 2132 if *p == '-' { 2133 i++ 2134 if i < n { 2135 b[i] = toUpperTable[b[i]] 2136 } 2137 continue 2138 } 2139 *p = toLowerTable[*p] 2140 } 2141} 2142 2143// AppendNormalizedHeaderKey appends normalized header key (name) to dst 2144// and returns the resulting dst. 2145// 2146// Normalized header key starts with uppercase letter. The first letters 2147// after dashes are also uppercased. All the other letters are lowercased. 2148// Examples: 2149// 2150// * coNTENT-TYPe -> Content-Type 2151// * HOST -> Host 2152// * foo-bar-baz -> Foo-Bar-Baz 2153func AppendNormalizedHeaderKey(dst []byte, key string) []byte { 2154 dst = append(dst, key...) 2155 normalizeHeaderKey(dst[len(dst)-len(key):], false) 2156 return dst 2157} 2158 2159// AppendNormalizedHeaderKeyBytes appends normalized header key (name) to dst 2160// and returns the resulting dst. 2161// 2162// Normalized header key starts with uppercase letter. The first letters 2163// after dashes are also uppercased. All the other letters are lowercased. 2164// Examples: 2165// 2166// * coNTENT-TYPe -> Content-Type 2167// * HOST -> Host 2168// * foo-bar-baz -> Foo-Bar-Baz 2169func AppendNormalizedHeaderKeyBytes(dst, key []byte) []byte { 2170 return AppendNormalizedHeaderKey(dst, b2s(key)) 2171} 2172 2173var ( 2174 errNeedMore = errors.New("need more data: cannot find trailing lf") 2175 errSmallBuffer = errors.New("small read buffer. Increase ReadBufferSize") 2176 errNothingRead = errors.New("read timeout with nothing read") 2177) 2178 2179// ErrSmallBuffer is returned when the provided buffer size is too small 2180// for reading request and/or response headers. 2181// 2182// ReadBufferSize value from Server or clients should reduce the number 2183// of such errors. 2184type ErrSmallBuffer struct { 2185 error 2186} 2187 2188func mustPeekBuffered(r *bufio.Reader) []byte { 2189 buf, err := r.Peek(r.Buffered()) 2190 if len(buf) == 0 || err != nil { 2191 panic(fmt.Sprintf("bufio.Reader.Peek() returned unexpected data (%q, %v)", buf, err)) 2192 } 2193 return buf 2194} 2195 2196func mustDiscard(r *bufio.Reader, n int) { 2197 if _, err := r.Discard(n); err != nil { 2198 panic(fmt.Sprintf("bufio.Reader.Discard(%d) failed: %s", n, err)) 2199 } 2200} 2201