github.com/cloudwego/hertz@v0.9.3/pkg/protocol/header_test.go (about) 1 /* 2 * Copyright 2022 CloudWeGo Authors 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 * 16 * The MIT License (MIT) 17 * 18 * Copyright (c) 2015-present Aliaksandr Valialkin, VertaMedia, Kirill Danshin, Erik Dubbelboer, FastHTTP Authors 19 * 20 * Permission is hereby granted, free of charge, to any person obtaining a copy 21 * of this software and associated documentation files (the "Software"), to deal 22 * in the Software without restriction, including without limitation the rights 23 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 24 * copies of the Software, and to permit persons to whom the Software is 25 * furnished to do so, subject to the following conditions: 26 * 27 * The above copyright notice and this permission notice shall be included in 28 * all copies or substantial portions of the Software. 29 * 30 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 31 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 32 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 33 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 34 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 35 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 36 * THE SOFTWARE. 37 * 38 * This file may have been modified by CloudWeGo authors. All CloudWeGo 39 * Modifications are Copyright 2022 CloudWeGo Authors. 40 */ 41 42 package protocol 43 44 import ( 45 "bytes" 46 "fmt" 47 "net/http" 48 "strings" 49 "testing" 50 51 "github.com/cloudwego/hertz/internal/bytestr" 52 "github.com/cloudwego/hertz/pkg/common/hlog" 53 "github.com/cloudwego/hertz/pkg/common/test/assert" 54 "github.com/cloudwego/hertz/pkg/protocol/consts" 55 ) 56 57 func TestRequestHeaderSetRawHeaders(t *testing.T) { 58 h := RequestHeader{} 59 h.SetRawHeaders([]byte("foo")) 60 assert.DeepEqual(t, h.rawHeaders, []byte("foo")) 61 } 62 63 func TestResponseHeaderSetHeaderLength(t *testing.T) { 64 h := ResponseHeader{} 65 h.SetHeaderLength(15) 66 assert.DeepEqual(t, h.headerLength, 15) 67 assert.DeepEqual(t, h.GetHeaderLength(), 15) 68 } 69 70 func TestSetNoHTTP11(t *testing.T) { 71 rh := ResponseHeader{} 72 rh.SetProtocol(consts.HTTP10) 73 assert.DeepEqual(t, consts.HTTP10, rh.protocol) 74 75 rh.SetProtocol(consts.HTTP11) 76 assert.DeepEqual(t, consts.HTTP11, rh.protocol) 77 assert.True(t, rh.IsHTTP11()) 78 79 h := RequestHeader{} 80 h.SetProtocol(consts.HTTP10) 81 assert.DeepEqual(t, consts.HTTP10, h.protocol) 82 83 h.SetProtocol(consts.HTTP11) 84 assert.DeepEqual(t, consts.HTTP11, h.protocol) 85 assert.True(t, h.IsHTTP11()) 86 } 87 88 func TestResponseHeaderSetContentType(t *testing.T) { 89 h := ResponseHeader{} 90 h.SetContentType("foo") 91 assert.DeepEqual(t, h.contentType, []byte("foo")) 92 } 93 94 func TestSetContentLengthBytes(t *testing.T) { 95 h := RequestHeader{} 96 h.SetContentLengthBytes([]byte("foo")) 97 assert.DeepEqual(t, h.contentLengthBytes, []byte("foo")) 98 99 rh := ResponseHeader{} 100 rh.SetContentLengthBytes([]byte("foo")) 101 assert.DeepEqual(t, rh.contentLengthBytes, []byte("foo")) 102 } 103 104 func TestInitContentLengthWithValue(t *testing.T) { 105 initLength := 100 106 h := RequestHeader{} 107 h.InitContentLengthWithValue(initLength) 108 assert.DeepEqual(t, h.contentLength, initLength) 109 110 rh := ResponseHeader{} 111 rh.InitContentLengthWithValue(initLength) 112 assert.DeepEqual(t, rh.contentLength, initLength) 113 } 114 115 func TestSetContentEncoding(t *testing.T) { 116 rh := ResponseHeader{} 117 rh.SetContentEncoding("gzip") 118 assert.DeepEqual(t, rh.contentEncoding, []byte("gzip")) 119 } 120 121 func Test_peekRawHeader(t *testing.T) { 122 s := "Expect: 100-continue\r\nUser-Agent: foo\r\nHost: 127.0.0.1\r\nConnection: Keep-Alive\r\nContent-Length: 5\r\nContent-Type: foo/bar\r\n\r\nabcdef4343" 123 assert.DeepEqual(t, []byte("127.0.0.1"), peekRawHeader([]byte(s), []byte("Host"))) 124 } 125 126 func TestResponseHeader_SetContentLength(t *testing.T) { 127 rh := new(ResponseHeader) 128 rh.SetContentLength(-1) 129 assert.True(t, strings.Contains(string(rh.Header()), "Transfer-Encoding: chunked")) 130 rh.SetContentLength(-2) 131 assert.True(t, strings.Contains(string(rh.Header()), "Transfer-Encoding: identity")) 132 } 133 134 func TestResponseHeader_SetContentRange(t *testing.T) { 135 rh := new(ResponseHeader) 136 rh.SetContentRange(1, 5, 10) 137 assert.DeepEqual(t, rh.bufKV.value, []byte("bytes 1-5/10")) 138 } 139 140 func TestSetCanonical(t *testing.T) { 141 h := ResponseHeader{} 142 h.SetCanonical([]byte(consts.HeaderContentType), []byte("foo")) 143 h.SetCanonical([]byte(consts.HeaderServer), []byte("foo1")) 144 h.SetCanonical([]byte(consts.HeaderSetCookie), []byte("foo2")) 145 h.SetCanonical([]byte(consts.HeaderContentLength), []byte("3")) 146 h.SetCanonical([]byte(consts.HeaderConnection), []byte("foo4")) 147 h.SetCanonical([]byte(consts.HeaderTransferEncoding), []byte("foo5")) 148 h.SetCanonical([]byte(consts.HeaderTrailer), []byte("foo7")) 149 h.SetCanonical([]byte("bar"), []byte("foo6")) 150 151 assert.DeepEqual(t, []byte("foo"), h.ContentType()) 152 assert.DeepEqual(t, []byte("foo1"), h.Server()) 153 assert.DeepEqual(t, true, strings.Contains(string(h.Header()), "foo2")) 154 assert.DeepEqual(t, 3, h.ContentLength()) 155 assert.DeepEqual(t, false, h.ConnectionClose()) 156 assert.DeepEqual(t, false, strings.Contains(string(h.ContentType()), "foo5")) 157 assert.DeepEqual(t, true, strings.Contains(string(h.Header()), "Trailer: Foo7")) 158 assert.DeepEqual(t, true, strings.Contains(string(h.Header()), "bar: foo6")) 159 } 160 161 func TestHasAcceptEncodingBytes(t *testing.T) { 162 h := RequestHeader{} 163 h.Set(consts.HeaderAcceptEncoding, "gzip") 164 assert.True(t, h.HasAcceptEncodingBytes([]byte("gzip"))) 165 } 166 167 func TestRequestHeaderGet(t *testing.T) { 168 h := RequestHeader{} 169 rightVal := "yyy" 170 h.Set("xxx", rightVal) 171 val := h.Get("xxx") 172 if val != rightVal { 173 t.Fatalf("Unexpected %v. Expected %v", val, rightVal) 174 } 175 } 176 177 func TestResponseHeaderGet(t *testing.T) { 178 h := ResponseHeader{} 179 rightVal := "yyy" 180 h.Set("xxx", rightVal) 181 val := h.Get("xxx") 182 assert.DeepEqual(t, val, rightVal) 183 } 184 185 func TestRequestHeaderGetAll(t *testing.T) { 186 h := RequestHeader{} 187 h.Set("Foo-Bar", "foo") 188 h.Add("Foo-Bar", "bar") 189 h.Add("Foo-Bar", "foo-bar") 190 values := h.GetAll("Foo-Bar") 191 assert.DeepEqual(t, values, []string{"foo", "bar", "foo-bar"}) 192 } 193 194 func TestResponseHeaderGetAll(t *testing.T) { 195 h := ResponseHeader{} 196 h.Set("Foo-Bar", "foo") 197 h.Add("Foo-Bar", "bar") 198 h.Add("Foo-Bar", "foo-bar") 199 values := h.GetAll("Foo-Bar") 200 assert.DeepEqual(t, values, []string{"foo", "bar", "foo-bar"}) 201 } 202 203 func TestRequestHeaderVisitAll(t *testing.T) { 204 h := RequestHeader{} 205 h.Set("xxx", "yyy") 206 h.Set("xxx2", "yyy2") 207 h.SetHost("host") 208 h.SetContentLengthBytes([]byte("content-length")) 209 h.Set(consts.HeaderContentType, "content-type") 210 h.Set(consts.HeaderUserAgent, "user-agent") 211 err := h.Trailer().SetTrailers([]byte("foo, bar")) 212 if err != nil { 213 t.Fatalf("Set trailer err %v", err) 214 } 215 h.SetCookie("foo", "bar") 216 h.Set(consts.HeaderConnection, "close") 217 h.VisitAll(func(k, v []byte) { 218 key := string(k) 219 value := string(v) 220 switch key { 221 case consts.HeaderHost: 222 assert.DeepEqual(t, value, "host") 223 case consts.HeaderContentLength: 224 assert.DeepEqual(t, value, "content-length") 225 case consts.HeaderContentType: 226 assert.DeepEqual(t, value, "content-type") 227 case consts.HeaderUserAgent: 228 assert.DeepEqual(t, value, "user-agent") 229 case consts.HeaderTrailer: 230 assert.DeepEqual(t, value, "Foo, Bar") 231 case consts.HeaderCookie: 232 assert.DeepEqual(t, value, "foo=bar") 233 case consts.HeaderConnection: 234 assert.DeepEqual(t, value, "close") 235 case "Xxx": 236 assert.DeepEqual(t, value, "yyy") 237 case "Xxx2": 238 assert.DeepEqual(t, value, "yyy2") 239 default: 240 t.Fatalf("Unexpected key %v", key) 241 } 242 }) 243 } 244 245 func TestRequestHeaderCookie(t *testing.T) { 246 var h RequestHeader 247 h.SetCookie("foo", "bar") 248 cookie := h.Cookie("foo") 249 assert.DeepEqual(t, []byte("bar"), cookie) 250 } 251 252 func TestRequestHeaderCookies(t *testing.T) { 253 var h RequestHeader 254 h.SetCookie("foo", "bar") 255 h.SetCookie("привет", "мир") 256 cookies := h.Cookies() 257 assert.DeepEqual(t, 2, len(cookies)) 258 assert.DeepEqual(t, []byte("foo"), cookies[0].Key()) 259 assert.DeepEqual(t, []byte("bar"), cookies[0].Value()) 260 assert.DeepEqual(t, []byte("привет"), cookies[1].Key()) 261 assert.DeepEqual(t, []byte("мир"), cookies[1].Value()) 262 } 263 264 func TestRequestHeaderDel(t *testing.T) { 265 t.Parallel() 266 267 var h RequestHeader 268 h.Set("Foo-Bar", "baz") 269 h.Set("aaa", "bbb") 270 h.Set("ccc", "ddd") 271 h.Set(consts.HeaderConnection, "keep-alive") 272 h.Set(consts.HeaderContentType, "aaa") 273 h.Set(consts.HeaderServer, "aaabbb") 274 h.Set(consts.HeaderContentLength, "1123") 275 h.Set(consts.HeaderTrailer, "foo, bar") 276 h.Set(consts.HeaderUserAgent, "foo-bar") 277 h.SetHost("foobar") 278 h.SetCookie("foo", "bar") 279 280 h.del([]byte("Foo-Bar")) 281 h.del([]byte("Connection")) 282 h.DelBytes([]byte("Content-Type")) 283 h.del([]byte(consts.HeaderServer)) 284 h.del([]byte("Content-Length")) 285 h.del([]byte("Set-Cookie")) 286 h.del([]byte("Host")) 287 h.del([]byte(consts.HeaderTrailer)) 288 h.del([]byte(consts.HeaderUserAgent)) 289 h.DelCookie("foo") 290 h.Del("ccc") 291 292 hv := h.Peek("aaa") 293 if string(hv) != "bbb" { 294 t.Fatalf("unexpected header value: %q. Expecting %q", hv, "bbb") 295 } 296 hv = h.Peek("ccc") 297 if string(hv) != "" { 298 t.Fatalf("unexpected header value: %q. Expecting %q", hv, "") 299 } 300 hv = h.Peek("Foo-Bar") 301 if len(hv) > 0 { 302 t.Fatalf("non-zero header value: %q", hv) 303 } 304 hv = h.Peek(consts.HeaderConnection) 305 if len(hv) > 0 { 306 t.Fatalf("non-zero value: %q", hv) 307 } 308 hv = h.Peek(consts.HeaderContentType) 309 if len(hv) > 0 { 310 t.Fatalf("non-zero value: %q", hv) 311 } 312 hv = h.Peek(consts.HeaderServer) 313 if len(hv) > 0 { 314 t.Fatalf("non-zero value: %q", hv) 315 } 316 hv = h.Peek(consts.HeaderContentLength) 317 if len(hv) > 0 { 318 t.Fatalf("non-zero value: %q", hv) 319 } 320 hv = h.FullCookie() 321 if len(hv) > 0 { 322 t.Fatalf("non-zero value: %q", hv) 323 } 324 hv = h.Peek(consts.HeaderCookie) 325 if len(hv) > 0 { 326 t.Fatalf("non-zero value: %q", hv) 327 } 328 hv = h.Peek(consts.HeaderTrailer) 329 if len(hv) > 0 { 330 t.Fatalf("non-zero value: %q", hv) 331 } 332 hv = h.Peek(consts.HeaderUserAgent) 333 if len(hv) > 0 { 334 t.Fatalf("non-zero value: %q", hv) 335 } 336 if h.ContentLength() != 0 { 337 t.Fatalf("unexpected content-length: %d. Expecting 0", h.ContentLength()) 338 } 339 } 340 341 func TestResponseHeaderDel(t *testing.T) { 342 t.Parallel() 343 344 var h ResponseHeader 345 h.Set("Foo-Bar", "baz") 346 h.Set("aaa", "bbb") 347 h.Set(consts.HeaderConnection, "keep-alive") 348 h.Set(consts.HeaderContentType, "aaa") 349 h.Set(consts.HeaderContentEncoding, "gzip") 350 h.Set(consts.HeaderServer, "aaabbb") 351 h.Set(consts.HeaderContentLength, "1123") 352 h.Set(consts.HeaderTrailer, "foo, bar") 353 354 var c Cookie 355 c.SetKey("foo") 356 c.SetValue("bar") 357 h.SetCookie(&c) 358 359 h.Del("foo-bar") 360 h.Del("connection") 361 h.DelBytes([]byte("content-type")) 362 h.Del(consts.HeaderServer) 363 h.Del("content-length") 364 h.Del("set-cookie") 365 h.Del("content-encoding") 366 h.Del(consts.HeaderTrailer) 367 368 hv := h.Peek("aaa") 369 if string(hv) != "bbb" { 370 t.Fatalf("unexpected header value: %q. Expecting %q", hv, "bbb") 371 } 372 hv = h.Peek("Foo-Bar") 373 if len(hv) > 0 { 374 t.Fatalf("non-zero header value: %q", hv) 375 } 376 hv = h.Peek(consts.HeaderConnection) 377 if len(hv) > 0 { 378 t.Fatalf("non-zero value: %q", hv) 379 } 380 hv = h.Peek(consts.HeaderContentType) 381 if string(hv) != string(bytestr.DefaultContentType) { 382 t.Fatalf("unexpected content-type: %q. Expecting %q", hv, bytestr.DefaultContentType) 383 } 384 hv = h.Peek(consts.HeaderContentEncoding) 385 if len(hv) > 0 { 386 t.Fatalf("non-zero value: %q", hv) 387 } 388 hv = h.Peek(consts.HeaderServer) 389 if len(hv) > 0 { 390 t.Fatalf("non-zero value: %q", hv) 391 } 392 hv = h.Peek(consts.HeaderContentLength) 393 if len(hv) > 0 { 394 t.Fatalf("non-zero value: %q", hv) 395 } 396 397 hv = h.Peek(consts.HeaderTrailer) 398 if len(hv) > 0 { 399 t.Fatalf("non-zero value: %q", hv) 400 } 401 402 if h.Cookie(&c) { 403 t.Fatalf("unexpected cookie obtained: %v", &c) 404 } 405 406 if h.ContentLength() != 0 { 407 t.Fatalf("unexpected content-length: %d. Expecting 0", h.ContentLength()) 408 } 409 } 410 411 func TestResponseHeaderDelClientCookie(t *testing.T) { 412 t.Parallel() 413 414 cookieName := "foobar" 415 416 var h ResponseHeader 417 c := AcquireCookie() 418 c.SetKey(cookieName) 419 c.SetValue("aasdfsdaf") 420 h.SetCookie(c) 421 422 h.DelClientCookieBytes([]byte(cookieName)) 423 if !h.Cookie(c) { 424 t.Fatalf("expecting cookie %q", c.Key()) 425 } 426 if !c.Expire().Equal(CookieExpireDelete) { 427 t.Fatalf("unexpected cookie expiration time: %s. Expecting %s", c.Expire(), CookieExpireDelete) 428 } 429 if len(c.Value()) > 0 { 430 t.Fatalf("unexpected cookie value: %q. Expecting empty value", c.Value()) 431 } 432 ReleaseCookie(c) 433 } 434 435 func TestResponseHeaderResetConnectionClose(t *testing.T) { 436 h := ResponseHeader{} 437 h.Set(consts.HeaderConnection, "close") 438 hv := h.Peek(consts.HeaderConnection) 439 assert.DeepEqual(t, hv, []byte("close")) 440 h.SetConnectionClose(true) 441 h.ResetConnectionClose() 442 assert.False(t, h.connectionClose) 443 hv = h.Peek(consts.HeaderConnection) 444 if len(hv) > 0 { 445 t.Fatalf("ResetConnectionClose do not work,Connection: %q", hv) 446 } 447 } 448 449 func TestRequestHeaderResetConnectionClose(t *testing.T) { 450 h := RequestHeader{} 451 h.Set(consts.HeaderConnection, "close") 452 hv := h.Peek(consts.HeaderConnection) 453 assert.DeepEqual(t, hv, []byte("close")) 454 h.connectionClose = true 455 h.ResetConnectionClose() 456 assert.False(t, h.connectionClose) 457 hv = h.Peek(consts.HeaderConnection) 458 if len(hv) > 0 { 459 t.Fatalf("ResetConnectionClose do not work,Connection: %q", hv) 460 } 461 } 462 463 func TestCheckWriteHeaderCode(t *testing.T) { 464 buffer := bytes.NewBuffer(make([]byte, 0, 1024)) 465 hlog.SetOutput(buffer) 466 checkWriteHeaderCode(99) 467 assert.True(t, strings.Contains(buffer.String(), "[Warn] HERTZ: Invalid StatusCode code")) 468 buffer.Reset() 469 checkWriteHeaderCode(600) 470 assert.True(t, strings.Contains(buffer.String(), "[Warn] HERTZ: Invalid StatusCode code")) 471 buffer.Reset() 472 checkWriteHeaderCode(100) 473 assert.False(t, strings.Contains(buffer.String(), "[Warn] HERTZ: Invalid StatusCode code")) 474 buffer.Reset() 475 checkWriteHeaderCode(599) 476 assert.False(t, strings.Contains(buffer.String(), "[Warn] HERTZ: Invalid StatusCode code")) 477 } 478 479 func TestResponseHeaderAdd(t *testing.T) { 480 t.Parallel() 481 482 m := make(map[string]struct{}) 483 var h ResponseHeader 484 h.Add("aaa", "bbb") 485 h.Add("content-type", "xxx") 486 h.SetContentEncoding("gzip") 487 m["bbb"] = struct{}{} 488 m["xxx"] = struct{}{} 489 m["gzip"] = struct{}{} 490 for i := 0; i < 10; i++ { 491 v := fmt.Sprintf("%d", i) 492 h.Add("Foo-Bar", v) 493 m[v] = struct{}{} 494 } 495 if h.Len() != 13 { 496 t.Fatalf("unexpected header len %d. Expecting 13", h.Len()) 497 } 498 499 h.VisitAll(func(k, v []byte) { 500 switch string(k) { 501 case "Aaa", "Foo-Bar", "Content-Type", "Content-Encoding": 502 if _, ok := m[string(v)]; !ok { 503 t.Fatalf("unexpected value found %q. key %q", v, k) 504 } 505 delete(m, string(v)) 506 default: 507 t.Fatalf("unexpected key found: %q", k) 508 } 509 }) 510 if len(m) > 0 { 511 t.Fatalf("%d headers are missed", len(m)) 512 } 513 } 514 515 func TestRequestHeaderAdd(t *testing.T) { 516 t.Parallel() 517 518 m := make(map[string]struct{}) 519 var h RequestHeader 520 h.Add("aaa", "bbb") 521 h.Add("user-agent", "xxx") 522 m["bbb"] = struct{}{} 523 m["xxx"] = struct{}{} 524 for i := 0; i < 10; i++ { 525 v := fmt.Sprintf("%d", i) 526 h.Add("Foo-Bar", v) 527 m[v] = struct{}{} 528 } 529 if h.Len() != 12 { 530 t.Fatalf("unexpected header len %d. Expecting 12", h.Len()) 531 } 532 533 h.VisitAll(func(k, v []byte) { 534 switch string(k) { 535 case "Aaa", "Foo-Bar", "User-Agent": 536 if _, ok := m[string(v)]; !ok { 537 t.Fatalf("unexpected value found %q. key %q", v, k) 538 } 539 delete(m, string(v)) 540 default: 541 t.Fatalf("unexpected key found: %q", k) 542 } 543 }) 544 if len(m) > 0 { 545 t.Fatalf("%d headers are missed", len(m)) 546 } 547 } 548 549 func TestResponseHeaderAddContentType(t *testing.T) { 550 t.Parallel() 551 552 var h ResponseHeader 553 h.Add("Content-Type", "test") 554 555 got := string(h.Peek("Content-Type")) 556 expected := "test" 557 if got != expected { 558 t.Errorf("expected %q got %q", expected, got) 559 } 560 561 if n := strings.Count(string(h.Header()), "Content-Type: "); n != 1 { 562 t.Errorf("Content-Type occurred %d times", n) 563 } 564 } 565 566 func TestResponseHeaderAddContentEncoding(t *testing.T) { 567 t.Parallel() 568 569 var h ResponseHeader 570 h.Add("Content-Encoding", "test") 571 572 got := string(h.ContentEncoding()) 573 expected := "test" 574 if got != expected { 575 t.Errorf("expected %q got %q", expected, got) 576 } 577 578 if n := strings.Count(string(h.Header()), "Content-Encoding: "); n != 1 { 579 t.Errorf("Content-Encoding occurred %d times", n) 580 } 581 } 582 583 func TestRequestHeaderAddContentType(t *testing.T) { 584 t.Parallel() 585 586 var h RequestHeader 587 h.Add("Content-Type", "test") 588 589 got := string(h.Peek("Content-Type")) 590 expected := "test" 591 if got != expected { 592 t.Errorf("expected %q got %q", expected, got) 593 } 594 595 if n := strings.Count(h.String(), "Content-Type: "); n != 1 { 596 t.Errorf("Content-Type occurred %d times", n) 597 } 598 } 599 600 func TestSetMultipartFormBoundary(t *testing.T) { 601 h := RequestHeader{} 602 h.SetMultipartFormBoundary("foo") 603 assert.DeepEqual(t, h.contentType, []byte("multipart/form-data; boundary=foo")) 604 } 605 606 func TestRequestHeaderSetByteRange(t *testing.T) { 607 var h RequestHeader 608 h.SetByteRange(1, 5) 609 hv := h.Peek(consts.HeaderRange) 610 assert.DeepEqual(t, hv, []byte("bytes=1-5")) 611 } 612 613 func TestRequestHeaderSetMethodBytes(t *testing.T) { 614 var h RequestHeader 615 h.SetMethodBytes([]byte("foo")) 616 assert.DeepEqual(t, h.Method(), []byte("foo")) 617 } 618 619 func TestRequestHeaderSetBytesKV(t *testing.T) { 620 var h RequestHeader 621 h.SetBytesKV([]byte("foo"), []byte("foo1")) 622 hv := h.Peek("foo") 623 assert.DeepEqual(t, hv, []byte("foo1")) 624 } 625 626 func TestResponseHeaderSetBytesV(t *testing.T) { 627 var h ResponseHeader 628 h.SetBytesV("foo", []byte("foo1")) 629 hv := h.Peek("foo") 630 assert.DeepEqual(t, hv, []byte("foo1")) 631 } 632 633 func TestRequestHeaderInitBufValue(t *testing.T) { 634 var h RequestHeader 635 slice := make([]byte, 0, 10) 636 h.InitBufValue(10) 637 assert.DeepEqual(t, cap(h.bufKV.value), cap(slice)) 638 assert.DeepEqual(t, h.GetBufValue(), slice) 639 } 640 641 func TestRequestHeaderDelAllCookies(t *testing.T) { 642 var h RequestHeader 643 h.SetCanonical([]byte(consts.HeaderSetCookie), []byte("foo2")) 644 h.DelAllCookies() 645 hv := h.FullCookie() 646 if len(hv) > 0 { 647 t.Fatalf("non-zero value: %q", hv) 648 } 649 } 650 651 func TestResponseHeaderDelAllCookies(t *testing.T) { 652 var h ResponseHeader 653 h.SetCanonical([]byte(consts.HeaderSetCookie), []byte("foo")) 654 h.DelAllCookies() 655 hv := h.FullCookie() 656 if len(hv) > 0 { 657 t.Fatalf("non-zero value: %q", hv) 658 } 659 } 660 661 func TestRequestHeaderSetNoDefaultContentType(t *testing.T) { 662 var h RequestHeader 663 h.SetMethod(http.MethodPost) 664 b := h.AppendBytes(nil) 665 assert.DeepEqual(t, b, []byte("POST / HTTP/1.1\r\nContent-Type: application/x-www-form-urlencoded\r\n\r\n")) 666 h.SetNoDefaultContentType(true) 667 b = h.AppendBytes(nil) 668 assert.DeepEqual(t, b, []byte("POST / HTTP/1.1\r\n\r\n")) 669 } 670 671 func TestRequestHeader_PeekAll(t *testing.T) { 672 t.Parallel() 673 h := &RequestHeader{} 674 h.Add(consts.HeaderConnection, "keep-alive") 675 h.Add("Content-Type", "aaa") 676 h.Add(consts.HeaderHost, "aaabbb") 677 h.Add("User-Agent", "asdfas") 678 h.Add("Content-Length", "1123") 679 h.Add("Cookie", "foobar=baz") 680 h.Add("aaa", "aaa") 681 h.Add("aaa", "bbb") 682 683 expectRequestHeaderAll(t, h, consts.HeaderConnection, [][]byte{[]byte("keep-alive")}) 684 expectRequestHeaderAll(t, h, "Content-Type", [][]byte{[]byte("aaa")}) 685 expectRequestHeaderAll(t, h, consts.HeaderHost, [][]byte{[]byte("aaabbb")}) 686 expectRequestHeaderAll(t, h, "User-Agent", [][]byte{[]byte("asdfas")}) 687 expectRequestHeaderAll(t, h, "Content-Length", [][]byte{[]byte("1123")}) 688 expectRequestHeaderAll(t, h, "Cookie", [][]byte{[]byte("foobar=baz")}) 689 expectRequestHeaderAll(t, h, "aaa", [][]byte{[]byte("aaa"), []byte("bbb")}) 690 691 h.DelBytes([]byte("Content-Type")) 692 h.DelBytes([]byte((consts.HeaderHost))) 693 h.DelBytes([]byte("aaa")) 694 expectRequestHeaderAll(t, h, "Content-Type", [][]byte{}) 695 expectRequestHeaderAll(t, h, consts.HeaderHost, [][]byte{}) 696 expectRequestHeaderAll(t, h, "aaa", [][]byte{}) 697 } 698 699 func expectRequestHeaderAll(t *testing.T, h *RequestHeader, key string, expectedValue [][]byte) { 700 if len(h.PeekAll(key)) != len(expectedValue) { 701 t.Fatalf("Unexpected size for key %q: %d. Expected %d", key, len(h.PeekAll(key)), len(expectedValue)) 702 } 703 assert.DeepEqual(t, h.PeekAll(key), expectedValue) 704 } 705 706 func TestResponseHeader_PeekAll(t *testing.T) { 707 t.Parallel() 708 709 h := &ResponseHeader{} 710 h.Add(consts.HeaderContentType, "aaa/bbb") 711 h.Add(consts.HeaderContentEncoding, "gzip") 712 h.Add(consts.HeaderConnection, "close") 713 h.Add(consts.HeaderContentLength, "1234") 714 h.Add(consts.HeaderServer, "aaaa") 715 h.Add(consts.HeaderSetCookie, "cccc") 716 h.Add("aaa", "aaa") 717 h.Add("aaa", "bbb") 718 719 expectResponseHeaderAll(t, h, consts.HeaderContentType, [][]byte{[]byte("aaa/bbb")}) 720 expectResponseHeaderAll(t, h, consts.HeaderContentEncoding, [][]byte{[]byte("gzip")}) 721 expectResponseHeaderAll(t, h, consts.HeaderConnection, [][]byte{[]byte("close")}) 722 expectResponseHeaderAll(t, h, consts.HeaderContentLength, [][]byte{[]byte("1234")}) 723 expectResponseHeaderAll(t, h, consts.HeaderServer, [][]byte{[]byte("aaaa")}) 724 expectResponseHeaderAll(t, h, consts.HeaderSetCookie, [][]byte{[]byte("cccc")}) 725 expectResponseHeaderAll(t, h, "aaa", [][]byte{[]byte("aaa"), []byte("bbb")}) 726 727 h.Del(consts.HeaderContentType) 728 h.Del(consts.HeaderContentEncoding) 729 expectResponseHeaderAll(t, h, consts.HeaderContentType, [][]byte{bytestr.DefaultContentType}) 730 expectResponseHeaderAll(t, h, consts.HeaderContentEncoding, [][]byte{}) 731 } 732 733 func expectResponseHeaderAll(t *testing.T, h *ResponseHeader, key string, expectedValue [][]byte) { 734 if len(h.PeekAll(key)) != len(expectedValue) { 735 t.Fatalf("Unexpected size for key %q: %d. Expected %d", key, len(h.PeekAll(key)), len(expectedValue)) 736 } 737 assert.DeepEqual(t, h.PeekAll(key), expectedValue) 738 } 739 740 func TestRequestHeaderCopyTo(t *testing.T) { 741 t.Parallel() 742 743 h, hCopy := &RequestHeader{}, &RequestHeader{} 744 h.SetProtocol(consts.HTTP10) 745 h.SetMethod(consts.MethodPatch) 746 h.SetNoDefaultContentType(true) 747 h.Add(consts.HeaderConnection, "keep-alive") 748 h.Add("Content-Type", "aaa") 749 h.Add(consts.HeaderHost, "aaabbb") 750 h.Add("User-Agent", "asdfas") 751 h.Add("Content-Length", "1123") 752 h.Add("Cookie", "foobar=baz") 753 h.Add("aaa", "aaa") 754 h.Add("aaa", "bbb") 755 756 h.CopyTo(hCopy) 757 expectRequestHeaderAll(t, hCopy, consts.HeaderConnection, [][]byte{[]byte("keep-alive")}) 758 expectRequestHeaderAll(t, hCopy, "Content-Type", [][]byte{[]byte("aaa")}) 759 expectRequestHeaderAll(t, hCopy, consts.HeaderHost, [][]byte{[]byte("aaabbb")}) 760 expectRequestHeaderAll(t, hCopy, "User-Agent", [][]byte{[]byte("asdfas")}) 761 expectRequestHeaderAll(t, hCopy, "Content-Length", [][]byte{[]byte("1123")}) 762 expectRequestHeaderAll(t, hCopy, "Cookie", [][]byte{[]byte("foobar=baz")}) 763 expectRequestHeaderAll(t, hCopy, "aaa", [][]byte{[]byte("aaa"), []byte("bbb")}) 764 assert.DeepEqual(t, hCopy.GetProtocol(), consts.HTTP10) 765 assert.DeepEqual(t, hCopy.noDefaultContentType, true) 766 assert.DeepEqual(t, string(hCopy.Method()), consts.MethodPatch) 767 } 768 769 func TestResponseHeaderCopyTo(t *testing.T) { 770 t.Parallel() 771 772 h, hCopy := &ResponseHeader{}, &ResponseHeader{} 773 h.SetProtocol(consts.HTTP10) 774 h.SetHeaderLength(100) 775 h.SetNoDefaultContentType(true) 776 h.Add(consts.HeaderContentType, "aaa/bbb") 777 h.Add(consts.HeaderContentEncoding, "gzip") 778 h.Add(consts.HeaderConnection, "close") 779 h.Add(consts.HeaderContentLength, "1234") 780 h.Add(consts.HeaderServer, "aaaa") 781 h.Add(consts.HeaderSetCookie, "cccc") 782 h.Add("aaa", "aaa") 783 h.Add("aaa", "bbb") 784 785 h.CopyTo(hCopy) 786 expectResponseHeaderAll(t, hCopy, consts.HeaderContentType, [][]byte{[]byte("aaa/bbb")}) 787 expectResponseHeaderAll(t, hCopy, consts.HeaderContentEncoding, [][]byte{[]byte("gzip")}) 788 expectResponseHeaderAll(t, hCopy, consts.HeaderConnection, [][]byte{[]byte("close")}) 789 expectResponseHeaderAll(t, hCopy, consts.HeaderContentLength, [][]byte{[]byte("1234")}) 790 expectResponseHeaderAll(t, hCopy, consts.HeaderServer, [][]byte{[]byte("aaaa")}) 791 expectResponseHeaderAll(t, hCopy, consts.HeaderSetCookie, [][]byte{[]byte("cccc")}) 792 expectResponseHeaderAll(t, hCopy, "aaa", [][]byte{[]byte("aaa"), []byte("bbb")}) 793 assert.DeepEqual(t, hCopy.GetProtocol(), consts.HTTP10) 794 assert.DeepEqual(t, hCopy.noDefaultContentType, true) 795 assert.DeepEqual(t, hCopy.GetHeaderLength(), 100) 796 } 797 798 func TestResponseHeaderDateEmpty(t *testing.T) { 799 t.Parallel() 800 801 var h ResponseHeader 802 h.noDefaultDate = true 803 headers := string(h.Header()) 804 805 if strings.Contains(headers, "\r\nDate: ") { 806 t.Fatalf("ResponseDateNoDefaultNotEmpty fail, response: \n%+v\noutcome: \n%q\n", h, headers) //nolint:govet 807 } 808 } 809 810 func TestSetTrailerWithROString(t *testing.T) { 811 h := &RequestHeader{} 812 h.Add(consts.HeaderTrailer, "foo,bar,hertz") 813 assert.DeepEqual(t, "Foo, Bar, Hertz", h.Get(consts.HeaderTrailer)) 814 815 h1 := &ResponseHeader{} 816 h1.Add(consts.HeaderTrailer, "foo,bar,hertz") 817 assert.DeepEqual(t, "Foo, Bar, Hertz", h1.Get(consts.HeaderTrailer)) 818 }