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  }