github.com/hellobchain/third_party@v0.0.0-20230331131523-deb0478a2e52/gin/context_test.go (about)

     1  // Copyright 2014 Manu Martinez-Almeida.  All rights reserved.
     2  // Use of this source code is governed by a MIT style
     3  // license that can be found in the LICENSE file.
     4  
     5  package gin
     6  
     7  import (
     8  	"bytes"
     9  	"context"
    10  	"errors"
    11  	"fmt"
    12  	"github.com/hellobchain/newcryptosm/http"
    13  	"github.com/hellobchain/newcryptosm/http/httptest"
    14  	"html/template"
    15  	"io"
    16  	"mime/multipart"
    17  	"os"
    18  	"reflect"
    19  	"strings"
    20  	"sync"
    21  	"testing"
    22  	"time"
    23  
    24  	"github.com/golang/protobuf/proto"
    25  	"github.com/hellobchain/third_party/gin/binding"
    26  	"github.com/hellobchain/third_party/sse"
    27  	"github.com/stretchr/testify/assert"
    28  
    29  	testdata "github.com/hellobchain/third_party/gin/testdata/protoexample"
    30  )
    31  
    32  var _ context.Context = &Context{}
    33  
    34  // Unit tests TODO
    35  // func (c *Context) File(filepath string) {
    36  // func (c *Context) Negotiate(code int, config Negotiate) {
    37  // BAD case: func (c *Context) Render(code int, render render.Render, obj ...interface{}) {
    38  // test that information is not leaked when reusing Contexts (using the Pool)
    39  
    40  func createMultipartRequest() *http.Request {
    41  	boundary := "--testboundary"
    42  	body := new(bytes.Buffer)
    43  	mw := multipart.NewWriter(body)
    44  	defer mw.Close()
    45  
    46  	must(mw.SetBoundary(boundary))
    47  	must(mw.WriteField("foo", "bar"))
    48  	must(mw.WriteField("bar", "10"))
    49  	must(mw.WriteField("bar", "foo2"))
    50  	must(mw.WriteField("array", "first"))
    51  	must(mw.WriteField("array", "second"))
    52  	must(mw.WriteField("id", ""))
    53  	must(mw.WriteField("time_local", "31/12/2016 14:55"))
    54  	must(mw.WriteField("time_utc", "31/12/2016 14:55"))
    55  	must(mw.WriteField("time_location", "31/12/2016 14:55"))
    56  	must(mw.WriteField("names[a]", "thinkerou"))
    57  	must(mw.WriteField("names[b]", "tianou"))
    58  	req, err := http.NewRequest("POST", "/", body)
    59  	must(err)
    60  	req.Header.Set("Content-Type", MIMEMultipartPOSTForm+"; boundary="+boundary)
    61  	return req
    62  }
    63  
    64  func must(err error) {
    65  	if err != nil {
    66  		panic(err.Error())
    67  	}
    68  }
    69  
    70  func TestContextFormFile(t *testing.T) {
    71  	buf := new(bytes.Buffer)
    72  	mw := multipart.NewWriter(buf)
    73  	w, err := mw.CreateFormFile("file", "test")
    74  	if assert.NoError(t, err) {
    75  		_, err = w.Write([]byte("test"))
    76  		assert.NoError(t, err)
    77  	}
    78  	mw.Close()
    79  	c, _ := CreateTestContext(httptest.NewRecorder())
    80  	c.Request, _ = http.NewRequest("POST", "/", buf)
    81  	c.Request.Header.Set("Content-Type", mw.FormDataContentType())
    82  	f, err := c.FormFile("file")
    83  	if assert.NoError(t, err) {
    84  		assert.Equal(t, "test", f.Filename)
    85  	}
    86  
    87  	assert.NoError(t, c.SaveUploadedFile(f, "test"))
    88  }
    89  
    90  func TestContextFormFileFailed(t *testing.T) {
    91  	buf := new(bytes.Buffer)
    92  	mw := multipart.NewWriter(buf)
    93  	mw.Close()
    94  	c, _ := CreateTestContext(httptest.NewRecorder())
    95  	c.Request, _ = http.NewRequest("POST", "/", nil)
    96  	c.Request.Header.Set("Content-Type", mw.FormDataContentType())
    97  	c.engine.MaxMultipartMemory = 8 << 20
    98  	f, err := c.FormFile("file")
    99  	assert.Error(t, err)
   100  	assert.Nil(t, f)
   101  }
   102  
   103  func TestContextMultipartForm(t *testing.T) {
   104  	buf := new(bytes.Buffer)
   105  	mw := multipart.NewWriter(buf)
   106  	assert.NoError(t, mw.WriteField("foo", "bar"))
   107  	w, err := mw.CreateFormFile("file", "test")
   108  	if assert.NoError(t, err) {
   109  		_, err = w.Write([]byte("test"))
   110  		assert.NoError(t, err)
   111  	}
   112  	mw.Close()
   113  	c, _ := CreateTestContext(httptest.NewRecorder())
   114  	c.Request, _ = http.NewRequest("POST", "/", buf)
   115  	c.Request.Header.Set("Content-Type", mw.FormDataContentType())
   116  	f, err := c.MultipartForm()
   117  	if assert.NoError(t, err) {
   118  		assert.NotNil(t, f)
   119  	}
   120  
   121  	assert.NoError(t, c.SaveUploadedFile(f.File["file"][0], "test"))
   122  }
   123  
   124  func TestSaveUploadedOpenFailed(t *testing.T) {
   125  	buf := new(bytes.Buffer)
   126  	mw := multipart.NewWriter(buf)
   127  	mw.Close()
   128  
   129  	c, _ := CreateTestContext(httptest.NewRecorder())
   130  	c.Request, _ = http.NewRequest("POST", "/", buf)
   131  	c.Request.Header.Set("Content-Type", mw.FormDataContentType())
   132  
   133  	f := &multipart.FileHeader{
   134  		Filename: "file",
   135  	}
   136  	assert.Error(t, c.SaveUploadedFile(f, "test"))
   137  }
   138  
   139  func TestSaveUploadedCreateFailed(t *testing.T) {
   140  	buf := new(bytes.Buffer)
   141  	mw := multipart.NewWriter(buf)
   142  	w, err := mw.CreateFormFile("file", "test")
   143  	if assert.NoError(t, err) {
   144  		_, err = w.Write([]byte("test"))
   145  		assert.NoError(t, err)
   146  	}
   147  	mw.Close()
   148  	c, _ := CreateTestContext(httptest.NewRecorder())
   149  	c.Request, _ = http.NewRequest("POST", "/", buf)
   150  	c.Request.Header.Set("Content-Type", mw.FormDataContentType())
   151  	f, err := c.FormFile("file")
   152  	if assert.NoError(t, err) {
   153  		assert.Equal(t, "test", f.Filename)
   154  	}
   155  
   156  	assert.Error(t, c.SaveUploadedFile(f, "/"))
   157  }
   158  
   159  func TestContextReset(t *testing.T) {
   160  	router := New()
   161  	c := router.allocateContext()
   162  	assert.Equal(t, c.engine, router)
   163  
   164  	c.index = 2
   165  	c.Writer = &responseWriter{ResponseWriter: httptest.NewRecorder()}
   166  	c.Params = Params{Param{}}
   167  	c.Error(errors.New("test")) // nolint: errcheck
   168  	c.Set("foo", "bar")
   169  	c.reset()
   170  
   171  	assert.False(t, c.IsAborted())
   172  	assert.Nil(t, c.Keys)
   173  	assert.Nil(t, c.Accepted)
   174  	assert.Len(t, c.Errors, 0)
   175  	assert.Empty(t, c.Errors.Errors())
   176  	assert.Empty(t, c.Errors.ByType(ErrorTypeAny))
   177  	assert.Len(t, c.Params, 0)
   178  	assert.EqualValues(t, c.index, -1)
   179  	assert.Equal(t, c.Writer.(*responseWriter), &c.writermem)
   180  }
   181  
   182  func TestContextHandlers(t *testing.T) {
   183  	c, _ := CreateTestContext(httptest.NewRecorder())
   184  	assert.Nil(t, c.handlers)
   185  	assert.Nil(t, c.handlers.Last())
   186  
   187  	c.handlers = HandlersChain{}
   188  	assert.NotNil(t, c.handlers)
   189  	assert.Nil(t, c.handlers.Last())
   190  
   191  	f := func(c *Context) {}
   192  	g := func(c *Context) {}
   193  
   194  	c.handlers = HandlersChain{f}
   195  	compareFunc(t, f, c.handlers.Last())
   196  
   197  	c.handlers = HandlersChain{f, g}
   198  	compareFunc(t, g, c.handlers.Last())
   199  }
   200  
   201  // TestContextSetGet tests that a parameter is set correctly on the
   202  // current context and can be retrieved using Get.
   203  func TestContextSetGet(t *testing.T) {
   204  	c, _ := CreateTestContext(httptest.NewRecorder())
   205  	c.Set("foo", "bar")
   206  
   207  	value, err := c.Get("foo")
   208  	assert.Equal(t, "bar", value)
   209  	assert.True(t, err)
   210  
   211  	value, err = c.Get("foo2")
   212  	assert.Nil(t, value)
   213  	assert.False(t, err)
   214  
   215  	assert.Equal(t, "bar", c.MustGet("foo"))
   216  	assert.Panics(t, func() { c.MustGet("no_exist") })
   217  }
   218  
   219  func TestContextSetGetValues(t *testing.T) {
   220  	c, _ := CreateTestContext(httptest.NewRecorder())
   221  	c.Set("string", "this is a string")
   222  	c.Set("int32", int32(-42))
   223  	c.Set("int64", int64(42424242424242))
   224  	c.Set("uint64", uint64(42))
   225  	c.Set("float32", float32(4.2))
   226  	c.Set("float64", 4.2)
   227  	var a interface{} = 1
   228  	c.Set("intInterface", a)
   229  
   230  	assert.Exactly(t, c.MustGet("string").(string), "this is a string")
   231  	assert.Exactly(t, c.MustGet("int32").(int32), int32(-42))
   232  	assert.Exactly(t, c.MustGet("int64").(int64), int64(42424242424242))
   233  	assert.Exactly(t, c.MustGet("uint64").(uint64), uint64(42))
   234  	assert.Exactly(t, c.MustGet("float32").(float32), float32(4.2))
   235  	assert.Exactly(t, c.MustGet("float64").(float64), 4.2)
   236  	assert.Exactly(t, c.MustGet("intInterface").(int), 1)
   237  
   238  }
   239  
   240  func TestContextGetString(t *testing.T) {
   241  	c, _ := CreateTestContext(httptest.NewRecorder())
   242  	c.Set("string", "this is a string")
   243  	assert.Equal(t, "this is a string", c.GetString("string"))
   244  }
   245  
   246  func TestContextSetGetBool(t *testing.T) {
   247  	c, _ := CreateTestContext(httptest.NewRecorder())
   248  	c.Set("bool", true)
   249  	assert.True(t, c.GetBool("bool"))
   250  }
   251  
   252  func TestContextGetInt(t *testing.T) {
   253  	c, _ := CreateTestContext(httptest.NewRecorder())
   254  	c.Set("int", 1)
   255  	assert.Equal(t, 1, c.GetInt("int"))
   256  }
   257  
   258  func TestContextGetInt64(t *testing.T) {
   259  	c, _ := CreateTestContext(httptest.NewRecorder())
   260  	c.Set("int64", int64(42424242424242))
   261  	assert.Equal(t, int64(42424242424242), c.GetInt64("int64"))
   262  }
   263  
   264  func TestContextGetUint(t *testing.T) {
   265  	c, _ := CreateTestContext(httptest.NewRecorder())
   266  	c.Set("uint", uint(1))
   267  	assert.Equal(t, uint(1), c.GetUint("uint"))
   268  }
   269  
   270  func TestContextGetUint64(t *testing.T) {
   271  	c, _ := CreateTestContext(httptest.NewRecorder())
   272  	c.Set("uint64", uint64(18446744073709551615))
   273  	assert.Equal(t, uint64(18446744073709551615), c.GetUint64("uint64"))
   274  }
   275  
   276  func TestContextGetFloat64(t *testing.T) {
   277  	c, _ := CreateTestContext(httptest.NewRecorder())
   278  	c.Set("float64", 4.2)
   279  	assert.Equal(t, 4.2, c.GetFloat64("float64"))
   280  }
   281  
   282  func TestContextGetTime(t *testing.T) {
   283  	c, _ := CreateTestContext(httptest.NewRecorder())
   284  	t1, _ := time.Parse("1/2/2006 15:04:05", "01/01/2017 12:00:00")
   285  	c.Set("time", t1)
   286  	assert.Equal(t, t1, c.GetTime("time"))
   287  }
   288  
   289  func TestContextGetDuration(t *testing.T) {
   290  	c, _ := CreateTestContext(httptest.NewRecorder())
   291  	c.Set("duration", time.Second)
   292  	assert.Equal(t, time.Second, c.GetDuration("duration"))
   293  }
   294  
   295  func TestContextGetStringSlice(t *testing.T) {
   296  	c, _ := CreateTestContext(httptest.NewRecorder())
   297  	c.Set("slice", []string{"foo"})
   298  	assert.Equal(t, []string{"foo"}, c.GetStringSlice("slice"))
   299  }
   300  
   301  func TestContextGetStringMap(t *testing.T) {
   302  	c, _ := CreateTestContext(httptest.NewRecorder())
   303  	var m = make(map[string]interface{})
   304  	m["foo"] = 1
   305  	c.Set("map", m)
   306  
   307  	assert.Equal(t, m, c.GetStringMap("map"))
   308  	assert.Equal(t, 1, c.GetStringMap("map")["foo"])
   309  }
   310  
   311  func TestContextGetStringMapString(t *testing.T) {
   312  	c, _ := CreateTestContext(httptest.NewRecorder())
   313  	var m = make(map[string]string)
   314  	m["foo"] = "bar"
   315  	c.Set("map", m)
   316  
   317  	assert.Equal(t, m, c.GetStringMapString("map"))
   318  	assert.Equal(t, "bar", c.GetStringMapString("map")["foo"])
   319  }
   320  
   321  func TestContextGetStringMapStringSlice(t *testing.T) {
   322  	c, _ := CreateTestContext(httptest.NewRecorder())
   323  	var m = make(map[string][]string)
   324  	m["foo"] = []string{"foo"}
   325  	c.Set("map", m)
   326  
   327  	assert.Equal(t, m, c.GetStringMapStringSlice("map"))
   328  	assert.Equal(t, []string{"foo"}, c.GetStringMapStringSlice("map")["foo"])
   329  }
   330  
   331  func TestContextCopy(t *testing.T) {
   332  	c, _ := CreateTestContext(httptest.NewRecorder())
   333  	c.index = 2
   334  	c.Request, _ = http.NewRequest("POST", "/hola", nil)
   335  	c.handlers = HandlersChain{func(c *Context) {}}
   336  	c.Params = Params{Param{Key: "foo", Value: "bar"}}
   337  	c.Set("foo", "bar")
   338  
   339  	cp := c.Copy()
   340  	assert.Nil(t, cp.handlers)
   341  	assert.Nil(t, cp.writermem.ResponseWriter)
   342  	assert.Equal(t, &cp.writermem, cp.Writer.(*responseWriter))
   343  	assert.Equal(t, cp.Request, c.Request)
   344  	assert.Equal(t, cp.index, abortIndex)
   345  	assert.Equal(t, cp.Keys, c.Keys)
   346  	assert.Equal(t, cp.engine, c.engine)
   347  	assert.Equal(t, cp.Params, c.Params)
   348  	cp.Set("foo", "notBar")
   349  	assert.False(t, cp.Keys["foo"] == c.Keys["foo"])
   350  }
   351  
   352  func TestContextHandlerName(t *testing.T) {
   353  	c, _ := CreateTestContext(httptest.NewRecorder())
   354  	c.handlers = HandlersChain{func(c *Context) {}, handlerNameTest}
   355  
   356  	assert.Regexp(t, "^(.*/vendor/)?github.com/gin-gonic/gin.handlerNameTest$", c.HandlerName())
   357  }
   358  
   359  func TestContextHandlerNames(t *testing.T) {
   360  	c, _ := CreateTestContext(httptest.NewRecorder())
   361  	c.handlers = HandlersChain{func(c *Context) {}, handlerNameTest, func(c *Context) {}, handlerNameTest2}
   362  
   363  	names := c.HandlerNames()
   364  
   365  	assert.True(t, len(names) == 4)
   366  	for _, name := range names {
   367  		assert.Regexp(t, `^(.*/vendor/)?(github\.com/gin-gonic/gin\.){1}(TestContextHandlerNames\.func.*){0,1}(handlerNameTest.*){0,1}`, name)
   368  	}
   369  }
   370  
   371  func handlerNameTest(c *Context) {
   372  
   373  }
   374  
   375  func handlerNameTest2(c *Context) {
   376  
   377  }
   378  
   379  var handlerTest HandlerFunc = func(c *Context) {
   380  
   381  }
   382  
   383  func TestContextHandler(t *testing.T) {
   384  	c, _ := CreateTestContext(httptest.NewRecorder())
   385  	c.handlers = HandlersChain{func(c *Context) {}, handlerTest}
   386  
   387  	assert.Equal(t, reflect.ValueOf(handlerTest).Pointer(), reflect.ValueOf(c.Handler()).Pointer())
   388  }
   389  
   390  func TestContextQuery(t *testing.T) {
   391  	c, _ := CreateTestContext(httptest.NewRecorder())
   392  	c.Request, _ = http.NewRequest("GET", "http://example.com/?foo=bar&page=10&id=", nil)
   393  
   394  	value, ok := c.GetQuery("foo")
   395  	assert.True(t, ok)
   396  	assert.Equal(t, "bar", value)
   397  	assert.Equal(t, "bar", c.DefaultQuery("foo", "none"))
   398  	assert.Equal(t, "bar", c.Query("foo"))
   399  
   400  	value, ok = c.GetQuery("page")
   401  	assert.True(t, ok)
   402  	assert.Equal(t, "10", value)
   403  	assert.Equal(t, "10", c.DefaultQuery("page", "0"))
   404  	assert.Equal(t, "10", c.Query("page"))
   405  
   406  	value, ok = c.GetQuery("id")
   407  	assert.True(t, ok)
   408  	assert.Empty(t, value)
   409  	assert.Empty(t, c.DefaultQuery("id", "nada"))
   410  	assert.Empty(t, c.Query("id"))
   411  
   412  	value, ok = c.GetQuery("NoKey")
   413  	assert.False(t, ok)
   414  	assert.Empty(t, value)
   415  	assert.Equal(t, "nada", c.DefaultQuery("NoKey", "nada"))
   416  	assert.Empty(t, c.Query("NoKey"))
   417  
   418  	// postform should not mess
   419  	value, ok = c.GetPostForm("page")
   420  	assert.False(t, ok)
   421  	assert.Empty(t, value)
   422  	assert.Empty(t, c.PostForm("foo"))
   423  }
   424  
   425  func TestContextDefaultQueryOnEmptyRequest(t *testing.T) {
   426  	c, _ := CreateTestContext(httptest.NewRecorder()) // here c.Request == nil
   427  	assert.NotPanics(t, func() {
   428  		value, ok := c.GetQuery("NoKey")
   429  		assert.False(t, ok)
   430  		assert.Empty(t, value)
   431  	})
   432  	assert.NotPanics(t, func() {
   433  		assert.Equal(t, "nada", c.DefaultQuery("NoKey", "nada"))
   434  	})
   435  	assert.NotPanics(t, func() {
   436  		assert.Empty(t, c.Query("NoKey"))
   437  	})
   438  }
   439  
   440  func TestContextQueryAndPostForm(t *testing.T) {
   441  	c, _ := CreateTestContext(httptest.NewRecorder())
   442  	body := bytes.NewBufferString("foo=bar&page=11&both=&foo=second")
   443  	c.Request, _ = http.NewRequest("POST",
   444  		"/?both=GET&id=main&id=omit&array[]=first&array[]=second&ids[a]=hi&ids[b]=3.14", body)
   445  	c.Request.Header.Add("Content-Type", MIMEPOSTForm)
   446  
   447  	assert.Equal(t, "bar", c.DefaultPostForm("foo", "none"))
   448  	assert.Equal(t, "bar", c.PostForm("foo"))
   449  	assert.Empty(t, c.Query("foo"))
   450  
   451  	value, ok := c.GetPostForm("page")
   452  	assert.True(t, ok)
   453  	assert.Equal(t, "11", value)
   454  	assert.Equal(t, "11", c.DefaultPostForm("page", "0"))
   455  	assert.Equal(t, "11", c.PostForm("page"))
   456  	assert.Empty(t, c.Query("page"))
   457  
   458  	value, ok = c.GetPostForm("both")
   459  	assert.True(t, ok)
   460  	assert.Empty(t, value)
   461  	assert.Empty(t, c.PostForm("both"))
   462  	assert.Empty(t, c.DefaultPostForm("both", "nothing"))
   463  	assert.Equal(t, "GET", c.Query("both"), "GET")
   464  
   465  	value, ok = c.GetQuery("id")
   466  	assert.True(t, ok)
   467  	assert.Equal(t, "main", value)
   468  	assert.Equal(t, "000", c.DefaultPostForm("id", "000"))
   469  	assert.Equal(t, "main", c.Query("id"))
   470  	assert.Empty(t, c.PostForm("id"))
   471  
   472  	value, ok = c.GetQuery("NoKey")
   473  	assert.False(t, ok)
   474  	assert.Empty(t, value)
   475  	value, ok = c.GetPostForm("NoKey")
   476  	assert.False(t, ok)
   477  	assert.Empty(t, value)
   478  	assert.Equal(t, "nada", c.DefaultPostForm("NoKey", "nada"))
   479  	assert.Equal(t, "nothing", c.DefaultQuery("NoKey", "nothing"))
   480  	assert.Empty(t, c.PostForm("NoKey"))
   481  	assert.Empty(t, c.Query("NoKey"))
   482  
   483  	var obj struct {
   484  		Foo   string   `form:"foo"`
   485  		ID    string   `form:"id"`
   486  		Page  int      `form:"page"`
   487  		Both  string   `form:"both"`
   488  		Array []string `form:"array[]"`
   489  	}
   490  	assert.NoError(t, c.Bind(&obj))
   491  	assert.Equal(t, "bar", obj.Foo, "bar")
   492  	assert.Equal(t, "main", obj.ID, "main")
   493  	assert.Equal(t, 11, obj.Page, 11)
   494  	assert.Empty(t, obj.Both)
   495  	assert.Equal(t, []string{"first", "second"}, obj.Array)
   496  
   497  	values, ok := c.GetQueryArray("array[]")
   498  	assert.True(t, ok)
   499  	assert.Equal(t, "first", values[0])
   500  	assert.Equal(t, "second", values[1])
   501  
   502  	values = c.QueryArray("array[]")
   503  	assert.Equal(t, "first", values[0])
   504  	assert.Equal(t, "second", values[1])
   505  
   506  	values = c.QueryArray("nokey")
   507  	assert.Equal(t, 0, len(values))
   508  
   509  	values = c.QueryArray("both")
   510  	assert.Equal(t, 1, len(values))
   511  	assert.Equal(t, "GET", values[0])
   512  
   513  	dicts, ok := c.GetQueryMap("ids")
   514  	assert.True(t, ok)
   515  	assert.Equal(t, "hi", dicts["a"])
   516  	assert.Equal(t, "3.14", dicts["b"])
   517  
   518  	dicts, ok = c.GetQueryMap("nokey")
   519  	assert.False(t, ok)
   520  	assert.Equal(t, 0, len(dicts))
   521  
   522  	dicts, ok = c.GetQueryMap("both")
   523  	assert.False(t, ok)
   524  	assert.Equal(t, 0, len(dicts))
   525  
   526  	dicts, ok = c.GetQueryMap("array")
   527  	assert.False(t, ok)
   528  	assert.Equal(t, 0, len(dicts))
   529  
   530  	dicts = c.QueryMap("ids")
   531  	assert.Equal(t, "hi", dicts["a"])
   532  	assert.Equal(t, "3.14", dicts["b"])
   533  
   534  	dicts = c.QueryMap("nokey")
   535  	assert.Equal(t, 0, len(dicts))
   536  }
   537  
   538  func TestContextPostFormMultipart(t *testing.T) {
   539  	c, _ := CreateTestContext(httptest.NewRecorder())
   540  	c.Request = createMultipartRequest()
   541  
   542  	var obj struct {
   543  		Foo          string    `form:"foo"`
   544  		Bar          string    `form:"bar"`
   545  		BarAsInt     int       `form:"bar"`
   546  		Array        []string  `form:"array"`
   547  		ID           string    `form:"id"`
   548  		TimeLocal    time.Time `form:"time_local" time_format:"02/01/2006 15:04"`
   549  		TimeUTC      time.Time `form:"time_utc" time_format:"02/01/2006 15:04" time_utc:"1"`
   550  		TimeLocation time.Time `form:"time_location" time_format:"02/01/2006 15:04" time_location:"Asia/Tokyo"`
   551  		BlankTime    time.Time `form:"blank_time" time_format:"02/01/2006 15:04"`
   552  	}
   553  	assert.NoError(t, c.Bind(&obj))
   554  	assert.Equal(t, "bar", obj.Foo)
   555  	assert.Equal(t, "10", obj.Bar)
   556  	assert.Equal(t, 10, obj.BarAsInt)
   557  	assert.Equal(t, []string{"first", "second"}, obj.Array)
   558  	assert.Empty(t, obj.ID)
   559  	assert.Equal(t, "31/12/2016 14:55", obj.TimeLocal.Format("02/01/2006 15:04"))
   560  	assert.Equal(t, time.Local, obj.TimeLocal.Location())
   561  	assert.Equal(t, "31/12/2016 14:55", obj.TimeUTC.Format("02/01/2006 15:04"))
   562  	assert.Equal(t, time.UTC, obj.TimeUTC.Location())
   563  	loc, _ := time.LoadLocation("Asia/Tokyo")
   564  	assert.Equal(t, "31/12/2016 14:55", obj.TimeLocation.Format("02/01/2006 15:04"))
   565  	assert.Equal(t, loc, obj.TimeLocation.Location())
   566  	assert.True(t, obj.BlankTime.IsZero())
   567  
   568  	value, ok := c.GetQuery("foo")
   569  	assert.False(t, ok)
   570  	assert.Empty(t, value)
   571  	assert.Empty(t, c.Query("bar"))
   572  	assert.Equal(t, "nothing", c.DefaultQuery("id", "nothing"))
   573  
   574  	value, ok = c.GetPostForm("foo")
   575  	assert.True(t, ok)
   576  	assert.Equal(t, "bar", value)
   577  	assert.Equal(t, "bar", c.PostForm("foo"))
   578  
   579  	value, ok = c.GetPostForm("array")
   580  	assert.True(t, ok)
   581  	assert.Equal(t, "first", value)
   582  	assert.Equal(t, "first", c.PostForm("array"))
   583  
   584  	assert.Equal(t, "10", c.DefaultPostForm("bar", "nothing"))
   585  
   586  	value, ok = c.GetPostForm("id")
   587  	assert.True(t, ok)
   588  	assert.Empty(t, value)
   589  	assert.Empty(t, c.PostForm("id"))
   590  	assert.Empty(t, c.DefaultPostForm("id", "nothing"))
   591  
   592  	value, ok = c.GetPostForm("nokey")
   593  	assert.False(t, ok)
   594  	assert.Empty(t, value)
   595  	assert.Equal(t, "nothing", c.DefaultPostForm("nokey", "nothing"))
   596  
   597  	values, ok := c.GetPostFormArray("array")
   598  	assert.True(t, ok)
   599  	assert.Equal(t, "first", values[0])
   600  	assert.Equal(t, "second", values[1])
   601  
   602  	values = c.PostFormArray("array")
   603  	assert.Equal(t, "first", values[0])
   604  	assert.Equal(t, "second", values[1])
   605  
   606  	values = c.PostFormArray("nokey")
   607  	assert.Equal(t, 0, len(values))
   608  
   609  	values = c.PostFormArray("foo")
   610  	assert.Equal(t, 1, len(values))
   611  	assert.Equal(t, "bar", values[0])
   612  
   613  	dicts, ok := c.GetPostFormMap("names")
   614  	assert.True(t, ok)
   615  	assert.Equal(t, "thinkerou", dicts["a"])
   616  	assert.Equal(t, "tianou", dicts["b"])
   617  
   618  	dicts, ok = c.GetPostFormMap("nokey")
   619  	assert.False(t, ok)
   620  	assert.Equal(t, 0, len(dicts))
   621  
   622  	dicts = c.PostFormMap("names")
   623  	assert.Equal(t, "thinkerou", dicts["a"])
   624  	assert.Equal(t, "tianou", dicts["b"])
   625  
   626  	dicts = c.PostFormMap("nokey")
   627  	assert.Equal(t, 0, len(dicts))
   628  }
   629  
   630  func TestContextSetCookie(t *testing.T) {
   631  	c, _ := CreateTestContext(httptest.NewRecorder())
   632  	c.SetSameSite(http.SameSiteLaxMode)
   633  	c.SetCookie("user", "gin", 1, "/", "localhost", true, true)
   634  	assert.Equal(t, "user=gin; Path=/; Domain=localhost; Max-Age=1; HttpOnly; Secure; SameSite=Lax", c.Writer.Header().Get("Set-Cookie"))
   635  }
   636  
   637  func TestContextSetCookiePathEmpty(t *testing.T) {
   638  	c, _ := CreateTestContext(httptest.NewRecorder())
   639  	c.SetSameSite(http.SameSiteLaxMode)
   640  	c.SetCookie("user", "gin", 1, "", "localhost", true, true)
   641  	assert.Equal(t, "user=gin; Path=/; Domain=localhost; Max-Age=1; HttpOnly; Secure; SameSite=Lax", c.Writer.Header().Get("Set-Cookie"))
   642  }
   643  
   644  func TestContextGetCookie(t *testing.T) {
   645  	c, _ := CreateTestContext(httptest.NewRecorder())
   646  	c.Request, _ = http.NewRequest("GET", "/get", nil)
   647  	c.Request.Header.Set("Cookie", "user=gin")
   648  	cookie, _ := c.Cookie("user")
   649  	assert.Equal(t, "gin", cookie)
   650  
   651  	_, err := c.Cookie("nokey")
   652  	assert.Error(t, err)
   653  }
   654  
   655  func TestContextBodyAllowedForStatus(t *testing.T) {
   656  	assert.False(t, false, bodyAllowedForStatus(http.StatusProcessing))
   657  	assert.False(t, false, bodyAllowedForStatus(http.StatusNoContent))
   658  	assert.False(t, false, bodyAllowedForStatus(http.StatusNotModified))
   659  	assert.True(t, true, bodyAllowedForStatus(http.StatusInternalServerError))
   660  }
   661  
   662  type TestPanicRender struct {
   663  }
   664  
   665  func (*TestPanicRender) Render(http.ResponseWriter) error {
   666  	return errors.New("TestPanicRender")
   667  }
   668  
   669  func (*TestPanicRender) WriteContentType(http.ResponseWriter) {}
   670  
   671  func TestContextRenderPanicIfErr(t *testing.T) {
   672  	defer func() {
   673  		r := recover()
   674  		assert.Equal(t, "TestPanicRender", fmt.Sprint(r))
   675  	}()
   676  	w := httptest.NewRecorder()
   677  	c, _ := CreateTestContext(w)
   678  
   679  	c.Render(http.StatusOK, &TestPanicRender{})
   680  
   681  	assert.Fail(t, "Panic not detected")
   682  }
   683  
   684  // Tests that the response is serialized as JSON
   685  // and Content-Type is set to application/json
   686  // and special HTML characters are escaped
   687  func TestContextRenderJSON(t *testing.T) {
   688  	w := httptest.NewRecorder()
   689  	c, _ := CreateTestContext(w)
   690  
   691  	c.JSON(http.StatusCreated, H{"foo": "bar", "html": "<b>"})
   692  
   693  	assert.Equal(t, http.StatusCreated, w.Code)
   694  	assert.Equal(t, "{\"foo\":\"bar\",\"html\":\"\\u003cb\\u003e\"}", w.Body.String())
   695  	assert.Equal(t, "application/json; charset=utf-8", w.Header().Get("Content-Type"))
   696  }
   697  
   698  // Tests that the response is serialized as JSONP
   699  // and Content-Type is set to application/javascript
   700  func TestContextRenderJSONP(t *testing.T) {
   701  	w := httptest.NewRecorder()
   702  	c, _ := CreateTestContext(w)
   703  	c.Request, _ = http.NewRequest("GET", "http://example.com/?callback=x", nil)
   704  
   705  	c.JSONP(http.StatusCreated, H{"foo": "bar"})
   706  
   707  	assert.Equal(t, http.StatusCreated, w.Code)
   708  	assert.Equal(t, "x({\"foo\":\"bar\"});", w.Body.String())
   709  	assert.Equal(t, "application/javascript; charset=utf-8", w.Header().Get("Content-Type"))
   710  }
   711  
   712  // Tests that the response is serialized as JSONP
   713  // and Content-Type is set to application/json
   714  func TestContextRenderJSONPWithoutCallback(t *testing.T) {
   715  	w := httptest.NewRecorder()
   716  	c, _ := CreateTestContext(w)
   717  	c.Request, _ = http.NewRequest("GET", "http://example.com", nil)
   718  
   719  	c.JSONP(http.StatusCreated, H{"foo": "bar"})
   720  
   721  	assert.Equal(t, http.StatusCreated, w.Code)
   722  	assert.Equal(t, "{\"foo\":\"bar\"}", w.Body.String())
   723  	assert.Equal(t, "application/json; charset=utf-8", w.Header().Get("Content-Type"))
   724  }
   725  
   726  // Tests that no JSON is rendered if code is 204
   727  func TestContextRenderNoContentJSON(t *testing.T) {
   728  	w := httptest.NewRecorder()
   729  	c, _ := CreateTestContext(w)
   730  
   731  	c.JSON(http.StatusNoContent, H{"foo": "bar"})
   732  
   733  	assert.Equal(t, http.StatusNoContent, w.Code)
   734  	assert.Empty(t, w.Body.String())
   735  	assert.Equal(t, "application/json; charset=utf-8", w.Header().Get("Content-Type"))
   736  }
   737  
   738  // Tests that the response is serialized as JSON
   739  // we change the content-type before
   740  func TestContextRenderAPIJSON(t *testing.T) {
   741  	w := httptest.NewRecorder()
   742  	c, _ := CreateTestContext(w)
   743  
   744  	c.Header("Content-Type", "application/vnd.api+json")
   745  	c.JSON(http.StatusCreated, H{"foo": "bar"})
   746  
   747  	assert.Equal(t, http.StatusCreated, w.Code)
   748  	assert.Equal(t, "{\"foo\":\"bar\"}", w.Body.String())
   749  	assert.Equal(t, "application/vnd.api+json", w.Header().Get("Content-Type"))
   750  }
   751  
   752  // Tests that no Custom JSON is rendered if code is 204
   753  func TestContextRenderNoContentAPIJSON(t *testing.T) {
   754  	w := httptest.NewRecorder()
   755  	c, _ := CreateTestContext(w)
   756  
   757  	c.Header("Content-Type", "application/vnd.api+json")
   758  	c.JSON(http.StatusNoContent, H{"foo": "bar"})
   759  
   760  	assert.Equal(t, http.StatusNoContent, w.Code)
   761  	assert.Empty(t, w.Body.String())
   762  	assert.Equal(t, w.Header().Get("Content-Type"), "application/vnd.api+json")
   763  }
   764  
   765  // Tests that the response is serialized as JSON
   766  // and Content-Type is set to application/json
   767  func TestContextRenderIndentedJSON(t *testing.T) {
   768  	w := httptest.NewRecorder()
   769  	c, _ := CreateTestContext(w)
   770  
   771  	c.IndentedJSON(http.StatusCreated, H{"foo": "bar", "bar": "foo", "nested": H{"foo": "bar"}})
   772  
   773  	assert.Equal(t, http.StatusCreated, w.Code)
   774  	assert.Equal(t, "{\n    \"bar\": \"foo\",\n    \"foo\": \"bar\",\n    \"nested\": {\n        \"foo\": \"bar\"\n    }\n}", w.Body.String())
   775  	assert.Equal(t, "application/json; charset=utf-8", w.Header().Get("Content-Type"))
   776  }
   777  
   778  // Tests that no Custom JSON is rendered if code is 204
   779  func TestContextRenderNoContentIndentedJSON(t *testing.T) {
   780  	w := httptest.NewRecorder()
   781  	c, _ := CreateTestContext(w)
   782  
   783  	c.IndentedJSON(http.StatusNoContent, H{"foo": "bar", "bar": "foo", "nested": H{"foo": "bar"}})
   784  
   785  	assert.Equal(t, http.StatusNoContent, w.Code)
   786  	assert.Empty(t, w.Body.String())
   787  	assert.Equal(t, "application/json; charset=utf-8", w.Header().Get("Content-Type"))
   788  }
   789  
   790  // Tests that the response is serialized as Secure JSON
   791  // and Content-Type is set to application/json
   792  func TestContextRenderSecureJSON(t *testing.T) {
   793  	w := httptest.NewRecorder()
   794  	c, router := CreateTestContext(w)
   795  
   796  	router.SecureJsonPrefix("&&&START&&&")
   797  	c.SecureJSON(http.StatusCreated, []string{"foo", "bar"})
   798  
   799  	assert.Equal(t, http.StatusCreated, w.Code)
   800  	assert.Equal(t, "&&&START&&&[\"foo\",\"bar\"]", w.Body.String())
   801  	assert.Equal(t, "application/json; charset=utf-8", w.Header().Get("Content-Type"))
   802  }
   803  
   804  // Tests that no Custom JSON is rendered if code is 204
   805  func TestContextRenderNoContentSecureJSON(t *testing.T) {
   806  	w := httptest.NewRecorder()
   807  	c, _ := CreateTestContext(w)
   808  
   809  	c.SecureJSON(http.StatusNoContent, []string{"foo", "bar"})
   810  
   811  	assert.Equal(t, http.StatusNoContent, w.Code)
   812  	assert.Empty(t, w.Body.String())
   813  	assert.Equal(t, "application/json; charset=utf-8", w.Header().Get("Content-Type"))
   814  }
   815  
   816  func TestContextRenderNoContentAsciiJSON(t *testing.T) {
   817  	w := httptest.NewRecorder()
   818  	c, _ := CreateTestContext(w)
   819  
   820  	c.AsciiJSON(http.StatusNoContent, []string{"lang", "Go语言"})
   821  
   822  	assert.Equal(t, http.StatusNoContent, w.Code)
   823  	assert.Empty(t, w.Body.String())
   824  	assert.Equal(t, "application/json", w.Header().Get("Content-Type"))
   825  }
   826  
   827  // Tests that the response is serialized as JSON
   828  // and Content-Type is set to application/json
   829  // and special HTML characters are preserved
   830  func TestContextRenderPureJSON(t *testing.T) {
   831  	w := httptest.NewRecorder()
   832  	c, _ := CreateTestContext(w)
   833  	c.PureJSON(http.StatusCreated, H{"foo": "bar", "html": "<b>"})
   834  	assert.Equal(t, http.StatusCreated, w.Code)
   835  	assert.Equal(t, "{\"foo\":\"bar\",\"html\":\"<b>\"}\n", w.Body.String())
   836  	assert.Equal(t, "application/json; charset=utf-8", w.Header().Get("Content-Type"))
   837  }
   838  
   839  // Tests that the response executes the templates
   840  // and responds with Content-Type set to text/html
   841  func TestContextRenderHTML(t *testing.T) {
   842  	w := httptest.NewRecorder()
   843  	c, router := CreateTestContext(w)
   844  
   845  	templ := template.Must(template.New("t").Parse(`Hello {{.name}}`))
   846  	router.SetHTMLTemplate(templ)
   847  
   848  	c.HTML(http.StatusCreated, "t", H{"name": "alexandernyquist"})
   849  
   850  	assert.Equal(t, http.StatusCreated, w.Code)
   851  	assert.Equal(t, "Hello alexandernyquist", w.Body.String())
   852  	assert.Equal(t, "text/html; charset=utf-8", w.Header().Get("Content-Type"))
   853  }
   854  
   855  func TestContextRenderHTML2(t *testing.T) {
   856  	w := httptest.NewRecorder()
   857  	c, router := CreateTestContext(w)
   858  
   859  	// print debug warning log when Engine.trees > 0
   860  	router.addRoute("GET", "/", HandlersChain{func(_ *Context) {}})
   861  	assert.Len(t, router.trees, 1)
   862  
   863  	templ := template.Must(template.New("t").Parse(`Hello {{.name}}`))
   864  	re := captureOutput(t, func() {
   865  		SetMode(DebugMode)
   866  		router.SetHTMLTemplate(templ)
   867  		SetMode(TestMode)
   868  	})
   869  
   870  	assert.Equal(t, "[GIN-debug] [WARNING] Since SetHTMLTemplate() is NOT thread-safe. It should only be called\nat initialization. ie. before any route is registered or the router is listening in a socket:\n\n\trouter := gin.Default()\n\trouter.SetHTMLTemplate(template) // << good place\n\n", re)
   871  
   872  	c.HTML(http.StatusCreated, "t", H{"name": "alexandernyquist"})
   873  
   874  	assert.Equal(t, http.StatusCreated, w.Code)
   875  	assert.Equal(t, "Hello alexandernyquist", w.Body.String())
   876  	assert.Equal(t, "text/html; charset=utf-8", w.Header().Get("Content-Type"))
   877  }
   878  
   879  // Tests that no HTML is rendered if code is 204
   880  func TestContextRenderNoContentHTML(t *testing.T) {
   881  	w := httptest.NewRecorder()
   882  	c, router := CreateTestContext(w)
   883  	templ := template.Must(template.New("t").Parse(`Hello {{.name}}`))
   884  	router.SetHTMLTemplate(templ)
   885  
   886  	c.HTML(http.StatusNoContent, "t", H{"name": "alexandernyquist"})
   887  
   888  	assert.Equal(t, http.StatusNoContent, w.Code)
   889  	assert.Empty(t, w.Body.String())
   890  	assert.Equal(t, "text/html; charset=utf-8", w.Header().Get("Content-Type"))
   891  }
   892  
   893  // TestContextXML tests that the response is serialized as XML
   894  // and Content-Type is set to application/xml
   895  func TestContextRenderXML(t *testing.T) {
   896  	w := httptest.NewRecorder()
   897  	c, _ := CreateTestContext(w)
   898  
   899  	c.XML(http.StatusCreated, H{"foo": "bar"})
   900  
   901  	assert.Equal(t, http.StatusCreated, w.Code)
   902  	assert.Equal(t, "<map><foo>bar</foo></map>", w.Body.String())
   903  	assert.Equal(t, "application/xml; charset=utf-8", w.Header().Get("Content-Type"))
   904  }
   905  
   906  // Tests that no XML is rendered if code is 204
   907  func TestContextRenderNoContentXML(t *testing.T) {
   908  	w := httptest.NewRecorder()
   909  	c, _ := CreateTestContext(w)
   910  
   911  	c.XML(http.StatusNoContent, H{"foo": "bar"})
   912  
   913  	assert.Equal(t, http.StatusNoContent, w.Code)
   914  	assert.Empty(t, w.Body.String())
   915  	assert.Equal(t, "application/xml; charset=utf-8", w.Header().Get("Content-Type"))
   916  }
   917  
   918  // TestContextString tests that the response is returned
   919  // with Content-Type set to text/plain
   920  func TestContextRenderString(t *testing.T) {
   921  	w := httptest.NewRecorder()
   922  	c, _ := CreateTestContext(w)
   923  
   924  	c.String(http.StatusCreated, "test %s %d", "string", 2)
   925  
   926  	assert.Equal(t, http.StatusCreated, w.Code)
   927  	assert.Equal(t, "test string 2", w.Body.String())
   928  	assert.Equal(t, "text/plain; charset=utf-8", w.Header().Get("Content-Type"))
   929  }
   930  
   931  // Tests that no String is rendered if code is 204
   932  func TestContextRenderNoContentString(t *testing.T) {
   933  	w := httptest.NewRecorder()
   934  	c, _ := CreateTestContext(w)
   935  
   936  	c.String(http.StatusNoContent, "test %s %d", "string", 2)
   937  
   938  	assert.Equal(t, http.StatusNoContent, w.Code)
   939  	assert.Empty(t, w.Body.String())
   940  	assert.Equal(t, "text/plain; charset=utf-8", w.Header().Get("Content-Type"))
   941  }
   942  
   943  // TestContextString tests that the response is returned
   944  // with Content-Type set to text/html
   945  func TestContextRenderHTMLString(t *testing.T) {
   946  	w := httptest.NewRecorder()
   947  	c, _ := CreateTestContext(w)
   948  
   949  	c.Header("Content-Type", "text/html; charset=utf-8")
   950  	c.String(http.StatusCreated, "<html>%s %d</html>", "string", 3)
   951  
   952  	assert.Equal(t, http.StatusCreated, w.Code)
   953  	assert.Equal(t, "<html>string 3</html>", w.Body.String())
   954  	assert.Equal(t, "text/html; charset=utf-8", w.Header().Get("Content-Type"))
   955  }
   956  
   957  // Tests that no HTML String is rendered if code is 204
   958  func TestContextRenderNoContentHTMLString(t *testing.T) {
   959  	w := httptest.NewRecorder()
   960  	c, _ := CreateTestContext(w)
   961  
   962  	c.Header("Content-Type", "text/html; charset=utf-8")
   963  	c.String(http.StatusNoContent, "<html>%s %d</html>", "string", 3)
   964  
   965  	assert.Equal(t, http.StatusNoContent, w.Code)
   966  	assert.Empty(t, w.Body.String())
   967  	assert.Equal(t, "text/html; charset=utf-8", w.Header().Get("Content-Type"))
   968  }
   969  
   970  // TestContextData tests that the response can be written from `bytestring`
   971  // with specified MIME type
   972  func TestContextRenderData(t *testing.T) {
   973  	w := httptest.NewRecorder()
   974  	c, _ := CreateTestContext(w)
   975  
   976  	c.Data(http.StatusCreated, "text/csv", []byte(`foo,bar`))
   977  
   978  	assert.Equal(t, http.StatusCreated, w.Code)
   979  	assert.Equal(t, "foo,bar", w.Body.String())
   980  	assert.Equal(t, "text/csv", w.Header().Get("Content-Type"))
   981  }
   982  
   983  // Tests that no Custom Data is rendered if code is 204
   984  func TestContextRenderNoContentData(t *testing.T) {
   985  	w := httptest.NewRecorder()
   986  	c, _ := CreateTestContext(w)
   987  
   988  	c.Data(http.StatusNoContent, "text/csv", []byte(`foo,bar`))
   989  
   990  	assert.Equal(t, http.StatusNoContent, w.Code)
   991  	assert.Empty(t, w.Body.String())
   992  	assert.Equal(t, "text/csv", w.Header().Get("Content-Type"))
   993  }
   994  
   995  func TestContextRenderSSE(t *testing.T) {
   996  	w := httptest.NewRecorder()
   997  	c, _ := CreateTestContext(w)
   998  
   999  	c.SSEvent("float", 1.5)
  1000  	c.Render(-1, sse.Event{
  1001  		Id:   "123",
  1002  		Data: "text",
  1003  	})
  1004  	c.SSEvent("chat", H{
  1005  		"foo": "bar",
  1006  		"bar": "foo",
  1007  	})
  1008  
  1009  	assert.Equal(t, strings.Replace(w.Body.String(), " ", "", -1), strings.Replace("event:float\ndata:1.5\n\nid:123\ndata:text\n\nevent:chat\ndata:{\"bar\":\"foo\",\"foo\":\"bar\"}\n\n", " ", "", -1))
  1010  }
  1011  
  1012  func TestContextRenderFile(t *testing.T) {
  1013  	w := httptest.NewRecorder()
  1014  	c, _ := CreateTestContext(w)
  1015  
  1016  	c.Request, _ = http.NewRequest("GET", "/", nil)
  1017  	c.File("./gin.go")
  1018  
  1019  	assert.Equal(t, http.StatusOK, w.Code)
  1020  	assert.Contains(t, w.Body.String(), "func New() *Engine {")
  1021  	assert.Equal(t, "text/plain; charset=utf-8", w.Header().Get("Content-Type"))
  1022  }
  1023  
  1024  func TestContextRenderFileFromFS(t *testing.T) {
  1025  	w := httptest.NewRecorder()
  1026  	c, _ := CreateTestContext(w)
  1027  
  1028  	c.Request, _ = http.NewRequest("GET", "/some/path", nil)
  1029  	c.FileFromFS("./gin.go", Dir(".", false))
  1030  
  1031  	assert.Equal(t, http.StatusOK, w.Code)
  1032  	assert.Contains(t, w.Body.String(), "func New() *Engine {")
  1033  	assert.Equal(t, "text/plain; charset=utf-8", w.Header().Get("Content-Type"))
  1034  	assert.Equal(t, "/some/path", c.Request.URL.Path)
  1035  }
  1036  
  1037  func TestContextRenderAttachment(t *testing.T) {
  1038  	w := httptest.NewRecorder()
  1039  	c, _ := CreateTestContext(w)
  1040  	newFilename := "new_filename.go"
  1041  
  1042  	c.Request, _ = http.NewRequest("GET", "/", nil)
  1043  	c.FileAttachment("./gin.go", newFilename)
  1044  
  1045  	assert.Equal(t, 200, w.Code)
  1046  	assert.Contains(t, w.Body.String(), "func New() *Engine {")
  1047  	assert.Equal(t, fmt.Sprintf("attachment; filename=\"%s\"", newFilename), w.HeaderMap.Get("Content-Disposition"))
  1048  }
  1049  
  1050  // TestContextRenderYAML tests that the response is serialized as YAML
  1051  // and Content-Type is set to application/x-yaml
  1052  func TestContextRenderYAML(t *testing.T) {
  1053  	w := httptest.NewRecorder()
  1054  	c, _ := CreateTestContext(w)
  1055  
  1056  	c.YAML(http.StatusCreated, H{"foo": "bar"})
  1057  
  1058  	assert.Equal(t, http.StatusCreated, w.Code)
  1059  	assert.Equal(t, "foo: bar\n", w.Body.String())
  1060  	assert.Equal(t, "application/x-yaml; charset=utf-8", w.Header().Get("Content-Type"))
  1061  }
  1062  
  1063  // TestContextRenderProtoBuf tests that the response is serialized as ProtoBuf
  1064  // and Content-Type is set to application/x-protobuf
  1065  // and we just use the example protobuf to check if the response is correct
  1066  func TestContextRenderProtoBuf(t *testing.T) {
  1067  	w := httptest.NewRecorder()
  1068  	c, _ := CreateTestContext(w)
  1069  
  1070  	reps := []int64{int64(1), int64(2)}
  1071  	label := "test"
  1072  	data := &testdata.Test{
  1073  		Label: &label,
  1074  		Reps:  reps,
  1075  	}
  1076  
  1077  	c.ProtoBuf(http.StatusCreated, data)
  1078  
  1079  	protoData, err := proto.Marshal(data)
  1080  	assert.NoError(t, err)
  1081  
  1082  	assert.Equal(t, http.StatusCreated, w.Code)
  1083  	assert.Equal(t, string(protoData), w.Body.String())
  1084  	assert.Equal(t, "application/x-protobuf", w.Header().Get("Content-Type"))
  1085  }
  1086  
  1087  func TestContextHeaders(t *testing.T) {
  1088  	c, _ := CreateTestContext(httptest.NewRecorder())
  1089  	c.Header("Content-Type", "text/plain")
  1090  	c.Header("X-Custom", "value")
  1091  
  1092  	assert.Equal(t, "text/plain", c.Writer.Header().Get("Content-Type"))
  1093  	assert.Equal(t, "value", c.Writer.Header().Get("X-Custom"))
  1094  
  1095  	c.Header("Content-Type", "text/html")
  1096  	c.Header("X-Custom", "")
  1097  
  1098  	assert.Equal(t, "text/html", c.Writer.Header().Get("Content-Type"))
  1099  	_, exist := c.Writer.Header()["X-Custom"]
  1100  	assert.False(t, exist)
  1101  }
  1102  
  1103  // TODO
  1104  func TestContextRenderRedirectWithRelativePath(t *testing.T) {
  1105  	w := httptest.NewRecorder()
  1106  	c, _ := CreateTestContext(w)
  1107  
  1108  	c.Request, _ = http.NewRequest("POST", "http://example.com", nil)
  1109  	assert.Panics(t, func() { c.Redirect(299, "/new_path") })
  1110  	assert.Panics(t, func() { c.Redirect(309, "/new_path") })
  1111  
  1112  	c.Redirect(http.StatusMovedPermanently, "/path")
  1113  	c.Writer.WriteHeaderNow()
  1114  	assert.Equal(t, http.StatusMovedPermanently, w.Code)
  1115  	assert.Equal(t, "/path", w.Header().Get("Location"))
  1116  }
  1117  
  1118  func TestContextRenderRedirectWithAbsolutePath(t *testing.T) {
  1119  	w := httptest.NewRecorder()
  1120  	c, _ := CreateTestContext(w)
  1121  
  1122  	c.Request, _ = http.NewRequest("POST", "http://example.com", nil)
  1123  	c.Redirect(http.StatusFound, "http://google.com")
  1124  	c.Writer.WriteHeaderNow()
  1125  
  1126  	assert.Equal(t, http.StatusFound, w.Code)
  1127  	assert.Equal(t, "http://google.com", w.Header().Get("Location"))
  1128  }
  1129  
  1130  func TestContextRenderRedirectWith201(t *testing.T) {
  1131  	w := httptest.NewRecorder()
  1132  	c, _ := CreateTestContext(w)
  1133  
  1134  	c.Request, _ = http.NewRequest("POST", "http://example.com", nil)
  1135  	c.Redirect(http.StatusCreated, "/resource")
  1136  	c.Writer.WriteHeaderNow()
  1137  
  1138  	assert.Equal(t, http.StatusCreated, w.Code)
  1139  	assert.Equal(t, "/resource", w.Header().Get("Location"))
  1140  }
  1141  
  1142  func TestContextRenderRedirectAll(t *testing.T) {
  1143  	c, _ := CreateTestContext(httptest.NewRecorder())
  1144  	c.Request, _ = http.NewRequest("POST", "http://example.com", nil)
  1145  	assert.Panics(t, func() { c.Redirect(http.StatusOK, "/resource") })
  1146  	assert.Panics(t, func() { c.Redirect(http.StatusAccepted, "/resource") })
  1147  	assert.Panics(t, func() { c.Redirect(299, "/resource") })
  1148  	assert.Panics(t, func() { c.Redirect(309, "/resource") })
  1149  	assert.NotPanics(t, func() { c.Redirect(http.StatusMultipleChoices, "/resource") })
  1150  	assert.NotPanics(t, func() { c.Redirect(http.StatusPermanentRedirect, "/resource") })
  1151  }
  1152  
  1153  func TestContextNegotiationWithJSON(t *testing.T) {
  1154  	w := httptest.NewRecorder()
  1155  	c, _ := CreateTestContext(w)
  1156  	c.Request, _ = http.NewRequest("POST", "", nil)
  1157  
  1158  	c.Negotiate(http.StatusOK, Negotiate{
  1159  		Offered: []string{MIMEJSON, MIMEXML, MIMEYAML},
  1160  		Data:    H{"foo": "bar"},
  1161  	})
  1162  
  1163  	assert.Equal(t, http.StatusOK, w.Code)
  1164  	assert.Equal(t, "{\"foo\":\"bar\"}", w.Body.String())
  1165  	assert.Equal(t, "application/json; charset=utf-8", w.Header().Get("Content-Type"))
  1166  }
  1167  
  1168  func TestContextNegotiationWithXML(t *testing.T) {
  1169  	w := httptest.NewRecorder()
  1170  	c, _ := CreateTestContext(w)
  1171  	c.Request, _ = http.NewRequest("POST", "", nil)
  1172  
  1173  	c.Negotiate(http.StatusOK, Negotiate{
  1174  		Offered: []string{MIMEXML, MIMEJSON, MIMEYAML},
  1175  		Data:    H{"foo": "bar"},
  1176  	})
  1177  
  1178  	assert.Equal(t, http.StatusOK, w.Code)
  1179  	assert.Equal(t, "<map><foo>bar</foo></map>", w.Body.String())
  1180  	assert.Equal(t, "application/xml; charset=utf-8", w.Header().Get("Content-Type"))
  1181  }
  1182  
  1183  func TestContextNegotiationWithHTML(t *testing.T) {
  1184  	w := httptest.NewRecorder()
  1185  	c, router := CreateTestContext(w)
  1186  	c.Request, _ = http.NewRequest("POST", "", nil)
  1187  	templ := template.Must(template.New("t").Parse(`Hello {{.name}}`))
  1188  	router.SetHTMLTemplate(templ)
  1189  
  1190  	c.Negotiate(http.StatusOK, Negotiate{
  1191  		Offered:  []string{MIMEHTML},
  1192  		Data:     H{"name": "gin"},
  1193  		HTMLName: "t",
  1194  	})
  1195  
  1196  	assert.Equal(t, http.StatusOK, w.Code)
  1197  	assert.Equal(t, "Hello gin", w.Body.String())
  1198  	assert.Equal(t, "text/html; charset=utf-8", w.Header().Get("Content-Type"))
  1199  }
  1200  
  1201  func TestContextNegotiationNotSupport(t *testing.T) {
  1202  	w := httptest.NewRecorder()
  1203  	c, _ := CreateTestContext(w)
  1204  	c.Request, _ = http.NewRequest("POST", "", nil)
  1205  
  1206  	c.Negotiate(http.StatusOK, Negotiate{
  1207  		Offered: []string{MIMEPOSTForm},
  1208  	})
  1209  
  1210  	assert.Equal(t, http.StatusNotAcceptable, w.Code)
  1211  	assert.Equal(t, c.index, abortIndex)
  1212  	assert.True(t, c.IsAborted())
  1213  }
  1214  
  1215  func TestContextNegotiationFormat(t *testing.T) {
  1216  	c, _ := CreateTestContext(httptest.NewRecorder())
  1217  	c.Request, _ = http.NewRequest("POST", "", nil)
  1218  
  1219  	assert.Panics(t, func() { c.NegotiateFormat() })
  1220  	assert.Equal(t, MIMEJSON, c.NegotiateFormat(MIMEJSON, MIMEXML))
  1221  	assert.Equal(t, MIMEHTML, c.NegotiateFormat(MIMEHTML, MIMEJSON))
  1222  }
  1223  
  1224  func TestContextNegotiationFormatWithAccept(t *testing.T) {
  1225  	c, _ := CreateTestContext(httptest.NewRecorder())
  1226  	c.Request, _ = http.NewRequest("POST", "/", nil)
  1227  	c.Request.Header.Add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9;q=0.8")
  1228  
  1229  	assert.Equal(t, MIMEXML, c.NegotiateFormat(MIMEJSON, MIMEXML))
  1230  	assert.Equal(t, MIMEHTML, c.NegotiateFormat(MIMEXML, MIMEHTML))
  1231  	assert.Empty(t, c.NegotiateFormat(MIMEJSON))
  1232  }
  1233  
  1234  func TestContextNegotiationFormatWithWildcardAccept(t *testing.T) {
  1235  	c, _ := CreateTestContext(httptest.NewRecorder())
  1236  	c.Request, _ = http.NewRequest("POST", "/", nil)
  1237  	c.Request.Header.Add("Accept", "*/*")
  1238  
  1239  	assert.Equal(t, c.NegotiateFormat("*/*"), "*/*")
  1240  	assert.Equal(t, c.NegotiateFormat("text/*"), "text/*")
  1241  	assert.Equal(t, c.NegotiateFormat("application/*"), "application/*")
  1242  	assert.Equal(t, c.NegotiateFormat(MIMEJSON), MIMEJSON)
  1243  	assert.Equal(t, c.NegotiateFormat(MIMEXML), MIMEXML)
  1244  	assert.Equal(t, c.NegotiateFormat(MIMEHTML), MIMEHTML)
  1245  
  1246  	c, _ = CreateTestContext(httptest.NewRecorder())
  1247  	c.Request, _ = http.NewRequest("POST", "/", nil)
  1248  	c.Request.Header.Add("Accept", "text/*")
  1249  
  1250  	assert.Equal(t, c.NegotiateFormat("*/*"), "*/*")
  1251  	assert.Equal(t, c.NegotiateFormat("text/*"), "text/*")
  1252  	assert.Equal(t, c.NegotiateFormat("application/*"), "")
  1253  	assert.Equal(t, c.NegotiateFormat(MIMEJSON), "")
  1254  	assert.Equal(t, c.NegotiateFormat(MIMEXML), "")
  1255  	assert.Equal(t, c.NegotiateFormat(MIMEHTML), MIMEHTML)
  1256  }
  1257  
  1258  func TestContextNegotiationFormatCustom(t *testing.T) {
  1259  	c, _ := CreateTestContext(httptest.NewRecorder())
  1260  	c.Request, _ = http.NewRequest("POST", "/", nil)
  1261  	c.Request.Header.Add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9;q=0.8")
  1262  
  1263  	c.Accepted = nil
  1264  	c.SetAccepted(MIMEJSON, MIMEXML)
  1265  
  1266  	assert.Equal(t, MIMEJSON, c.NegotiateFormat(MIMEJSON, MIMEXML))
  1267  	assert.Equal(t, MIMEXML, c.NegotiateFormat(MIMEXML, MIMEHTML))
  1268  	assert.Equal(t, MIMEJSON, c.NegotiateFormat(MIMEJSON))
  1269  }
  1270  
  1271  func TestContextIsAborted(t *testing.T) {
  1272  	c, _ := CreateTestContext(httptest.NewRecorder())
  1273  	assert.False(t, c.IsAborted())
  1274  
  1275  	c.Abort()
  1276  	assert.True(t, c.IsAborted())
  1277  
  1278  	c.Next()
  1279  	assert.True(t, c.IsAborted())
  1280  
  1281  	c.index++
  1282  	assert.True(t, c.IsAborted())
  1283  }
  1284  
  1285  // TestContextData tests that the response can be written from `bytestring`
  1286  // with specified MIME type
  1287  func TestContextAbortWithStatus(t *testing.T) {
  1288  	w := httptest.NewRecorder()
  1289  	c, _ := CreateTestContext(w)
  1290  
  1291  	c.index = 4
  1292  	c.AbortWithStatus(http.StatusUnauthorized)
  1293  
  1294  	assert.Equal(t, abortIndex, c.index)
  1295  	assert.Equal(t, http.StatusUnauthorized, c.Writer.Status())
  1296  	assert.Equal(t, http.StatusUnauthorized, w.Code)
  1297  	assert.True(t, c.IsAborted())
  1298  }
  1299  
  1300  type testJSONAbortMsg struct {
  1301  	Foo string `json:"foo"`
  1302  	Bar string `json:"bar"`
  1303  }
  1304  
  1305  func TestContextAbortWithStatusJSON(t *testing.T) {
  1306  	w := httptest.NewRecorder()
  1307  	c, _ := CreateTestContext(w)
  1308  	c.index = 4
  1309  
  1310  	in := new(testJSONAbortMsg)
  1311  	in.Bar = "barValue"
  1312  	in.Foo = "fooValue"
  1313  
  1314  	c.AbortWithStatusJSON(http.StatusUnsupportedMediaType, in)
  1315  
  1316  	assert.Equal(t, abortIndex, c.index)
  1317  	assert.Equal(t, http.StatusUnsupportedMediaType, c.Writer.Status())
  1318  	assert.Equal(t, http.StatusUnsupportedMediaType, w.Code)
  1319  	assert.True(t, c.IsAborted())
  1320  
  1321  	contentType := w.Header().Get("Content-Type")
  1322  	assert.Equal(t, "application/json; charset=utf-8", contentType)
  1323  
  1324  	buf := new(bytes.Buffer)
  1325  	_, err := buf.ReadFrom(w.Body)
  1326  	assert.NoError(t, err)
  1327  	jsonStringBody := buf.String()
  1328  	assert.Equal(t, fmt.Sprint("{\"foo\":\"fooValue\",\"bar\":\"barValue\"}"), jsonStringBody)
  1329  }
  1330  
  1331  func TestContextError(t *testing.T) {
  1332  	c, _ := CreateTestContext(httptest.NewRecorder())
  1333  	assert.Empty(t, c.Errors)
  1334  
  1335  	firstErr := errors.New("first error")
  1336  	c.Error(firstErr) // nolint: errcheck
  1337  	assert.Len(t, c.Errors, 1)
  1338  	assert.Equal(t, "Error #01: first error\n", c.Errors.String())
  1339  
  1340  	secondErr := errors.New("second error")
  1341  	c.Error(&Error{ // nolint: errcheck
  1342  		Err:  secondErr,
  1343  		Meta: "some data 2",
  1344  		Type: ErrorTypePublic,
  1345  	})
  1346  	assert.Len(t, c.Errors, 2)
  1347  
  1348  	assert.Equal(t, firstErr, c.Errors[0].Err)
  1349  	assert.Nil(t, c.Errors[0].Meta)
  1350  	assert.Equal(t, ErrorTypePrivate, c.Errors[0].Type)
  1351  
  1352  	assert.Equal(t, secondErr, c.Errors[1].Err)
  1353  	assert.Equal(t, "some data 2", c.Errors[1].Meta)
  1354  	assert.Equal(t, ErrorTypePublic, c.Errors[1].Type)
  1355  
  1356  	assert.Equal(t, c.Errors.Last(), c.Errors[1])
  1357  
  1358  	defer func() {
  1359  		if recover() == nil {
  1360  			t.Error("didn't panic")
  1361  		}
  1362  	}()
  1363  	c.Error(nil) // nolint: errcheck
  1364  }
  1365  
  1366  func TestContextTypedError(t *testing.T) {
  1367  	c, _ := CreateTestContext(httptest.NewRecorder())
  1368  	c.Error(errors.New("externo 0")).SetType(ErrorTypePublic)  // nolint: errcheck
  1369  	c.Error(errors.New("interno 0")).SetType(ErrorTypePrivate) // nolint: errcheck
  1370  
  1371  	for _, err := range c.Errors.ByType(ErrorTypePublic) {
  1372  		assert.Equal(t, ErrorTypePublic, err.Type)
  1373  	}
  1374  	for _, err := range c.Errors.ByType(ErrorTypePrivate) {
  1375  		assert.Equal(t, ErrorTypePrivate, err.Type)
  1376  	}
  1377  	assert.Equal(t, []string{"externo 0", "interno 0"}, c.Errors.Errors())
  1378  }
  1379  
  1380  func TestContextAbortWithError(t *testing.T) {
  1381  	w := httptest.NewRecorder()
  1382  	c, _ := CreateTestContext(w)
  1383  
  1384  	c.AbortWithError(http.StatusUnauthorized, errors.New("bad input")).SetMeta("some input") // nolint: errcheck
  1385  
  1386  	assert.Equal(t, http.StatusUnauthorized, w.Code)
  1387  	assert.Equal(t, abortIndex, c.index)
  1388  	assert.True(t, c.IsAborted())
  1389  }
  1390  
  1391  func resetTrustedCIDRs(c *Context) {
  1392  	c.engine.trustedCIDRs, _ = c.engine.prepareTrustedCIDRs()
  1393  }
  1394  
  1395  func TestContextClientIP(t *testing.T) {
  1396  	c, _ := CreateTestContext(httptest.NewRecorder())
  1397  	c.Request, _ = http.NewRequest("POST", "/", nil)
  1398  	resetTrustedCIDRs(c)
  1399  	resetContextForClientIPTests(c)
  1400  
  1401  	// Legacy tests (validating that the defaults don't break the
  1402  	// (insecure!) old behaviour)
  1403  	assert.Equal(t, "20.20.20.20", c.ClientIP())
  1404  
  1405  	c.Request.Header.Del("X-Forwarded-For")
  1406  	assert.Equal(t, "10.10.10.10", c.ClientIP())
  1407  
  1408  	c.Request.Header.Set("X-Forwarded-For", "30.30.30.30  ")
  1409  	assert.Equal(t, "30.30.30.30", c.ClientIP())
  1410  
  1411  	c.Request.Header.Del("X-Forwarded-For")
  1412  	c.Request.Header.Del("X-Real-IP")
  1413  	c.engine.AppEngine = true
  1414  	assert.Equal(t, "50.50.50.50", c.ClientIP())
  1415  
  1416  	c.Request.Header.Del("X-Appengine-Remote-Addr")
  1417  	assert.Equal(t, "40.40.40.40", c.ClientIP())
  1418  
  1419  	// no port
  1420  	c.Request.RemoteAddr = "50.50.50.50"
  1421  	assert.Empty(t, c.ClientIP())
  1422  
  1423  	// Tests exercising the TrustedProxies functionality
  1424  	resetContextForClientIPTests(c)
  1425  
  1426  	// No trusted proxies
  1427  	c.engine.TrustedProxies = []string{}
  1428  	resetTrustedCIDRs(c)
  1429  	c.engine.RemoteIPHeaders = []string{"X-Forwarded-For"}
  1430  	assert.Equal(t, "40.40.40.40", c.ClientIP())
  1431  
  1432  	// Last proxy is trusted, but the RemoteAddr is not
  1433  	c.engine.TrustedProxies = []string{"30.30.30.30"}
  1434  	resetTrustedCIDRs(c)
  1435  	assert.Equal(t, "40.40.40.40", c.ClientIP())
  1436  
  1437  	// Only trust RemoteAddr
  1438  	c.engine.TrustedProxies = []string{"40.40.40.40"}
  1439  	resetTrustedCIDRs(c)
  1440  	assert.Equal(t, "20.20.20.20", c.ClientIP())
  1441  
  1442  	// All steps are trusted
  1443  	c.engine.TrustedProxies = []string{"40.40.40.40", "30.30.30.30", "20.20.20.20"}
  1444  	resetTrustedCIDRs(c)
  1445  	assert.Equal(t, "20.20.20.20", c.ClientIP())
  1446  
  1447  	// Use CIDR
  1448  	c.engine.TrustedProxies = []string{"40.40.25.25/16", "30.30.30.30"}
  1449  	resetTrustedCIDRs(c)
  1450  	assert.Equal(t, "20.20.20.20", c.ClientIP())
  1451  
  1452  	// Use hostname that resolves to all the proxies
  1453  	c.engine.TrustedProxies = []string{"foo"}
  1454  	resetTrustedCIDRs(c)
  1455  	assert.Equal(t, "40.40.40.40", c.ClientIP())
  1456  
  1457  	// Use hostname that returns an error
  1458  	c.engine.TrustedProxies = []string{"bar"}
  1459  	resetTrustedCIDRs(c)
  1460  	assert.Equal(t, "40.40.40.40", c.ClientIP())
  1461  
  1462  	// X-Forwarded-For has a non-IP element
  1463  	c.engine.TrustedProxies = []string{"40.40.40.40"}
  1464  	resetTrustedCIDRs(c)
  1465  	c.Request.Header.Set("X-Forwarded-For", " blah ")
  1466  	assert.Equal(t, "40.40.40.40", c.ClientIP())
  1467  
  1468  	// Result from LookupHost has non-IP element. This should never
  1469  	// happen, but we should test it to make sure we handle it
  1470  	// gracefully.
  1471  	c.engine.TrustedProxies = []string{"baz"}
  1472  	resetTrustedCIDRs(c)
  1473  	c.Request.Header.Set("X-Forwarded-For", " 30.30.30.30 ")
  1474  	assert.Equal(t, "40.40.40.40", c.ClientIP())
  1475  
  1476  	c.engine.TrustedProxies = []string{"40.40.40.40"}
  1477  	resetTrustedCIDRs(c)
  1478  	c.Request.Header.Del("X-Forwarded-For")
  1479  	c.engine.RemoteIPHeaders = []string{"X-Forwarded-For", "X-Real-IP"}
  1480  	assert.Equal(t, "10.10.10.10", c.ClientIP())
  1481  
  1482  	c.engine.RemoteIPHeaders = []string{}
  1483  	c.engine.AppEngine = true
  1484  	assert.Equal(t, "50.50.50.50", c.ClientIP())
  1485  
  1486  	c.Request.Header.Del("X-Appengine-Remote-Addr")
  1487  	assert.Equal(t, "40.40.40.40", c.ClientIP())
  1488  
  1489  	// no port
  1490  	c.Request.RemoteAddr = "50.50.50.50"
  1491  	assert.Empty(t, c.ClientIP())
  1492  }
  1493  
  1494  func resetContextForClientIPTests(c *Context) {
  1495  	c.Request.Header.Set("X-Real-IP", " 10.10.10.10  ")
  1496  	c.Request.Header.Set("X-Forwarded-For", "  20.20.20.20, 30.30.30.30")
  1497  	c.Request.Header.Set("X-Appengine-Remote-Addr", "50.50.50.50")
  1498  	c.Request.RemoteAddr = "  40.40.40.40:42123 "
  1499  	c.engine.AppEngine = false
  1500  }
  1501  
  1502  func TestContextContentType(t *testing.T) {
  1503  	c, _ := CreateTestContext(httptest.NewRecorder())
  1504  	c.Request, _ = http.NewRequest("POST", "/", nil)
  1505  	c.Request.Header.Set("Content-Type", "application/json; charset=utf-8")
  1506  
  1507  	assert.Equal(t, "application/json", c.ContentType())
  1508  }
  1509  
  1510  func TestContextAutoBindJSON(t *testing.T) {
  1511  	c, _ := CreateTestContext(httptest.NewRecorder())
  1512  	c.Request, _ = http.NewRequest("POST", "/", bytes.NewBufferString("{\"foo\":\"bar\", \"bar\":\"foo\"}"))
  1513  	c.Request.Header.Add("Content-Type", MIMEJSON)
  1514  
  1515  	var obj struct {
  1516  		Foo string `json:"foo"`
  1517  		Bar string `json:"bar"`
  1518  	}
  1519  	assert.NoError(t, c.Bind(&obj))
  1520  	assert.Equal(t, "foo", obj.Bar)
  1521  	assert.Equal(t, "bar", obj.Foo)
  1522  	assert.Empty(t, c.Errors)
  1523  }
  1524  
  1525  func TestContextBindWithJSON(t *testing.T) {
  1526  	w := httptest.NewRecorder()
  1527  	c, _ := CreateTestContext(w)
  1528  
  1529  	c.Request, _ = http.NewRequest("POST", "/", bytes.NewBufferString("{\"foo\":\"bar\", \"bar\":\"foo\"}"))
  1530  	c.Request.Header.Add("Content-Type", MIMEXML) // set fake content-type
  1531  
  1532  	var obj struct {
  1533  		Foo string `json:"foo"`
  1534  		Bar string `json:"bar"`
  1535  	}
  1536  	assert.NoError(t, c.BindJSON(&obj))
  1537  	assert.Equal(t, "foo", obj.Bar)
  1538  	assert.Equal(t, "bar", obj.Foo)
  1539  	assert.Equal(t, 0, w.Body.Len())
  1540  }
  1541  func TestContextBindWithXML(t *testing.T) {
  1542  	w := httptest.NewRecorder()
  1543  	c, _ := CreateTestContext(w)
  1544  
  1545  	c.Request, _ = http.NewRequest("POST", "/", bytes.NewBufferString(`<?xml version="1.0" encoding="UTF-8"?>
  1546  		<root>
  1547  			<foo>FOO</foo>
  1548  		   	<bar>BAR</bar>
  1549  		</root>`))
  1550  	c.Request.Header.Add("Content-Type", MIMEXML) // set fake content-type
  1551  
  1552  	var obj struct {
  1553  		Foo string `xml:"foo"`
  1554  		Bar string `xml:"bar"`
  1555  	}
  1556  	assert.NoError(t, c.BindXML(&obj))
  1557  	assert.Equal(t, "FOO", obj.Foo)
  1558  	assert.Equal(t, "BAR", obj.Bar)
  1559  	assert.Equal(t, 0, w.Body.Len())
  1560  }
  1561  
  1562  func TestContextBindHeader(t *testing.T) {
  1563  	w := httptest.NewRecorder()
  1564  	c, _ := CreateTestContext(w)
  1565  
  1566  	c.Request, _ = http.NewRequest("POST", "/", nil)
  1567  	c.Request.Header.Add("rate", "8000")
  1568  	c.Request.Header.Add("domain", "music")
  1569  	c.Request.Header.Add("limit", "1000")
  1570  
  1571  	var testHeader struct {
  1572  		Rate   int    `header:"Rate"`
  1573  		Domain string `header:"Domain"`
  1574  		Limit  int    `header:"limit"`
  1575  	}
  1576  
  1577  	assert.NoError(t, c.BindHeader(&testHeader))
  1578  	assert.Equal(t, 8000, testHeader.Rate)
  1579  	assert.Equal(t, "music", testHeader.Domain)
  1580  	assert.Equal(t, 1000, testHeader.Limit)
  1581  	assert.Equal(t, 0, w.Body.Len())
  1582  }
  1583  
  1584  func TestContextBindWithQuery(t *testing.T) {
  1585  	w := httptest.NewRecorder()
  1586  	c, _ := CreateTestContext(w)
  1587  
  1588  	c.Request, _ = http.NewRequest("POST", "/?foo=bar&bar=foo", bytes.NewBufferString("foo=unused"))
  1589  
  1590  	var obj struct {
  1591  		Foo string `form:"foo"`
  1592  		Bar string `form:"bar"`
  1593  	}
  1594  	assert.NoError(t, c.BindQuery(&obj))
  1595  	assert.Equal(t, "foo", obj.Bar)
  1596  	assert.Equal(t, "bar", obj.Foo)
  1597  	assert.Equal(t, 0, w.Body.Len())
  1598  }
  1599  
  1600  func TestContextBindWithYAML(t *testing.T) {
  1601  	w := httptest.NewRecorder()
  1602  	c, _ := CreateTestContext(w)
  1603  
  1604  	c.Request, _ = http.NewRequest("POST", "/", bytes.NewBufferString("foo: bar\nbar: foo"))
  1605  	c.Request.Header.Add("Content-Type", MIMEXML) // set fake content-type
  1606  
  1607  	var obj struct {
  1608  		Foo string `yaml:"foo"`
  1609  		Bar string `yaml:"bar"`
  1610  	}
  1611  	assert.NoError(t, c.BindYAML(&obj))
  1612  	assert.Equal(t, "foo", obj.Bar)
  1613  	assert.Equal(t, "bar", obj.Foo)
  1614  	assert.Equal(t, 0, w.Body.Len())
  1615  }
  1616  
  1617  func TestContextBadAutoBind(t *testing.T) {
  1618  	w := httptest.NewRecorder()
  1619  	c, _ := CreateTestContext(w)
  1620  
  1621  	c.Request, _ = http.NewRequest("POST", "http://example.com", bytes.NewBufferString("\"foo\":\"bar\", \"bar\":\"foo\"}"))
  1622  	c.Request.Header.Add("Content-Type", MIMEJSON)
  1623  	var obj struct {
  1624  		Foo string `json:"foo"`
  1625  		Bar string `json:"bar"`
  1626  	}
  1627  
  1628  	assert.False(t, c.IsAborted())
  1629  	assert.Error(t, c.Bind(&obj))
  1630  	c.Writer.WriteHeaderNow()
  1631  
  1632  	assert.Empty(t, obj.Bar)
  1633  	assert.Empty(t, obj.Foo)
  1634  	assert.Equal(t, http.StatusBadRequest, w.Code)
  1635  	assert.True(t, c.IsAborted())
  1636  }
  1637  
  1638  func TestContextAutoShouldBindJSON(t *testing.T) {
  1639  	c, _ := CreateTestContext(httptest.NewRecorder())
  1640  	c.Request, _ = http.NewRequest("POST", "/", bytes.NewBufferString("{\"foo\":\"bar\", \"bar\":\"foo\"}"))
  1641  	c.Request.Header.Add("Content-Type", MIMEJSON)
  1642  
  1643  	var obj struct {
  1644  		Foo string `json:"foo"`
  1645  		Bar string `json:"bar"`
  1646  	}
  1647  	assert.NoError(t, c.ShouldBind(&obj))
  1648  	assert.Equal(t, "foo", obj.Bar)
  1649  	assert.Equal(t, "bar", obj.Foo)
  1650  	assert.Empty(t, c.Errors)
  1651  }
  1652  
  1653  func TestContextShouldBindWithJSON(t *testing.T) {
  1654  	w := httptest.NewRecorder()
  1655  	c, _ := CreateTestContext(w)
  1656  
  1657  	c.Request, _ = http.NewRequest("POST", "/", bytes.NewBufferString("{\"foo\":\"bar\", \"bar\":\"foo\"}"))
  1658  	c.Request.Header.Add("Content-Type", MIMEXML) // set fake content-type
  1659  
  1660  	var obj struct {
  1661  		Foo string `json:"foo"`
  1662  		Bar string `json:"bar"`
  1663  	}
  1664  	assert.NoError(t, c.ShouldBindJSON(&obj))
  1665  	assert.Equal(t, "foo", obj.Bar)
  1666  	assert.Equal(t, "bar", obj.Foo)
  1667  	assert.Equal(t, 0, w.Body.Len())
  1668  }
  1669  
  1670  func TestContextShouldBindWithXML(t *testing.T) {
  1671  	w := httptest.NewRecorder()
  1672  	c, _ := CreateTestContext(w)
  1673  
  1674  	c.Request, _ = http.NewRequest("POST", "/", bytes.NewBufferString(`<?xml version="1.0" encoding="UTF-8"?>
  1675  		<root>
  1676  			<foo>FOO</foo>
  1677  			<bar>BAR</bar>
  1678  		</root>`))
  1679  	c.Request.Header.Add("Content-Type", MIMEXML) // set fake content-type
  1680  
  1681  	var obj struct {
  1682  		Foo string `xml:"foo"`
  1683  		Bar string `xml:"bar"`
  1684  	}
  1685  	assert.NoError(t, c.ShouldBindXML(&obj))
  1686  	assert.Equal(t, "FOO", obj.Foo)
  1687  	assert.Equal(t, "BAR", obj.Bar)
  1688  	assert.Equal(t, 0, w.Body.Len())
  1689  }
  1690  
  1691  func TestContextShouldBindHeader(t *testing.T) {
  1692  	w := httptest.NewRecorder()
  1693  	c, _ := CreateTestContext(w)
  1694  
  1695  	c.Request, _ = http.NewRequest("POST", "/", nil)
  1696  	c.Request.Header.Add("rate", "8000")
  1697  	c.Request.Header.Add("domain", "music")
  1698  	c.Request.Header.Add("limit", "1000")
  1699  
  1700  	var testHeader struct {
  1701  		Rate   int    `header:"Rate"`
  1702  		Domain string `header:"Domain"`
  1703  		Limit  int    `header:"limit"`
  1704  	}
  1705  
  1706  	assert.NoError(t, c.ShouldBindHeader(&testHeader))
  1707  	assert.Equal(t, 8000, testHeader.Rate)
  1708  	assert.Equal(t, "music", testHeader.Domain)
  1709  	assert.Equal(t, 1000, testHeader.Limit)
  1710  	assert.Equal(t, 0, w.Body.Len())
  1711  }
  1712  
  1713  func TestContextShouldBindWithQuery(t *testing.T) {
  1714  	w := httptest.NewRecorder()
  1715  	c, _ := CreateTestContext(w)
  1716  
  1717  	c.Request, _ = http.NewRequest("POST", "/?foo=bar&bar=foo&Foo=bar1&Bar=foo1", bytes.NewBufferString("foo=unused"))
  1718  
  1719  	var obj struct {
  1720  		Foo  string `form:"foo"`
  1721  		Bar  string `form:"bar"`
  1722  		Foo1 string `form:"Foo"`
  1723  		Bar1 string `form:"Bar"`
  1724  	}
  1725  	assert.NoError(t, c.ShouldBindQuery(&obj))
  1726  	assert.Equal(t, "foo", obj.Bar)
  1727  	assert.Equal(t, "bar", obj.Foo)
  1728  	assert.Equal(t, "foo1", obj.Bar1)
  1729  	assert.Equal(t, "bar1", obj.Foo1)
  1730  	assert.Equal(t, 0, w.Body.Len())
  1731  }
  1732  
  1733  func TestContextShouldBindWithYAML(t *testing.T) {
  1734  	w := httptest.NewRecorder()
  1735  	c, _ := CreateTestContext(w)
  1736  
  1737  	c.Request, _ = http.NewRequest("POST", "/", bytes.NewBufferString("foo: bar\nbar: foo"))
  1738  	c.Request.Header.Add("Content-Type", MIMEXML) // set fake content-type
  1739  
  1740  	var obj struct {
  1741  		Foo string `yaml:"foo"`
  1742  		Bar string `yaml:"bar"`
  1743  	}
  1744  	assert.NoError(t, c.ShouldBindYAML(&obj))
  1745  	assert.Equal(t, "foo", obj.Bar)
  1746  	assert.Equal(t, "bar", obj.Foo)
  1747  	assert.Equal(t, 0, w.Body.Len())
  1748  }
  1749  
  1750  func TestContextBadAutoShouldBind(t *testing.T) {
  1751  	w := httptest.NewRecorder()
  1752  	c, _ := CreateTestContext(w)
  1753  
  1754  	c.Request, _ = http.NewRequest("POST", "http://example.com", bytes.NewBufferString("\"foo\":\"bar\", \"bar\":\"foo\"}"))
  1755  	c.Request.Header.Add("Content-Type", MIMEJSON)
  1756  	var obj struct {
  1757  		Foo string `json:"foo"`
  1758  		Bar string `json:"bar"`
  1759  	}
  1760  
  1761  	assert.False(t, c.IsAborted())
  1762  	assert.Error(t, c.ShouldBind(&obj))
  1763  
  1764  	assert.Empty(t, obj.Bar)
  1765  	assert.Empty(t, obj.Foo)
  1766  	assert.False(t, c.IsAborted())
  1767  }
  1768  
  1769  func TestContextShouldBindBodyWith(t *testing.T) {
  1770  	type typeA struct {
  1771  		Foo string `json:"foo" xml:"foo" binding:"required"`
  1772  	}
  1773  	type typeB struct {
  1774  		Bar string `json:"bar" xml:"bar" binding:"required"`
  1775  	}
  1776  	for _, tt := range []struct {
  1777  		name               string
  1778  		bindingA, bindingB binding.BindingBody
  1779  		bodyA, bodyB       string
  1780  	}{
  1781  		{
  1782  			name:     "JSON & JSON",
  1783  			bindingA: binding.JSON,
  1784  			bindingB: binding.JSON,
  1785  			bodyA:    `{"foo":"FOO"}`,
  1786  			bodyB:    `{"bar":"BAR"}`,
  1787  		},
  1788  		{
  1789  			name:     "JSON & XML",
  1790  			bindingA: binding.JSON,
  1791  			bindingB: binding.XML,
  1792  			bodyA:    `{"foo":"FOO"}`,
  1793  			bodyB: `<?xml version="1.0" encoding="UTF-8"?>
  1794  <root>
  1795     <bar>BAR</bar>
  1796  </root>`,
  1797  		},
  1798  		{
  1799  			name:     "XML & XML",
  1800  			bindingA: binding.XML,
  1801  			bindingB: binding.XML,
  1802  			bodyA: `<?xml version="1.0" encoding="UTF-8"?>
  1803  <root>
  1804     <foo>FOO</foo>
  1805  </root>`,
  1806  			bodyB: `<?xml version="1.0" encoding="UTF-8"?>
  1807  <root>
  1808     <bar>BAR</bar>
  1809  </root>`,
  1810  		},
  1811  	} {
  1812  		t.Logf("testing: %s", tt.name)
  1813  		// bodyA to typeA and typeB
  1814  		{
  1815  			w := httptest.NewRecorder()
  1816  			c, _ := CreateTestContext(w)
  1817  			c.Request, _ = http.NewRequest(
  1818  				"POST", "http://example.com", bytes.NewBufferString(tt.bodyA),
  1819  			)
  1820  			// When it binds to typeA and typeB, it finds the body is
  1821  			// not typeB but typeA.
  1822  			objA := typeA{}
  1823  			assert.NoError(t, c.ShouldBindBodyWith(&objA, tt.bindingA))
  1824  			assert.Equal(t, typeA{"FOO"}, objA)
  1825  			objB := typeB{}
  1826  			assert.Error(t, c.ShouldBindBodyWith(&objB, tt.bindingB))
  1827  			assert.NotEqual(t, typeB{"BAR"}, objB)
  1828  		}
  1829  		// bodyB to typeA and typeB
  1830  		{
  1831  			// When it binds to typeA and typeB, it finds the body is
  1832  			// not typeA but typeB.
  1833  			w := httptest.NewRecorder()
  1834  			c, _ := CreateTestContext(w)
  1835  			c.Request, _ = http.NewRequest(
  1836  				"POST", "http://example.com", bytes.NewBufferString(tt.bodyB),
  1837  			)
  1838  			objA := typeA{}
  1839  			assert.Error(t, c.ShouldBindBodyWith(&objA, tt.bindingA))
  1840  			assert.NotEqual(t, typeA{"FOO"}, objA)
  1841  			objB := typeB{}
  1842  			assert.NoError(t, c.ShouldBindBodyWith(&objB, tt.bindingB))
  1843  			assert.Equal(t, typeB{"BAR"}, objB)
  1844  		}
  1845  	}
  1846  }
  1847  
  1848  func TestContextGolangContext(t *testing.T) {
  1849  	c, _ := CreateTestContext(httptest.NewRecorder())
  1850  	c.Request, _ = http.NewRequest("POST", "/", bytes.NewBufferString("{\"foo\":\"bar\", \"bar\":\"foo\"}"))
  1851  	assert.NoError(t, c.Err())
  1852  	assert.Nil(t, c.Done())
  1853  	ti, ok := c.Deadline()
  1854  	assert.Equal(t, ti, time.Time{})
  1855  	assert.False(t, ok)
  1856  	assert.Equal(t, c.Value(0), c.Request)
  1857  	assert.Nil(t, c.Value("foo"))
  1858  
  1859  	c.Set("foo", "bar")
  1860  	assert.Equal(t, "bar", c.Value("foo"))
  1861  	assert.Nil(t, c.Value(1))
  1862  }
  1863  
  1864  func TestWebsocketsRequired(t *testing.T) {
  1865  	// Example request from spec: https://tools.ietf.org/html/rfc6455#section-1.2
  1866  	c, _ := CreateTestContext(httptest.NewRecorder())
  1867  	c.Request, _ = http.NewRequest("GET", "/chat", nil)
  1868  	c.Request.Header.Set("Host", "server.example.com")
  1869  	c.Request.Header.Set("Upgrade", "websocket")
  1870  	c.Request.Header.Set("Connection", "Upgrade")
  1871  	c.Request.Header.Set("Sec-WebSocket-Key", "dGhlIHNhbXBsZSBub25jZQ==")
  1872  	c.Request.Header.Set("Origin", "http://example.com")
  1873  	c.Request.Header.Set("Sec-WebSocket-Protocol", "chat, superchat")
  1874  	c.Request.Header.Set("Sec-WebSocket-Version", "13")
  1875  
  1876  	assert.True(t, c.IsWebsocket())
  1877  
  1878  	// Normal request, no websocket required.
  1879  	c, _ = CreateTestContext(httptest.NewRecorder())
  1880  	c.Request, _ = http.NewRequest("GET", "/chat", nil)
  1881  	c.Request.Header.Set("Host", "server.example.com")
  1882  
  1883  	assert.False(t, c.IsWebsocket())
  1884  }
  1885  
  1886  func TestGetRequestHeaderValue(t *testing.T) {
  1887  	c, _ := CreateTestContext(httptest.NewRecorder())
  1888  	c.Request, _ = http.NewRequest("GET", "/chat", nil)
  1889  	c.Request.Header.Set("Gin-Version", "1.0.0")
  1890  
  1891  	assert.Equal(t, "1.0.0", c.GetHeader("Gin-Version"))
  1892  	assert.Empty(t, c.GetHeader("Connection"))
  1893  }
  1894  
  1895  func TestContextGetRawData(t *testing.T) {
  1896  	c, _ := CreateTestContext(httptest.NewRecorder())
  1897  	body := bytes.NewBufferString("Fetch binary post data")
  1898  	c.Request, _ = http.NewRequest("POST", "/", body)
  1899  	c.Request.Header.Add("Content-Type", MIMEPOSTForm)
  1900  
  1901  	data, err := c.GetRawData()
  1902  	assert.Nil(t, err)
  1903  	assert.Equal(t, "Fetch binary post data", string(data))
  1904  }
  1905  
  1906  func TestContextRenderDataFromReader(t *testing.T) {
  1907  	w := httptest.NewRecorder()
  1908  	c, _ := CreateTestContext(w)
  1909  
  1910  	body := "#!PNG some raw data"
  1911  	reader := strings.NewReader(body)
  1912  	contentLength := int64(len(body))
  1913  	contentType := "image/png"
  1914  	extraHeaders := map[string]string{"Content-Disposition": `attachment; filename="gopher.png"`}
  1915  
  1916  	c.DataFromReader(http.StatusOK, contentLength, contentType, reader, extraHeaders)
  1917  
  1918  	assert.Equal(t, http.StatusOK, w.Code)
  1919  	assert.Equal(t, body, w.Body.String())
  1920  	assert.Equal(t, contentType, w.Header().Get("Content-Type"))
  1921  	assert.Equal(t, fmt.Sprintf("%d", contentLength), w.Header().Get("Content-Length"))
  1922  	assert.Equal(t, extraHeaders["Content-Disposition"], w.Header().Get("Content-Disposition"))
  1923  }
  1924  
  1925  func TestContextRenderDataFromReaderNoHeaders(t *testing.T) {
  1926  	w := httptest.NewRecorder()
  1927  	c, _ := CreateTestContext(w)
  1928  
  1929  	body := "#!PNG some raw data"
  1930  	reader := strings.NewReader(body)
  1931  	contentLength := int64(len(body))
  1932  	contentType := "image/png"
  1933  
  1934  	c.DataFromReader(http.StatusOK, contentLength, contentType, reader, nil)
  1935  
  1936  	assert.Equal(t, http.StatusOK, w.Code)
  1937  	assert.Equal(t, body, w.Body.String())
  1938  	assert.Equal(t, contentType, w.Header().Get("Content-Type"))
  1939  	assert.Equal(t, fmt.Sprintf("%d", contentLength), w.Header().Get("Content-Length"))
  1940  }
  1941  
  1942  type TestResponseRecorder struct {
  1943  	*httptest.ResponseRecorder
  1944  	closeChannel chan bool
  1945  }
  1946  
  1947  func (r *TestResponseRecorder) CloseNotify() <-chan bool {
  1948  	return r.closeChannel
  1949  }
  1950  
  1951  func (r *TestResponseRecorder) closeClient() {
  1952  	r.closeChannel <- true
  1953  }
  1954  
  1955  func CreateTestResponseRecorder() *TestResponseRecorder {
  1956  	return &TestResponseRecorder{
  1957  		httptest.NewRecorder(),
  1958  		make(chan bool, 1),
  1959  	}
  1960  }
  1961  
  1962  func TestContextStream(t *testing.T) {
  1963  	w := CreateTestResponseRecorder()
  1964  	c, _ := CreateTestContext(w)
  1965  
  1966  	stopStream := true
  1967  	c.Stream(func(w io.Writer) bool {
  1968  		defer func() {
  1969  			stopStream = false
  1970  		}()
  1971  
  1972  		_, err := w.Write([]byte("test"))
  1973  		assert.NoError(t, err)
  1974  
  1975  		return stopStream
  1976  	})
  1977  
  1978  	assert.Equal(t, "testtest", w.Body.String())
  1979  }
  1980  
  1981  func TestContextStreamWithClientGone(t *testing.T) {
  1982  	w := CreateTestResponseRecorder()
  1983  	c, _ := CreateTestContext(w)
  1984  
  1985  	c.Stream(func(writer io.Writer) bool {
  1986  		defer func() {
  1987  			w.closeClient()
  1988  		}()
  1989  
  1990  		_, err := writer.Write([]byte("test"))
  1991  		assert.NoError(t, err)
  1992  
  1993  		return true
  1994  	})
  1995  
  1996  	assert.Equal(t, "test", w.Body.String())
  1997  }
  1998  
  1999  func TestContextResetInHandler(t *testing.T) {
  2000  	w := CreateTestResponseRecorder()
  2001  	c, _ := CreateTestContext(w)
  2002  
  2003  	c.handlers = []HandlerFunc{
  2004  		func(c *Context) { c.reset() },
  2005  	}
  2006  	assert.NotPanics(t, func() {
  2007  		c.Next()
  2008  	})
  2009  }
  2010  
  2011  func TestRaceParamsContextCopy(t *testing.T) {
  2012  	DefaultWriter = os.Stdout
  2013  	router := Default()
  2014  	nameGroup := router.Group("/:name")
  2015  	var wg sync.WaitGroup
  2016  	wg.Add(2)
  2017  	{
  2018  		nameGroup.GET("/api", func(c *Context) {
  2019  			go func(c *Context, param string) {
  2020  				defer wg.Done()
  2021  				// First assert must be executed after the second request
  2022  				time.Sleep(50 * time.Millisecond)
  2023  				assert.Equal(t, c.Param("name"), param)
  2024  			}(c.Copy(), c.Param("name"))
  2025  		})
  2026  	}
  2027  	performRequest(router, "GET", "/name1/api")
  2028  	performRequest(router, "GET", "/name2/api")
  2029  	wg.Wait()
  2030  }
  2031  
  2032  func TestContextWithKeysMutex(t *testing.T) {
  2033  	c := &Context{}
  2034  	c.Set("foo", "bar")
  2035  
  2036  	value, err := c.Get("foo")
  2037  	assert.Equal(t, "bar", value)
  2038  	assert.True(t, err)
  2039  
  2040  	value, err = c.Get("foo2")
  2041  	assert.Nil(t, value)
  2042  	assert.False(t, err)
  2043  }
  2044  
  2045  func TestRemoteIPFail(t *testing.T) {
  2046  	c, _ := CreateTestContext(httptest.NewRecorder())
  2047  	c.Request, _ = http.NewRequest("POST", "/", nil)
  2048  	c.Request.RemoteAddr = "[:::]:80"
  2049  	ip, trust := c.RemoteIP()
  2050  	assert.Nil(t, ip)
  2051  	assert.False(t, trust)
  2052  }