context_test.go 55 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823
  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. package gin
  5. import (
  6. "bytes"
  7. "errors"
  8. "fmt"
  9. "html/template"
  10. "io"
  11. "mime/multipart"
  12. "net/http"
  13. "net/http/httptest"
  14. "reflect"
  15. "strings"
  16. "testing"
  17. "time"
  18. "github.com/gin-contrib/sse"
  19. "github.com/gin-gonic/gin/binding"
  20. "github.com/golang/protobuf/proto"
  21. "github.com/stretchr/testify/assert"
  22. "golang.org/x/net/context"
  23. testdata "github.com/gin-gonic/gin/testdata/protoexample"
  24. )
  25. var _ context.Context = &Context{}
  26. // Unit tests TODO
  27. // func (c *Context) File(filepath string) {
  28. // func (c *Context) Negotiate(code int, config Negotiate) {
  29. // BAD case: func (c *Context) Render(code int, render render.Render, obj ...interface{}) {
  30. // test that information is not leaked when reusing Contexts (using the Pool)
  31. func createMultipartRequest() *http.Request {
  32. boundary := "--testboundary"
  33. body := new(bytes.Buffer)
  34. mw := multipart.NewWriter(body)
  35. defer mw.Close()
  36. must(mw.SetBoundary(boundary))
  37. must(mw.WriteField("foo", "bar"))
  38. must(mw.WriteField("bar", "10"))
  39. must(mw.WriteField("bar", "foo2"))
  40. must(mw.WriteField("array", "first"))
  41. must(mw.WriteField("array", "second"))
  42. must(mw.WriteField("id", ""))
  43. must(mw.WriteField("time_local", "31/12/2016 14:55"))
  44. must(mw.WriteField("time_utc", "31/12/2016 14:55"))
  45. must(mw.WriteField("time_location", "31/12/2016 14:55"))
  46. must(mw.WriteField("names[a]", "thinkerou"))
  47. must(mw.WriteField("names[b]", "tianou"))
  48. req, err := http.NewRequest("POST", "/", body)
  49. must(err)
  50. req.Header.Set("Content-Type", MIMEMultipartPOSTForm+"; boundary="+boundary)
  51. return req
  52. }
  53. func must(err error) {
  54. if err != nil {
  55. panic(err.Error())
  56. }
  57. }
  58. func TestContextFormFile(t *testing.T) {
  59. buf := new(bytes.Buffer)
  60. mw := multipart.NewWriter(buf)
  61. w, err := mw.CreateFormFile("file", "test")
  62. if assert.NoError(t, err) {
  63. _, err = w.Write([]byte("test"))
  64. assert.NoError(t, err)
  65. }
  66. mw.Close()
  67. c, _ := CreateTestContext(httptest.NewRecorder())
  68. c.Request, _ = http.NewRequest("POST", "/", buf)
  69. c.Request.Header.Set("Content-Type", mw.FormDataContentType())
  70. f, err := c.FormFile("file")
  71. if assert.NoError(t, err) {
  72. assert.Equal(t, "test", f.Filename)
  73. }
  74. assert.NoError(t, c.SaveUploadedFile(f, "test"))
  75. }
  76. func TestContextFormFileFailed(t *testing.T) {
  77. buf := new(bytes.Buffer)
  78. mw := multipart.NewWriter(buf)
  79. mw.Close()
  80. c, _ := CreateTestContext(httptest.NewRecorder())
  81. c.Request, _ = http.NewRequest("POST", "/", nil)
  82. c.Request.Header.Set("Content-Type", mw.FormDataContentType())
  83. c.engine.MaxMultipartMemory = 8 << 20
  84. f, err := c.FormFile("file")
  85. assert.Error(t, err)
  86. assert.Nil(t, f)
  87. }
  88. func TestContextMultipartForm(t *testing.T) {
  89. buf := new(bytes.Buffer)
  90. mw := multipart.NewWriter(buf)
  91. assert.NoError(t, mw.WriteField("foo", "bar"))
  92. w, err := mw.CreateFormFile("file", "test")
  93. if assert.NoError(t, err) {
  94. _, err = w.Write([]byte("test"))
  95. assert.NoError(t, err)
  96. }
  97. mw.Close()
  98. c, _ := CreateTestContext(httptest.NewRecorder())
  99. c.Request, _ = http.NewRequest("POST", "/", buf)
  100. c.Request.Header.Set("Content-Type", mw.FormDataContentType())
  101. f, err := c.MultipartForm()
  102. if assert.NoError(t, err) {
  103. assert.NotNil(t, f)
  104. }
  105. assert.NoError(t, c.SaveUploadedFile(f.File["file"][0], "test"))
  106. }
  107. func TestSaveUploadedOpenFailed(t *testing.T) {
  108. buf := new(bytes.Buffer)
  109. mw := multipart.NewWriter(buf)
  110. mw.Close()
  111. c, _ := CreateTestContext(httptest.NewRecorder())
  112. c.Request, _ = http.NewRequest("POST", "/", buf)
  113. c.Request.Header.Set("Content-Type", mw.FormDataContentType())
  114. f := &multipart.FileHeader{
  115. Filename: "file",
  116. }
  117. assert.Error(t, c.SaveUploadedFile(f, "test"))
  118. }
  119. func TestSaveUploadedCreateFailed(t *testing.T) {
  120. buf := new(bytes.Buffer)
  121. mw := multipart.NewWriter(buf)
  122. w, err := mw.CreateFormFile("file", "test")
  123. if assert.NoError(t, err) {
  124. _, err = w.Write([]byte("test"))
  125. assert.NoError(t, err)
  126. }
  127. mw.Close()
  128. c, _ := CreateTestContext(httptest.NewRecorder())
  129. c.Request, _ = http.NewRequest("POST", "/", buf)
  130. c.Request.Header.Set("Content-Type", mw.FormDataContentType())
  131. f, err := c.FormFile("file")
  132. if assert.NoError(t, err) {
  133. assert.Equal(t, "test", f.Filename)
  134. }
  135. assert.Error(t, c.SaveUploadedFile(f, "/"))
  136. }
  137. func TestContextReset(t *testing.T) {
  138. router := New()
  139. c := router.allocateContext()
  140. assert.Equal(t, c.engine, router)
  141. c.index = 2
  142. c.Writer = &responseWriter{ResponseWriter: httptest.NewRecorder()}
  143. c.Params = Params{Param{}}
  144. c.Error(errors.New("test")) // nolint: errcheck
  145. c.Set("foo", "bar")
  146. c.reset()
  147. assert.False(t, c.IsAborted())
  148. assert.Nil(t, c.Keys)
  149. assert.Nil(t, c.Accepted)
  150. assert.Len(t, c.Errors, 0)
  151. assert.Empty(t, c.Errors.Errors())
  152. assert.Empty(t, c.Errors.ByType(ErrorTypeAny))
  153. assert.Len(t, c.Params, 0)
  154. assert.EqualValues(t, c.index, -1)
  155. assert.Equal(t, c.Writer.(*responseWriter), &c.writermem)
  156. }
  157. func TestContextHandlers(t *testing.T) {
  158. c, _ := CreateTestContext(httptest.NewRecorder())
  159. assert.Nil(t, c.handlers)
  160. assert.Nil(t, c.handlers.Last())
  161. c.handlers = HandlersChain{}
  162. assert.NotNil(t, c.handlers)
  163. assert.Nil(t, c.handlers.Last())
  164. f := func(c *Context) {}
  165. g := func(c *Context) {}
  166. c.handlers = HandlersChain{f}
  167. compareFunc(t, f, c.handlers.Last())
  168. c.handlers = HandlersChain{f, g}
  169. compareFunc(t, g, c.handlers.Last())
  170. }
  171. // TestContextSetGet tests that a parameter is set correctly on the
  172. // current context and can be retrieved using Get.
  173. func TestContextSetGet(t *testing.T) {
  174. c, _ := CreateTestContext(httptest.NewRecorder())
  175. c.Set("foo", "bar")
  176. value, err := c.Get("foo")
  177. assert.Equal(t, "bar", value)
  178. assert.True(t, err)
  179. value, err = c.Get("foo2")
  180. assert.Nil(t, value)
  181. assert.False(t, err)
  182. assert.Equal(t, "bar", c.MustGet("foo"))
  183. assert.Panics(t, func() { c.MustGet("no_exist") })
  184. }
  185. func TestContextSetGetValues(t *testing.T) {
  186. c, _ := CreateTestContext(httptest.NewRecorder())
  187. c.Set("string", "this is a string")
  188. c.Set("int32", int32(-42))
  189. c.Set("int64", int64(42424242424242))
  190. c.Set("uint64", uint64(42))
  191. c.Set("float32", float32(4.2))
  192. c.Set("float64", 4.2)
  193. var a interface{} = 1
  194. c.Set("intInterface", a)
  195. assert.Exactly(t, c.MustGet("string").(string), "this is a string")
  196. assert.Exactly(t, c.MustGet("int32").(int32), int32(-42))
  197. assert.Exactly(t, c.MustGet("int64").(int64), int64(42424242424242))
  198. assert.Exactly(t, c.MustGet("uint64").(uint64), uint64(42))
  199. assert.Exactly(t, c.MustGet("float32").(float32), float32(4.2))
  200. assert.Exactly(t, c.MustGet("float64").(float64), 4.2)
  201. assert.Exactly(t, c.MustGet("intInterface").(int), 1)
  202. }
  203. func TestContextGetString(t *testing.T) {
  204. c, _ := CreateTestContext(httptest.NewRecorder())
  205. c.Set("string", "this is a string")
  206. assert.Equal(t, "this is a string", c.GetString("string"))
  207. }
  208. func TestContextSetGetBool(t *testing.T) {
  209. c, _ := CreateTestContext(httptest.NewRecorder())
  210. c.Set("bool", true)
  211. assert.True(t, c.GetBool("bool"))
  212. }
  213. func TestContextGetInt(t *testing.T) {
  214. c, _ := CreateTestContext(httptest.NewRecorder())
  215. c.Set("int", 1)
  216. assert.Equal(t, 1, c.GetInt("int"))
  217. }
  218. func TestContextGetInt64(t *testing.T) {
  219. c, _ := CreateTestContext(httptest.NewRecorder())
  220. c.Set("int64", int64(42424242424242))
  221. assert.Equal(t, int64(42424242424242), c.GetInt64("int64"))
  222. }
  223. func TestContextGetFloat64(t *testing.T) {
  224. c, _ := CreateTestContext(httptest.NewRecorder())
  225. c.Set("float64", 4.2)
  226. assert.Equal(t, 4.2, c.GetFloat64("float64"))
  227. }
  228. func TestContextGetTime(t *testing.T) {
  229. c, _ := CreateTestContext(httptest.NewRecorder())
  230. t1, _ := time.Parse("1/2/2006 15:04:05", "01/01/2017 12:00:00")
  231. c.Set("time", t1)
  232. assert.Equal(t, t1, c.GetTime("time"))
  233. }
  234. func TestContextGetDuration(t *testing.T) {
  235. c, _ := CreateTestContext(httptest.NewRecorder())
  236. c.Set("duration", time.Second)
  237. assert.Equal(t, time.Second, c.GetDuration("duration"))
  238. }
  239. func TestContextGetStringSlice(t *testing.T) {
  240. c, _ := CreateTestContext(httptest.NewRecorder())
  241. c.Set("slice", []string{"foo"})
  242. assert.Equal(t, []string{"foo"}, c.GetStringSlice("slice"))
  243. }
  244. func TestContextGetStringMap(t *testing.T) {
  245. c, _ := CreateTestContext(httptest.NewRecorder())
  246. var m = make(map[string]interface{})
  247. m["foo"] = 1
  248. c.Set("map", m)
  249. assert.Equal(t, m, c.GetStringMap("map"))
  250. assert.Equal(t, 1, c.GetStringMap("map")["foo"])
  251. }
  252. func TestContextGetStringMapString(t *testing.T) {
  253. c, _ := CreateTestContext(httptest.NewRecorder())
  254. var m = make(map[string]string)
  255. m["foo"] = "bar"
  256. c.Set("map", m)
  257. assert.Equal(t, m, c.GetStringMapString("map"))
  258. assert.Equal(t, "bar", c.GetStringMapString("map")["foo"])
  259. }
  260. func TestContextGetStringMapStringSlice(t *testing.T) {
  261. c, _ := CreateTestContext(httptest.NewRecorder())
  262. var m = make(map[string][]string)
  263. m["foo"] = []string{"foo"}
  264. c.Set("map", m)
  265. assert.Equal(t, m, c.GetStringMapStringSlice("map"))
  266. assert.Equal(t, []string{"foo"}, c.GetStringMapStringSlice("map")["foo"])
  267. }
  268. func TestContextCopy(t *testing.T) {
  269. c, _ := CreateTestContext(httptest.NewRecorder())
  270. c.index = 2
  271. c.Request, _ = http.NewRequest("POST", "/hola", nil)
  272. c.handlers = HandlersChain{func(c *Context) {}}
  273. c.Params = Params{Param{Key: "foo", Value: "bar"}}
  274. c.Set("foo", "bar")
  275. cp := c.Copy()
  276. assert.Nil(t, cp.handlers)
  277. assert.Nil(t, cp.writermem.ResponseWriter)
  278. assert.Equal(t, &cp.writermem, cp.Writer.(*responseWriter))
  279. assert.Equal(t, cp.Request, c.Request)
  280. assert.Equal(t, cp.index, abortIndex)
  281. assert.Equal(t, cp.Keys, c.Keys)
  282. assert.Equal(t, cp.engine, c.engine)
  283. assert.Equal(t, cp.Params, c.Params)
  284. cp.Set("foo", "notBar")
  285. assert.False(t, cp.Keys["foo"] == c.Keys["foo"])
  286. }
  287. func TestContextHandlerName(t *testing.T) {
  288. c, _ := CreateTestContext(httptest.NewRecorder())
  289. c.handlers = HandlersChain{func(c *Context) {}, handlerNameTest}
  290. assert.Regexp(t, "^(.*/vendor/)?github.com/gin-gonic/gin.handlerNameTest$", c.HandlerName())
  291. }
  292. func TestContextHandlerNames(t *testing.T) {
  293. c, _ := CreateTestContext(httptest.NewRecorder())
  294. c.handlers = HandlersChain{func(c *Context) {}, handlerNameTest, func(c *Context) {}, handlerNameTest2}
  295. names := c.HandlerNames()
  296. assert.True(t, len(names) == 4)
  297. for _, name := range names {
  298. assert.Regexp(t, `^(.*/vendor/)?(github\.com/gin-gonic/gin\.){1}(TestContextHandlerNames\.func.*){0,1}(handlerNameTest.*){0,1}`, name)
  299. }
  300. }
  301. func handlerNameTest(c *Context) {
  302. }
  303. func handlerNameTest2(c *Context) {
  304. }
  305. var handlerTest HandlerFunc = func(c *Context) {
  306. }
  307. func TestContextHandler(t *testing.T) {
  308. c, _ := CreateTestContext(httptest.NewRecorder())
  309. c.handlers = HandlersChain{func(c *Context) {}, handlerTest}
  310. assert.Equal(t, reflect.ValueOf(handlerTest).Pointer(), reflect.ValueOf(c.Handler()).Pointer())
  311. }
  312. func TestContextQuery(t *testing.T) {
  313. c, _ := CreateTestContext(httptest.NewRecorder())
  314. c.Request, _ = http.NewRequest("GET", "http://example.com/?foo=bar&page=10&id=", nil)
  315. value, ok := c.GetQuery("foo")
  316. assert.True(t, ok)
  317. assert.Equal(t, "bar", value)
  318. assert.Equal(t, "bar", c.DefaultQuery("foo", "none"))
  319. assert.Equal(t, "bar", c.Query("foo"))
  320. value, ok = c.GetQuery("page")
  321. assert.True(t, ok)
  322. assert.Equal(t, "10", value)
  323. assert.Equal(t, "10", c.DefaultQuery("page", "0"))
  324. assert.Equal(t, "10", c.Query("page"))
  325. value, ok = c.GetQuery("id")
  326. assert.True(t, ok)
  327. assert.Empty(t, value)
  328. assert.Empty(t, c.DefaultQuery("id", "nada"))
  329. assert.Empty(t, c.Query("id"))
  330. value, ok = c.GetQuery("NoKey")
  331. assert.False(t, ok)
  332. assert.Empty(t, value)
  333. assert.Equal(t, "nada", c.DefaultQuery("NoKey", "nada"))
  334. assert.Empty(t, c.Query("NoKey"))
  335. // postform should not mess
  336. value, ok = c.GetPostForm("page")
  337. assert.False(t, ok)
  338. assert.Empty(t, value)
  339. assert.Empty(t, c.PostForm("foo"))
  340. }
  341. func TestContextQueryAndPostForm(t *testing.T) {
  342. c, _ := CreateTestContext(httptest.NewRecorder())
  343. body := bytes.NewBufferString("foo=bar&page=11&both=&foo=second")
  344. c.Request, _ = http.NewRequest("POST",
  345. "/?both=GET&id=main&id=omit&array[]=first&array[]=second&ids[a]=hi&ids[b]=3.14", body)
  346. c.Request.Header.Add("Content-Type", MIMEPOSTForm)
  347. assert.Equal(t, "bar", c.DefaultPostForm("foo", "none"))
  348. assert.Equal(t, "bar", c.PostForm("foo"))
  349. assert.Empty(t, c.Query("foo"))
  350. value, ok := c.GetPostForm("page")
  351. assert.True(t, ok)
  352. assert.Equal(t, "11", value)
  353. assert.Equal(t, "11", c.DefaultPostForm("page", "0"))
  354. assert.Equal(t, "11", c.PostForm("page"))
  355. assert.Empty(t, c.Query("page"))
  356. value, ok = c.GetPostForm("both")
  357. assert.True(t, ok)
  358. assert.Empty(t, value)
  359. assert.Empty(t, c.PostForm("both"))
  360. assert.Empty(t, c.DefaultPostForm("both", "nothing"))
  361. assert.Equal(t, "GET", c.Query("both"), "GET")
  362. value, ok = c.GetQuery("id")
  363. assert.True(t, ok)
  364. assert.Equal(t, "main", value)
  365. assert.Equal(t, "000", c.DefaultPostForm("id", "000"))
  366. assert.Equal(t, "main", c.Query("id"))
  367. assert.Empty(t, c.PostForm("id"))
  368. value, ok = c.GetQuery("NoKey")
  369. assert.False(t, ok)
  370. assert.Empty(t, value)
  371. value, ok = c.GetPostForm("NoKey")
  372. assert.False(t, ok)
  373. assert.Empty(t, value)
  374. assert.Equal(t, "nada", c.DefaultPostForm("NoKey", "nada"))
  375. assert.Equal(t, "nothing", c.DefaultQuery("NoKey", "nothing"))
  376. assert.Empty(t, c.PostForm("NoKey"))
  377. assert.Empty(t, c.Query("NoKey"))
  378. var obj struct {
  379. Foo string `form:"foo"`
  380. ID string `form:"id"`
  381. Page int `form:"page"`
  382. Both string `form:"both"`
  383. Array []string `form:"array[]"`
  384. }
  385. assert.NoError(t, c.Bind(&obj))
  386. assert.Equal(t, "bar", obj.Foo, "bar")
  387. assert.Equal(t, "main", obj.ID, "main")
  388. assert.Equal(t, 11, obj.Page, 11)
  389. assert.Empty(t, obj.Both)
  390. assert.Equal(t, []string{"first", "second"}, obj.Array)
  391. values, ok := c.GetQueryArray("array[]")
  392. assert.True(t, ok)
  393. assert.Equal(t, "first", values[0])
  394. assert.Equal(t, "second", values[1])
  395. values = c.QueryArray("array[]")
  396. assert.Equal(t, "first", values[0])
  397. assert.Equal(t, "second", values[1])
  398. values = c.QueryArray("nokey")
  399. assert.Equal(t, 0, len(values))
  400. values = c.QueryArray("both")
  401. assert.Equal(t, 1, len(values))
  402. assert.Equal(t, "GET", values[0])
  403. dicts, ok := c.GetQueryMap("ids")
  404. assert.True(t, ok)
  405. assert.Equal(t, "hi", dicts["a"])
  406. assert.Equal(t, "3.14", dicts["b"])
  407. dicts, ok = c.GetQueryMap("nokey")
  408. assert.False(t, ok)
  409. assert.Equal(t, 0, len(dicts))
  410. dicts, ok = c.GetQueryMap("both")
  411. assert.False(t, ok)
  412. assert.Equal(t, 0, len(dicts))
  413. dicts, ok = c.GetQueryMap("array")
  414. assert.False(t, ok)
  415. assert.Equal(t, 0, len(dicts))
  416. dicts = c.QueryMap("ids")
  417. assert.Equal(t, "hi", dicts["a"])
  418. assert.Equal(t, "3.14", dicts["b"])
  419. dicts = c.QueryMap("nokey")
  420. assert.Equal(t, 0, len(dicts))
  421. }
  422. func TestContextPostFormMultipart(t *testing.T) {
  423. c, _ := CreateTestContext(httptest.NewRecorder())
  424. c.Request = createMultipartRequest()
  425. var obj struct {
  426. Foo string `form:"foo"`
  427. Bar string `form:"bar"`
  428. BarAsInt int `form:"bar"`
  429. Array []string `form:"array"`
  430. ID string `form:"id"`
  431. TimeLocal time.Time `form:"time_local" time_format:"02/01/2006 15:04"`
  432. TimeUTC time.Time `form:"time_utc" time_format:"02/01/2006 15:04" time_utc:"1"`
  433. TimeLocation time.Time `form:"time_location" time_format:"02/01/2006 15:04" time_location:"Asia/Tokyo"`
  434. BlankTime time.Time `form:"blank_time" time_format:"02/01/2006 15:04"`
  435. }
  436. assert.NoError(t, c.Bind(&obj))
  437. assert.Equal(t, "bar", obj.Foo)
  438. assert.Equal(t, "10", obj.Bar)
  439. assert.Equal(t, 10, obj.BarAsInt)
  440. assert.Equal(t, []string{"first", "second"}, obj.Array)
  441. assert.Empty(t, obj.ID)
  442. assert.Equal(t, "31/12/2016 14:55", obj.TimeLocal.Format("02/01/2006 15:04"))
  443. assert.Equal(t, time.Local, obj.TimeLocal.Location())
  444. assert.Equal(t, "31/12/2016 14:55", obj.TimeUTC.Format("02/01/2006 15:04"))
  445. assert.Equal(t, time.UTC, obj.TimeUTC.Location())
  446. loc, _ := time.LoadLocation("Asia/Tokyo")
  447. assert.Equal(t, "31/12/2016 14:55", obj.TimeLocation.Format("02/01/2006 15:04"))
  448. assert.Equal(t, loc, obj.TimeLocation.Location())
  449. assert.True(t, obj.BlankTime.IsZero())
  450. value, ok := c.GetQuery("foo")
  451. assert.False(t, ok)
  452. assert.Empty(t, value)
  453. assert.Empty(t, c.Query("bar"))
  454. assert.Equal(t, "nothing", c.DefaultQuery("id", "nothing"))
  455. value, ok = c.GetPostForm("foo")
  456. assert.True(t, ok)
  457. assert.Equal(t, "bar", value)
  458. assert.Equal(t, "bar", c.PostForm("foo"))
  459. value, ok = c.GetPostForm("array")
  460. assert.True(t, ok)
  461. assert.Equal(t, "first", value)
  462. assert.Equal(t, "first", c.PostForm("array"))
  463. assert.Equal(t, "10", c.DefaultPostForm("bar", "nothing"))
  464. value, ok = c.GetPostForm("id")
  465. assert.True(t, ok)
  466. assert.Empty(t, value)
  467. assert.Empty(t, c.PostForm("id"))
  468. assert.Empty(t, c.DefaultPostForm("id", "nothing"))
  469. value, ok = c.GetPostForm("nokey")
  470. assert.False(t, ok)
  471. assert.Empty(t, value)
  472. assert.Equal(t, "nothing", c.DefaultPostForm("nokey", "nothing"))
  473. values, ok := c.GetPostFormArray("array")
  474. assert.True(t, ok)
  475. assert.Equal(t, "first", values[0])
  476. assert.Equal(t, "second", values[1])
  477. values = c.PostFormArray("array")
  478. assert.Equal(t, "first", values[0])
  479. assert.Equal(t, "second", values[1])
  480. values = c.PostFormArray("nokey")
  481. assert.Equal(t, 0, len(values))
  482. values = c.PostFormArray("foo")
  483. assert.Equal(t, 1, len(values))
  484. assert.Equal(t, "bar", values[0])
  485. dicts, ok := c.GetPostFormMap("names")
  486. assert.True(t, ok)
  487. assert.Equal(t, "thinkerou", dicts["a"])
  488. assert.Equal(t, "tianou", dicts["b"])
  489. dicts, ok = c.GetPostFormMap("nokey")
  490. assert.False(t, ok)
  491. assert.Equal(t, 0, len(dicts))
  492. dicts = c.PostFormMap("names")
  493. assert.Equal(t, "thinkerou", dicts["a"])
  494. assert.Equal(t, "tianou", dicts["b"])
  495. dicts = c.PostFormMap("nokey")
  496. assert.Equal(t, 0, len(dicts))
  497. }
  498. func TestContextSetCookie(t *testing.T) {
  499. c, _ := CreateTestContext(httptest.NewRecorder())
  500. c.SetCookie("user", "gin", 1, "/", "localhost", true, true)
  501. assert.Equal(t, "user=gin; Path=/; Domain=localhost; Max-Age=1; HttpOnly; Secure", c.Writer.Header().Get("Set-Cookie"))
  502. }
  503. func TestContextSetCookiePathEmpty(t *testing.T) {
  504. c, _ := CreateTestContext(httptest.NewRecorder())
  505. c.SetCookie("user", "gin", 1, "", "localhost", true, true)
  506. assert.Equal(t, "user=gin; Path=/; Domain=localhost; Max-Age=1; HttpOnly; Secure", c.Writer.Header().Get("Set-Cookie"))
  507. }
  508. func TestContextGetCookie(t *testing.T) {
  509. c, _ := CreateTestContext(httptest.NewRecorder())
  510. c.Request, _ = http.NewRequest("GET", "/get", nil)
  511. c.Request.Header.Set("Cookie", "user=gin")
  512. cookie, _ := c.Cookie("user")
  513. assert.Equal(t, "gin", cookie)
  514. _, err := c.Cookie("nokey")
  515. assert.Error(t, err)
  516. }
  517. func TestContextBodyAllowedForStatus(t *testing.T) {
  518. assert.False(t, false, bodyAllowedForStatus(http.StatusProcessing))
  519. assert.False(t, false, bodyAllowedForStatus(http.StatusNoContent))
  520. assert.False(t, false, bodyAllowedForStatus(http.StatusNotModified))
  521. assert.True(t, true, bodyAllowedForStatus(http.StatusInternalServerError))
  522. }
  523. type TestPanicRender struct {
  524. }
  525. func (*TestPanicRender) Render(http.ResponseWriter) error {
  526. return errors.New("TestPanicRender")
  527. }
  528. func (*TestPanicRender) WriteContentType(http.ResponseWriter) {}
  529. func TestContextRenderPanicIfErr(t *testing.T) {
  530. defer func() {
  531. r := recover()
  532. assert.Equal(t, "TestPanicRender", fmt.Sprint(r))
  533. }()
  534. w := httptest.NewRecorder()
  535. c, _ := CreateTestContext(w)
  536. c.Render(http.StatusOK, &TestPanicRender{})
  537. assert.Fail(t, "Panic not detected")
  538. }
  539. // Tests that the response is serialized as JSON
  540. // and Content-Type is set to application/json
  541. // and special HTML characters are escaped
  542. func TestContextRenderJSON(t *testing.T) {
  543. w := httptest.NewRecorder()
  544. c, _ := CreateTestContext(w)
  545. c.JSON(http.StatusCreated, H{"foo": "bar", "html": "<b>"})
  546. assert.Equal(t, http.StatusCreated, w.Code)
  547. assert.Equal(t, "{\"foo\":\"bar\",\"html\":\"\\u003cb\\u003e\"}", w.Body.String())
  548. assert.Equal(t, "application/json; charset=utf-8", w.Header().Get("Content-Type"))
  549. }
  550. // Tests that the response is serialized as JSONP
  551. // and Content-Type is set to application/javascript
  552. func TestContextRenderJSONP(t *testing.T) {
  553. w := httptest.NewRecorder()
  554. c, _ := CreateTestContext(w)
  555. c.Request, _ = http.NewRequest("GET", "http://example.com/?callback=x", nil)
  556. c.JSONP(http.StatusCreated, H{"foo": "bar"})
  557. assert.Equal(t, http.StatusCreated, w.Code)
  558. assert.Equal(t, "x({\"foo\":\"bar\"})", w.Body.String())
  559. assert.Equal(t, "application/javascript; charset=utf-8", w.Header().Get("Content-Type"))
  560. }
  561. // Tests that the response is serialized as JSONP
  562. // and Content-Type is set to application/json
  563. func TestContextRenderJSONPWithoutCallback(t *testing.T) {
  564. w := httptest.NewRecorder()
  565. c, _ := CreateTestContext(w)
  566. c.Request, _ = http.NewRequest("GET", "http://example.com", nil)
  567. c.JSONP(http.StatusCreated, H{"foo": "bar"})
  568. assert.Equal(t, http.StatusCreated, w.Code)
  569. assert.Equal(t, "{\"foo\":\"bar\"}", w.Body.String())
  570. assert.Equal(t, "application/json; charset=utf-8", w.Header().Get("Content-Type"))
  571. }
  572. // Tests that no JSON is rendered if code is 204
  573. func TestContextRenderNoContentJSON(t *testing.T) {
  574. w := httptest.NewRecorder()
  575. c, _ := CreateTestContext(w)
  576. c.JSON(http.StatusNoContent, H{"foo": "bar"})
  577. assert.Equal(t, http.StatusNoContent, w.Code)
  578. assert.Empty(t, w.Body.String())
  579. assert.Equal(t, "application/json; charset=utf-8", w.Header().Get("Content-Type"))
  580. }
  581. // Tests that the response is serialized as JSON
  582. // we change the content-type before
  583. func TestContextRenderAPIJSON(t *testing.T) {
  584. w := httptest.NewRecorder()
  585. c, _ := CreateTestContext(w)
  586. c.Header("Content-Type", "application/vnd.api+json")
  587. c.JSON(http.StatusCreated, H{"foo": "bar"})
  588. assert.Equal(t, http.StatusCreated, w.Code)
  589. assert.Equal(t, "{\"foo\":\"bar\"}", w.Body.String())
  590. assert.Equal(t, "application/vnd.api+json", w.Header().Get("Content-Type"))
  591. }
  592. // Tests that no Custom JSON is rendered if code is 204
  593. func TestContextRenderNoContentAPIJSON(t *testing.T) {
  594. w := httptest.NewRecorder()
  595. c, _ := CreateTestContext(w)
  596. c.Header("Content-Type", "application/vnd.api+json")
  597. c.JSON(http.StatusNoContent, H{"foo": "bar"})
  598. assert.Equal(t, http.StatusNoContent, w.Code)
  599. assert.Empty(t, w.Body.String())
  600. assert.Equal(t, w.Header().Get("Content-Type"), "application/vnd.api+json")
  601. }
  602. // Tests that the response is serialized as JSON
  603. // and Content-Type is set to application/json
  604. func TestContextRenderIndentedJSON(t *testing.T) {
  605. w := httptest.NewRecorder()
  606. c, _ := CreateTestContext(w)
  607. c.IndentedJSON(http.StatusCreated, H{"foo": "bar", "bar": "foo", "nested": H{"foo": "bar"}})
  608. assert.Equal(t, http.StatusCreated, w.Code)
  609. assert.Equal(t, "{\n \"bar\": \"foo\",\n \"foo\": \"bar\",\n \"nested\": {\n \"foo\": \"bar\"\n }\n}", w.Body.String())
  610. assert.Equal(t, "application/json; charset=utf-8", w.Header().Get("Content-Type"))
  611. }
  612. // Tests that no Custom JSON is rendered if code is 204
  613. func TestContextRenderNoContentIndentedJSON(t *testing.T) {
  614. w := httptest.NewRecorder()
  615. c, _ := CreateTestContext(w)
  616. c.IndentedJSON(http.StatusNoContent, H{"foo": "bar", "bar": "foo", "nested": H{"foo": "bar"}})
  617. assert.Equal(t, http.StatusNoContent, w.Code)
  618. assert.Empty(t, w.Body.String())
  619. assert.Equal(t, "application/json; charset=utf-8", w.Header().Get("Content-Type"))
  620. }
  621. // Tests that the response is serialized as Secure JSON
  622. // and Content-Type is set to application/json
  623. func TestContextRenderSecureJSON(t *testing.T) {
  624. w := httptest.NewRecorder()
  625. c, router := CreateTestContext(w)
  626. router.SecureJsonPrefix("&&&START&&&")
  627. c.SecureJSON(http.StatusCreated, []string{"foo", "bar"})
  628. assert.Equal(t, http.StatusCreated, w.Code)
  629. assert.Equal(t, "&&&START&&&[\"foo\",\"bar\"]", w.Body.String())
  630. assert.Equal(t, "application/json; charset=utf-8", w.Header().Get("Content-Type"))
  631. }
  632. // Tests that no Custom JSON is rendered if code is 204
  633. func TestContextRenderNoContentSecureJSON(t *testing.T) {
  634. w := httptest.NewRecorder()
  635. c, _ := CreateTestContext(w)
  636. c.SecureJSON(http.StatusNoContent, []string{"foo", "bar"})
  637. assert.Equal(t, http.StatusNoContent, w.Code)
  638. assert.Empty(t, w.Body.String())
  639. assert.Equal(t, "application/json; charset=utf-8", w.Header().Get("Content-Type"))
  640. }
  641. func TestContextRenderNoContentAsciiJSON(t *testing.T) {
  642. w := httptest.NewRecorder()
  643. c, _ := CreateTestContext(w)
  644. c.AsciiJSON(http.StatusNoContent, []string{"lang", "Go语言"})
  645. assert.Equal(t, http.StatusNoContent, w.Code)
  646. assert.Empty(t, w.Body.String())
  647. assert.Equal(t, "application/json", w.Header().Get("Content-Type"))
  648. }
  649. // Tests that the response is serialized as JSON
  650. // and Content-Type is set to application/json
  651. // and special HTML characters are preserved
  652. func TestContextRenderPureJSON(t *testing.T) {
  653. w := httptest.NewRecorder()
  654. c, _ := CreateTestContext(w)
  655. c.PureJSON(http.StatusCreated, H{"foo": "bar", "html": "<b>"})
  656. assert.Equal(t, http.StatusCreated, w.Code)
  657. assert.Equal(t, "{\"foo\":\"bar\",\"html\":\"<b>\"}\n", w.Body.String())
  658. assert.Equal(t, "application/json; charset=utf-8", w.Header().Get("Content-Type"))
  659. }
  660. // Tests that the response executes the templates
  661. // and responds with Content-Type set to text/html
  662. func TestContextRenderHTML(t *testing.T) {
  663. w := httptest.NewRecorder()
  664. c, router := CreateTestContext(w)
  665. templ := template.Must(template.New("t").Parse(`Hello {{.name}}`))
  666. router.SetHTMLTemplate(templ)
  667. c.HTML(http.StatusCreated, "t", H{"name": "alexandernyquist"})
  668. assert.Equal(t, http.StatusCreated, w.Code)
  669. assert.Equal(t, "Hello alexandernyquist", w.Body.String())
  670. assert.Equal(t, "text/html; charset=utf-8", w.Header().Get("Content-Type"))
  671. }
  672. func TestContextRenderHTML2(t *testing.T) {
  673. w := httptest.NewRecorder()
  674. c, router := CreateTestContext(w)
  675. // print debug warning log when Engine.trees > 0
  676. router.addRoute("GET", "/", HandlersChain{func(_ *Context) {}})
  677. assert.Len(t, router.trees, 1)
  678. templ := template.Must(template.New("t").Parse(`Hello {{.name}}`))
  679. re := captureOutput(t, func() {
  680. SetMode(DebugMode)
  681. router.SetHTMLTemplate(templ)
  682. SetMode(TestMode)
  683. })
  684. 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)
  685. c.HTML(http.StatusCreated, "t", H{"name": "alexandernyquist"})
  686. assert.Equal(t, http.StatusCreated, w.Code)
  687. assert.Equal(t, "Hello alexandernyquist", w.Body.String())
  688. assert.Equal(t, "text/html; charset=utf-8", w.Header().Get("Content-Type"))
  689. }
  690. // Tests that no HTML is rendered if code is 204
  691. func TestContextRenderNoContentHTML(t *testing.T) {
  692. w := httptest.NewRecorder()
  693. c, router := CreateTestContext(w)
  694. templ := template.Must(template.New("t").Parse(`Hello {{.name}}`))
  695. router.SetHTMLTemplate(templ)
  696. c.HTML(http.StatusNoContent, "t", H{"name": "alexandernyquist"})
  697. assert.Equal(t, http.StatusNoContent, w.Code)
  698. assert.Empty(t, w.Body.String())
  699. assert.Equal(t, "text/html; charset=utf-8", w.Header().Get("Content-Type"))
  700. }
  701. // TestContextXML tests that the response is serialized as XML
  702. // and Content-Type is set to application/xml
  703. func TestContextRenderXML(t *testing.T) {
  704. w := httptest.NewRecorder()
  705. c, _ := CreateTestContext(w)
  706. c.XML(http.StatusCreated, H{"foo": "bar"})
  707. assert.Equal(t, http.StatusCreated, w.Code)
  708. assert.Equal(t, "<map><foo>bar</foo></map>", w.Body.String())
  709. assert.Equal(t, "application/xml; charset=utf-8", w.Header().Get("Content-Type"))
  710. }
  711. // Tests that no XML is rendered if code is 204
  712. func TestContextRenderNoContentXML(t *testing.T) {
  713. w := httptest.NewRecorder()
  714. c, _ := CreateTestContext(w)
  715. c.XML(http.StatusNoContent, H{"foo": "bar"})
  716. assert.Equal(t, http.StatusNoContent, w.Code)
  717. assert.Empty(t, w.Body.String())
  718. assert.Equal(t, "application/xml; charset=utf-8", w.Header().Get("Content-Type"))
  719. }
  720. // TestContextString tests that the response is returned
  721. // with Content-Type set to text/plain
  722. func TestContextRenderString(t *testing.T) {
  723. w := httptest.NewRecorder()
  724. c, _ := CreateTestContext(w)
  725. c.String(http.StatusCreated, "test %s %d", "string", 2)
  726. assert.Equal(t, http.StatusCreated, w.Code)
  727. assert.Equal(t, "test string 2", w.Body.String())
  728. assert.Equal(t, "text/plain; charset=utf-8", w.Header().Get("Content-Type"))
  729. }
  730. // Tests that no String is rendered if code is 204
  731. func TestContextRenderNoContentString(t *testing.T) {
  732. w := httptest.NewRecorder()
  733. c, _ := CreateTestContext(w)
  734. c.String(http.StatusNoContent, "test %s %d", "string", 2)
  735. assert.Equal(t, http.StatusNoContent, w.Code)
  736. assert.Empty(t, w.Body.String())
  737. assert.Equal(t, "text/plain; charset=utf-8", w.Header().Get("Content-Type"))
  738. }
  739. // TestContextString tests that the response is returned
  740. // with Content-Type set to text/html
  741. func TestContextRenderHTMLString(t *testing.T) {
  742. w := httptest.NewRecorder()
  743. c, _ := CreateTestContext(w)
  744. c.Header("Content-Type", "text/html; charset=utf-8")
  745. c.String(http.StatusCreated, "<html>%s %d</html>", "string", 3)
  746. assert.Equal(t, http.StatusCreated, w.Code)
  747. assert.Equal(t, "<html>string 3</html>", w.Body.String())
  748. assert.Equal(t, "text/html; charset=utf-8", w.Header().Get("Content-Type"))
  749. }
  750. // Tests that no HTML String is rendered if code is 204
  751. func TestContextRenderNoContentHTMLString(t *testing.T) {
  752. w := httptest.NewRecorder()
  753. c, _ := CreateTestContext(w)
  754. c.Header("Content-Type", "text/html; charset=utf-8")
  755. c.String(http.StatusNoContent, "<html>%s %d</html>", "string", 3)
  756. assert.Equal(t, http.StatusNoContent, w.Code)
  757. assert.Empty(t, w.Body.String())
  758. assert.Equal(t, "text/html; charset=utf-8", w.Header().Get("Content-Type"))
  759. }
  760. // TestContextData tests that the response can be written from `bytesting`
  761. // with specified MIME type
  762. func TestContextRenderData(t *testing.T) {
  763. w := httptest.NewRecorder()
  764. c, _ := CreateTestContext(w)
  765. c.Data(http.StatusCreated, "text/csv", []byte(`foo,bar`))
  766. assert.Equal(t, http.StatusCreated, w.Code)
  767. assert.Equal(t, "foo,bar", w.Body.String())
  768. assert.Equal(t, "text/csv", w.Header().Get("Content-Type"))
  769. }
  770. // Tests that no Custom Data is rendered if code is 204
  771. func TestContextRenderNoContentData(t *testing.T) {
  772. w := httptest.NewRecorder()
  773. c, _ := CreateTestContext(w)
  774. c.Data(http.StatusNoContent, "text/csv", []byte(`foo,bar`))
  775. assert.Equal(t, http.StatusNoContent, w.Code)
  776. assert.Empty(t, w.Body.String())
  777. assert.Equal(t, "text/csv", w.Header().Get("Content-Type"))
  778. }
  779. func TestContextRenderSSE(t *testing.T) {
  780. w := httptest.NewRecorder()
  781. c, _ := CreateTestContext(w)
  782. c.SSEvent("float", 1.5)
  783. c.Render(-1, sse.Event{
  784. Id: "123",
  785. Data: "text",
  786. })
  787. c.SSEvent("chat", H{
  788. "foo": "bar",
  789. "bar": "foo",
  790. })
  791. 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))
  792. }
  793. func TestContextRenderFile(t *testing.T) {
  794. w := httptest.NewRecorder()
  795. c, _ := CreateTestContext(w)
  796. c.Request, _ = http.NewRequest("GET", "/", nil)
  797. c.File("./gin.go")
  798. assert.Equal(t, http.StatusOK, w.Code)
  799. assert.Contains(t, w.Body.String(), "func New() *Engine {")
  800. assert.Equal(t, "text/plain; charset=utf-8", w.Header().Get("Content-Type"))
  801. }
  802. func TestContextRenderAttachment(t *testing.T) {
  803. w := httptest.NewRecorder()
  804. c, _ := CreateTestContext(w)
  805. newFilename := "new_filename.go"
  806. c.Request, _ = http.NewRequest("GET", "/", nil)
  807. c.FileAttachment("./gin.go", newFilename)
  808. assert.Equal(t, 200, w.Code)
  809. assert.Contains(t, w.Body.String(), "func New() *Engine {")
  810. assert.Equal(t, fmt.Sprintf("attachment; filename=\"%s\"", newFilename), w.HeaderMap.Get("Content-Disposition"))
  811. }
  812. // TestContextRenderYAML tests that the response is serialized as YAML
  813. // and Content-Type is set to application/x-yaml
  814. func TestContextRenderYAML(t *testing.T) {
  815. w := httptest.NewRecorder()
  816. c, _ := CreateTestContext(w)
  817. c.YAML(http.StatusCreated, H{"foo": "bar"})
  818. assert.Equal(t, http.StatusCreated, w.Code)
  819. assert.Equal(t, "foo: bar\n", w.Body.String())
  820. assert.Equal(t, "application/x-yaml; charset=utf-8", w.Header().Get("Content-Type"))
  821. }
  822. // TestContextRenderProtoBuf tests that the response is serialized as ProtoBuf
  823. // and Content-Type is set to application/x-protobuf
  824. // and we just use the example protobuf to check if the response is correct
  825. func TestContextRenderProtoBuf(t *testing.T) {
  826. w := httptest.NewRecorder()
  827. c, _ := CreateTestContext(w)
  828. reps := []int64{int64(1), int64(2)}
  829. label := "test"
  830. data := &testdata.Test{
  831. Label: &label,
  832. Reps: reps,
  833. }
  834. c.ProtoBuf(http.StatusCreated, data)
  835. protoData, err := proto.Marshal(data)
  836. assert.NoError(t, err)
  837. assert.Equal(t, http.StatusCreated, w.Code)
  838. assert.Equal(t, string(protoData), w.Body.String())
  839. assert.Equal(t, "application/x-protobuf", w.Header().Get("Content-Type"))
  840. }
  841. func TestContextHeaders(t *testing.T) {
  842. c, _ := CreateTestContext(httptest.NewRecorder())
  843. c.Header("Content-Type", "text/plain")
  844. c.Header("X-Custom", "value")
  845. assert.Equal(t, "text/plain", c.Writer.Header().Get("Content-Type"))
  846. assert.Equal(t, "value", c.Writer.Header().Get("X-Custom"))
  847. c.Header("Content-Type", "text/html")
  848. c.Header("X-Custom", "")
  849. assert.Equal(t, "text/html", c.Writer.Header().Get("Content-Type"))
  850. _, exist := c.Writer.Header()["X-Custom"]
  851. assert.False(t, exist)
  852. }
  853. // TODO
  854. func TestContextRenderRedirectWithRelativePath(t *testing.T) {
  855. w := httptest.NewRecorder()
  856. c, _ := CreateTestContext(w)
  857. c.Request, _ = http.NewRequest("POST", "http://example.com", nil)
  858. assert.Panics(t, func() { c.Redirect(299, "/new_path") })
  859. assert.Panics(t, func() { c.Redirect(309, "/new_path") })
  860. c.Redirect(http.StatusMovedPermanently, "/path")
  861. c.Writer.WriteHeaderNow()
  862. assert.Equal(t, http.StatusMovedPermanently, w.Code)
  863. assert.Equal(t, "/path", w.Header().Get("Location"))
  864. }
  865. func TestContextRenderRedirectWithAbsolutePath(t *testing.T) {
  866. w := httptest.NewRecorder()
  867. c, _ := CreateTestContext(w)
  868. c.Request, _ = http.NewRequest("POST", "http://example.com", nil)
  869. c.Redirect(http.StatusFound, "http://google.com")
  870. c.Writer.WriteHeaderNow()
  871. assert.Equal(t, http.StatusFound, w.Code)
  872. assert.Equal(t, "http://google.com", w.Header().Get("Location"))
  873. }
  874. func TestContextRenderRedirectWith201(t *testing.T) {
  875. w := httptest.NewRecorder()
  876. c, _ := CreateTestContext(w)
  877. c.Request, _ = http.NewRequest("POST", "http://example.com", nil)
  878. c.Redirect(http.StatusCreated, "/resource")
  879. c.Writer.WriteHeaderNow()
  880. assert.Equal(t, http.StatusCreated, w.Code)
  881. assert.Equal(t, "/resource", w.Header().Get("Location"))
  882. }
  883. func TestContextRenderRedirectAll(t *testing.T) {
  884. c, _ := CreateTestContext(httptest.NewRecorder())
  885. c.Request, _ = http.NewRequest("POST", "http://example.com", nil)
  886. assert.Panics(t, func() { c.Redirect(http.StatusOK, "/resource") })
  887. assert.Panics(t, func() { c.Redirect(http.StatusAccepted, "/resource") })
  888. assert.Panics(t, func() { c.Redirect(299, "/resource") })
  889. assert.Panics(t, func() { c.Redirect(309, "/resource") })
  890. assert.NotPanics(t, func() { c.Redirect(http.StatusMultipleChoices, "/resource") })
  891. assert.NotPanics(t, func() { c.Redirect(http.StatusPermanentRedirect, "/resource") })
  892. }
  893. func TestContextNegotiationWithJSON(t *testing.T) {
  894. w := httptest.NewRecorder()
  895. c, _ := CreateTestContext(w)
  896. c.Request, _ = http.NewRequest("POST", "", nil)
  897. c.Negotiate(http.StatusOK, Negotiate{
  898. Offered: []string{MIMEJSON, MIMEXML},
  899. Data: H{"foo": "bar"},
  900. })
  901. assert.Equal(t, http.StatusOK, w.Code)
  902. assert.Equal(t, "{\"foo\":\"bar\"}", w.Body.String())
  903. assert.Equal(t, "application/json; charset=utf-8", w.Header().Get("Content-Type"))
  904. }
  905. func TestContextNegotiationWithXML(t *testing.T) {
  906. w := httptest.NewRecorder()
  907. c, _ := CreateTestContext(w)
  908. c.Request, _ = http.NewRequest("POST", "", nil)
  909. c.Negotiate(http.StatusOK, Negotiate{
  910. Offered: []string{MIMEXML, MIMEJSON},
  911. Data: H{"foo": "bar"},
  912. })
  913. assert.Equal(t, http.StatusOK, w.Code)
  914. assert.Equal(t, "<map><foo>bar</foo></map>", w.Body.String())
  915. assert.Equal(t, "application/xml; charset=utf-8", w.Header().Get("Content-Type"))
  916. }
  917. func TestContextNegotiationWithHTML(t *testing.T) {
  918. w := httptest.NewRecorder()
  919. c, router := CreateTestContext(w)
  920. c.Request, _ = http.NewRequest("POST", "", nil)
  921. templ := template.Must(template.New("t").Parse(`Hello {{.name}}`))
  922. router.SetHTMLTemplate(templ)
  923. c.Negotiate(http.StatusOK, Negotiate{
  924. Offered: []string{MIMEHTML},
  925. Data: H{"name": "gin"},
  926. HTMLName: "t",
  927. })
  928. assert.Equal(t, http.StatusOK, w.Code)
  929. assert.Equal(t, "Hello gin", w.Body.String())
  930. assert.Equal(t, "text/html; charset=utf-8", w.Header().Get("Content-Type"))
  931. }
  932. func TestContextNegotiationNotSupport(t *testing.T) {
  933. w := httptest.NewRecorder()
  934. c, _ := CreateTestContext(w)
  935. c.Request, _ = http.NewRequest("POST", "", nil)
  936. c.Negotiate(http.StatusOK, Negotiate{
  937. Offered: []string{MIMEPOSTForm},
  938. })
  939. assert.Equal(t, http.StatusNotAcceptable, w.Code)
  940. assert.Equal(t, c.index, abortIndex)
  941. assert.True(t, c.IsAborted())
  942. }
  943. func TestContextNegotiationFormat(t *testing.T) {
  944. c, _ := CreateTestContext(httptest.NewRecorder())
  945. c.Request, _ = http.NewRequest("POST", "", nil)
  946. assert.Panics(t, func() { c.NegotiateFormat() })
  947. assert.Equal(t, MIMEJSON, c.NegotiateFormat(MIMEJSON, MIMEXML))
  948. assert.Equal(t, MIMEHTML, c.NegotiateFormat(MIMEHTML, MIMEJSON))
  949. }
  950. func TestContextNegotiationFormatWithAccept(t *testing.T) {
  951. c, _ := CreateTestContext(httptest.NewRecorder())
  952. c.Request, _ = http.NewRequest("POST", "/", nil)
  953. c.Request.Header.Add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9;q=0.8")
  954. assert.Equal(t, MIMEXML, c.NegotiateFormat(MIMEJSON, MIMEXML))
  955. assert.Equal(t, MIMEHTML, c.NegotiateFormat(MIMEXML, MIMEHTML))
  956. assert.Empty(t, c.NegotiateFormat(MIMEJSON))
  957. }
  958. func TestContextNegotiationFormatWithWildcardAccept(t *testing.T) {
  959. c, _ := CreateTestContext(httptest.NewRecorder())
  960. c.Request, _ = http.NewRequest("POST", "/", nil)
  961. c.Request.Header.Add("Accept", "*/*")
  962. assert.Equal(t, c.NegotiateFormat("*/*"), "*/*")
  963. assert.Equal(t, c.NegotiateFormat("text/*"), "text/*")
  964. assert.Equal(t, c.NegotiateFormat("application/*"), "application/*")
  965. assert.Equal(t, c.NegotiateFormat(MIMEJSON), MIMEJSON)
  966. assert.Equal(t, c.NegotiateFormat(MIMEXML), MIMEXML)
  967. assert.Equal(t, c.NegotiateFormat(MIMEHTML), MIMEHTML)
  968. c, _ = CreateTestContext(httptest.NewRecorder())
  969. c.Request, _ = http.NewRequest("POST", "/", nil)
  970. c.Request.Header.Add("Accept", "text/*")
  971. assert.Equal(t, c.NegotiateFormat("*/*"), "*/*")
  972. assert.Equal(t, c.NegotiateFormat("text/*"), "text/*")
  973. assert.Equal(t, c.NegotiateFormat("application/*"), "")
  974. assert.Equal(t, c.NegotiateFormat(MIMEJSON), "")
  975. assert.Equal(t, c.NegotiateFormat(MIMEXML), "")
  976. assert.Equal(t, c.NegotiateFormat(MIMEHTML), MIMEHTML)
  977. }
  978. func TestContextNegotiationFormatCustom(t *testing.T) {
  979. c, _ := CreateTestContext(httptest.NewRecorder())
  980. c.Request, _ = http.NewRequest("POST", "/", nil)
  981. c.Request.Header.Add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9;q=0.8")
  982. c.Accepted = nil
  983. c.SetAccepted(MIMEJSON, MIMEXML)
  984. assert.Equal(t, MIMEJSON, c.NegotiateFormat(MIMEJSON, MIMEXML))
  985. assert.Equal(t, MIMEXML, c.NegotiateFormat(MIMEXML, MIMEHTML))
  986. assert.Equal(t, MIMEJSON, c.NegotiateFormat(MIMEJSON))
  987. }
  988. func TestContextIsAborted(t *testing.T) {
  989. c, _ := CreateTestContext(httptest.NewRecorder())
  990. assert.False(t, c.IsAborted())
  991. c.Abort()
  992. assert.True(t, c.IsAborted())
  993. c.Next()
  994. assert.True(t, c.IsAborted())
  995. c.index++
  996. assert.True(t, c.IsAborted())
  997. }
  998. // TestContextData tests that the response can be written from `bytesting`
  999. // with specified MIME type
  1000. func TestContextAbortWithStatus(t *testing.T) {
  1001. w := httptest.NewRecorder()
  1002. c, _ := CreateTestContext(w)
  1003. c.index = 4
  1004. c.AbortWithStatus(http.StatusUnauthorized)
  1005. assert.Equal(t, abortIndex, c.index)
  1006. assert.Equal(t, http.StatusUnauthorized, c.Writer.Status())
  1007. assert.Equal(t, http.StatusUnauthorized, w.Code)
  1008. assert.True(t, c.IsAborted())
  1009. }
  1010. type testJSONAbortMsg struct {
  1011. Foo string `json:"foo"`
  1012. Bar string `json:"bar"`
  1013. }
  1014. func TestContextAbortWithStatusJSON(t *testing.T) {
  1015. w := httptest.NewRecorder()
  1016. c, _ := CreateTestContext(w)
  1017. c.index = 4
  1018. in := new(testJSONAbortMsg)
  1019. in.Bar = "barValue"
  1020. in.Foo = "fooValue"
  1021. c.AbortWithStatusJSON(http.StatusUnsupportedMediaType, in)
  1022. assert.Equal(t, abortIndex, c.index)
  1023. assert.Equal(t, http.StatusUnsupportedMediaType, c.Writer.Status())
  1024. assert.Equal(t, http.StatusUnsupportedMediaType, w.Code)
  1025. assert.True(t, c.IsAborted())
  1026. contentType := w.Header().Get("Content-Type")
  1027. assert.Equal(t, "application/json; charset=utf-8", contentType)
  1028. buf := new(bytes.Buffer)
  1029. _, err := buf.ReadFrom(w.Body)
  1030. assert.NoError(t, err)
  1031. jsonStringBody := buf.String()
  1032. assert.Equal(t, fmt.Sprint(`{"foo":"fooValue","bar":"barValue"}`), jsonStringBody)
  1033. }
  1034. func TestContextError(t *testing.T) {
  1035. c, _ := CreateTestContext(httptest.NewRecorder())
  1036. assert.Empty(t, c.Errors)
  1037. firstErr := errors.New("first error")
  1038. c.Error(firstErr) // nolint: errcheck
  1039. assert.Len(t, c.Errors, 1)
  1040. assert.Equal(t, "Error #01: first error\n", c.Errors.String())
  1041. secondErr := errors.New("second error")
  1042. c.Error(&Error{ // nolint: errcheck
  1043. Err: secondErr,
  1044. Meta: "some data 2",
  1045. Type: ErrorTypePublic,
  1046. })
  1047. assert.Len(t, c.Errors, 2)
  1048. assert.Equal(t, firstErr, c.Errors[0].Err)
  1049. assert.Nil(t, c.Errors[0].Meta)
  1050. assert.Equal(t, ErrorTypePrivate, c.Errors[0].Type)
  1051. assert.Equal(t, secondErr, c.Errors[1].Err)
  1052. assert.Equal(t, "some data 2", c.Errors[1].Meta)
  1053. assert.Equal(t, ErrorTypePublic, c.Errors[1].Type)
  1054. assert.Equal(t, c.Errors.Last(), c.Errors[1])
  1055. defer func() {
  1056. if recover() == nil {
  1057. t.Error("didn't panic")
  1058. }
  1059. }()
  1060. c.Error(nil) // nolint: errcheck
  1061. }
  1062. func TestContextTypedError(t *testing.T) {
  1063. c, _ := CreateTestContext(httptest.NewRecorder())
  1064. c.Error(errors.New("externo 0")).SetType(ErrorTypePublic) // nolint: errcheck
  1065. c.Error(errors.New("interno 0")).SetType(ErrorTypePrivate) // nolint: errcheck
  1066. for _, err := range c.Errors.ByType(ErrorTypePublic) {
  1067. assert.Equal(t, ErrorTypePublic, err.Type)
  1068. }
  1069. for _, err := range c.Errors.ByType(ErrorTypePrivate) {
  1070. assert.Equal(t, ErrorTypePrivate, err.Type)
  1071. }
  1072. assert.Equal(t, []string{"externo 0", "interno 0"}, c.Errors.Errors())
  1073. }
  1074. func TestContextAbortWithError(t *testing.T) {
  1075. w := httptest.NewRecorder()
  1076. c, _ := CreateTestContext(w)
  1077. c.AbortWithError(http.StatusUnauthorized, errors.New("bad input")).SetMeta("some input") // nolint: errcheck
  1078. assert.Equal(t, http.StatusUnauthorized, w.Code)
  1079. assert.Equal(t, abortIndex, c.index)
  1080. assert.True(t, c.IsAborted())
  1081. }
  1082. func TestContextClientIP(t *testing.T) {
  1083. c, _ := CreateTestContext(httptest.NewRecorder())
  1084. c.Request, _ = http.NewRequest("POST", "/", nil)
  1085. c.Request.Header.Set("X-Real-IP", " 10.10.10.10 ")
  1086. c.Request.Header.Set("X-Forwarded-For", " 20.20.20.20, 30.30.30.30")
  1087. c.Request.Header.Set("X-Appengine-Remote-Addr", "50.50.50.50")
  1088. c.Request.RemoteAddr = " 40.40.40.40:42123 "
  1089. assert.Equal(t, "20.20.20.20", c.ClientIP())
  1090. c.Request.Header.Del("X-Forwarded-For")
  1091. assert.Equal(t, "10.10.10.10", c.ClientIP())
  1092. c.Request.Header.Set("X-Forwarded-For", "30.30.30.30 ")
  1093. assert.Equal(t, "30.30.30.30", c.ClientIP())
  1094. c.Request.Header.Del("X-Forwarded-For")
  1095. c.Request.Header.Del("X-Real-IP")
  1096. c.engine.AppEngine = true
  1097. assert.Equal(t, "50.50.50.50", c.ClientIP())
  1098. c.Request.Header.Del("X-Appengine-Remote-Addr")
  1099. assert.Equal(t, "40.40.40.40", c.ClientIP())
  1100. // no port
  1101. c.Request.RemoteAddr = "50.50.50.50"
  1102. assert.Empty(t, c.ClientIP())
  1103. }
  1104. func TestContextContentType(t *testing.T) {
  1105. c, _ := CreateTestContext(httptest.NewRecorder())
  1106. c.Request, _ = http.NewRequest("POST", "/", nil)
  1107. c.Request.Header.Set("Content-Type", "application/json; charset=utf-8")
  1108. assert.Equal(t, "application/json", c.ContentType())
  1109. }
  1110. func TestContextAutoBindJSON(t *testing.T) {
  1111. c, _ := CreateTestContext(httptest.NewRecorder())
  1112. c.Request, _ = http.NewRequest("POST", "/", bytes.NewBufferString("{\"foo\":\"bar\", \"bar\":\"foo\"}"))
  1113. c.Request.Header.Add("Content-Type", MIMEJSON)
  1114. var obj struct {
  1115. Foo string `json:"foo"`
  1116. Bar string `json:"bar"`
  1117. }
  1118. assert.NoError(t, c.Bind(&obj))
  1119. assert.Equal(t, "foo", obj.Bar)
  1120. assert.Equal(t, "bar", obj.Foo)
  1121. assert.Empty(t, c.Errors)
  1122. }
  1123. func TestContextBindWithJSON(t *testing.T) {
  1124. w := httptest.NewRecorder()
  1125. c, _ := CreateTestContext(w)
  1126. c.Request, _ = http.NewRequest("POST", "/", bytes.NewBufferString("{\"foo\":\"bar\", \"bar\":\"foo\"}"))
  1127. c.Request.Header.Add("Content-Type", MIMEXML) // set fake content-type
  1128. var obj struct {
  1129. Foo string `json:"foo"`
  1130. Bar string `json:"bar"`
  1131. }
  1132. assert.NoError(t, c.BindJSON(&obj))
  1133. assert.Equal(t, "foo", obj.Bar)
  1134. assert.Equal(t, "bar", obj.Foo)
  1135. assert.Equal(t, 0, w.Body.Len())
  1136. }
  1137. func TestContextBindWithXML(t *testing.T) {
  1138. w := httptest.NewRecorder()
  1139. c, _ := CreateTestContext(w)
  1140. c.Request, _ = http.NewRequest("POST", "/", bytes.NewBufferString(`<?xml version="1.0" encoding="UTF-8"?>
  1141. <root>
  1142. <foo>FOO</foo>
  1143. <bar>BAR</bar>
  1144. </root>`))
  1145. c.Request.Header.Add("Content-Type", MIMEXML) // set fake content-type
  1146. var obj struct {
  1147. Foo string `xml:"foo"`
  1148. Bar string `xml:"bar"`
  1149. }
  1150. assert.NoError(t, c.BindXML(&obj))
  1151. assert.Equal(t, "FOO", obj.Foo)
  1152. assert.Equal(t, "BAR", obj.Bar)
  1153. assert.Equal(t, 0, w.Body.Len())
  1154. }
  1155. func TestContextBindWithQuery(t *testing.T) {
  1156. w := httptest.NewRecorder()
  1157. c, _ := CreateTestContext(w)
  1158. c.Request, _ = http.NewRequest("POST", "/?foo=bar&bar=foo", bytes.NewBufferString("foo=unused"))
  1159. var obj struct {
  1160. Foo string `form:"foo"`
  1161. Bar string `form:"bar"`
  1162. }
  1163. assert.NoError(t, c.BindQuery(&obj))
  1164. assert.Equal(t, "foo", obj.Bar)
  1165. assert.Equal(t, "bar", obj.Foo)
  1166. assert.Equal(t, 0, w.Body.Len())
  1167. }
  1168. func TestContextBindWithYAML(t *testing.T) {
  1169. w := httptest.NewRecorder()
  1170. c, _ := CreateTestContext(w)
  1171. c.Request, _ = http.NewRequest("POST", "/", bytes.NewBufferString("foo: bar\nbar: foo"))
  1172. c.Request.Header.Add("Content-Type", MIMEXML) // set fake content-type
  1173. var obj struct {
  1174. Foo string `yaml:"foo"`
  1175. Bar string `yaml:"bar"`
  1176. }
  1177. assert.NoError(t, c.BindYAML(&obj))
  1178. assert.Equal(t, "foo", obj.Bar)
  1179. assert.Equal(t, "bar", obj.Foo)
  1180. assert.Equal(t, 0, w.Body.Len())
  1181. }
  1182. func TestContextBadAutoBind(t *testing.T) {
  1183. w := httptest.NewRecorder()
  1184. c, _ := CreateTestContext(w)
  1185. c.Request, _ = http.NewRequest("POST", "http://example.com", bytes.NewBufferString("\"foo\":\"bar\", \"bar\":\"foo\"}"))
  1186. c.Request.Header.Add("Content-Type", MIMEJSON)
  1187. var obj struct {
  1188. Foo string `json:"foo"`
  1189. Bar string `json:"bar"`
  1190. }
  1191. assert.False(t, c.IsAborted())
  1192. assert.Error(t, c.Bind(&obj))
  1193. c.Writer.WriteHeaderNow()
  1194. assert.Empty(t, obj.Bar)
  1195. assert.Empty(t, obj.Foo)
  1196. assert.Equal(t, http.StatusBadRequest, w.Code)
  1197. assert.True(t, c.IsAborted())
  1198. }
  1199. func TestContextAutoShouldBindJSON(t *testing.T) {
  1200. c, _ := CreateTestContext(httptest.NewRecorder())
  1201. c.Request, _ = http.NewRequest("POST", "/", bytes.NewBufferString("{\"foo\":\"bar\", \"bar\":\"foo\"}"))
  1202. c.Request.Header.Add("Content-Type", MIMEJSON)
  1203. var obj struct {
  1204. Foo string `json:"foo"`
  1205. Bar string `json:"bar"`
  1206. }
  1207. assert.NoError(t, c.ShouldBind(&obj))
  1208. assert.Equal(t, "foo", obj.Bar)
  1209. assert.Equal(t, "bar", obj.Foo)
  1210. assert.Empty(t, c.Errors)
  1211. }
  1212. func TestContextShouldBindWithJSON(t *testing.T) {
  1213. w := httptest.NewRecorder()
  1214. c, _ := CreateTestContext(w)
  1215. c.Request, _ = http.NewRequest("POST", "/", bytes.NewBufferString("{\"foo\":\"bar\", \"bar\":\"foo\"}"))
  1216. c.Request.Header.Add("Content-Type", MIMEXML) // set fake content-type
  1217. var obj struct {
  1218. Foo string `json:"foo"`
  1219. Bar string `json:"bar"`
  1220. }
  1221. assert.NoError(t, c.ShouldBindJSON(&obj))
  1222. assert.Equal(t, "foo", obj.Bar)
  1223. assert.Equal(t, "bar", obj.Foo)
  1224. assert.Equal(t, 0, w.Body.Len())
  1225. }
  1226. func TestContextShouldBindWithXML(t *testing.T) {
  1227. w := httptest.NewRecorder()
  1228. c, _ := CreateTestContext(w)
  1229. c.Request, _ = http.NewRequest("POST", "/", bytes.NewBufferString(`<?xml version="1.0" encoding="UTF-8"?>
  1230. <root>
  1231. <foo>FOO</foo>
  1232. <bar>BAR</bar>
  1233. </root>`))
  1234. c.Request.Header.Add("Content-Type", MIMEXML) // set fake content-type
  1235. var obj struct {
  1236. Foo string `xml:"foo"`
  1237. Bar string `xml:"bar"`
  1238. }
  1239. assert.NoError(t, c.ShouldBindXML(&obj))
  1240. assert.Equal(t, "FOO", obj.Foo)
  1241. assert.Equal(t, "BAR", obj.Bar)
  1242. assert.Equal(t, 0, w.Body.Len())
  1243. }
  1244. func TestContextShouldBindWithQuery(t *testing.T) {
  1245. w := httptest.NewRecorder()
  1246. c, _ := CreateTestContext(w)
  1247. c.Request, _ = http.NewRequest("POST", "/?foo=bar&bar=foo&Foo=bar1&Bar=foo1", bytes.NewBufferString("foo=unused"))
  1248. var obj struct {
  1249. Foo string `form:"foo"`
  1250. Bar string `form:"bar"`
  1251. Foo1 string `form:"Foo"`
  1252. Bar1 string `form:"Bar"`
  1253. }
  1254. assert.NoError(t, c.ShouldBindQuery(&obj))
  1255. assert.Equal(t, "foo", obj.Bar)
  1256. assert.Equal(t, "bar", obj.Foo)
  1257. assert.Equal(t, "foo1", obj.Bar1)
  1258. assert.Equal(t, "bar1", obj.Foo1)
  1259. assert.Equal(t, 0, w.Body.Len())
  1260. }
  1261. func TestContextShouldBindWithYAML(t *testing.T) {
  1262. w := httptest.NewRecorder()
  1263. c, _ := CreateTestContext(w)
  1264. c.Request, _ = http.NewRequest("POST", "/", bytes.NewBufferString("foo: bar\nbar: foo"))
  1265. c.Request.Header.Add("Content-Type", MIMEXML) // set fake content-type
  1266. var obj struct {
  1267. Foo string `yaml:"foo"`
  1268. Bar string `yaml:"bar"`
  1269. }
  1270. assert.NoError(t, c.ShouldBindYAML(&obj))
  1271. assert.Equal(t, "foo", obj.Bar)
  1272. assert.Equal(t, "bar", obj.Foo)
  1273. assert.Equal(t, 0, w.Body.Len())
  1274. }
  1275. func TestContextBadAutoShouldBind(t *testing.T) {
  1276. w := httptest.NewRecorder()
  1277. c, _ := CreateTestContext(w)
  1278. c.Request, _ = http.NewRequest("POST", "http://example.com", bytes.NewBufferString("\"foo\":\"bar\", \"bar\":\"foo\"}"))
  1279. c.Request.Header.Add("Content-Type", MIMEJSON)
  1280. var obj struct {
  1281. Foo string `json:"foo"`
  1282. Bar string `json:"bar"`
  1283. }
  1284. assert.False(t, c.IsAborted())
  1285. assert.Error(t, c.ShouldBind(&obj))
  1286. assert.Empty(t, obj.Bar)
  1287. assert.Empty(t, obj.Foo)
  1288. assert.False(t, c.IsAborted())
  1289. }
  1290. func TestContextShouldBindBodyWith(t *testing.T) {
  1291. type typeA struct {
  1292. Foo string `json:"foo" xml:"foo" binding:"required"`
  1293. }
  1294. type typeB struct {
  1295. Bar string `json:"bar" xml:"bar" binding:"required"`
  1296. }
  1297. for _, tt := range []struct {
  1298. name string
  1299. bindingA, bindingB binding.BindingBody
  1300. bodyA, bodyB string
  1301. }{
  1302. {
  1303. name: "JSON & JSON",
  1304. bindingA: binding.JSON,
  1305. bindingB: binding.JSON,
  1306. bodyA: `{"foo":"FOO"}`,
  1307. bodyB: `{"bar":"BAR"}`,
  1308. },
  1309. {
  1310. name: "JSON & XML",
  1311. bindingA: binding.JSON,
  1312. bindingB: binding.XML,
  1313. bodyA: `{"foo":"FOO"}`,
  1314. bodyB: `<?xml version="1.0" encoding="UTF-8"?>
  1315. <root>
  1316. <bar>BAR</bar>
  1317. </root>`,
  1318. },
  1319. {
  1320. name: "XML & XML",
  1321. bindingA: binding.XML,
  1322. bindingB: binding.XML,
  1323. bodyA: `<?xml version="1.0" encoding="UTF-8"?>
  1324. <root>
  1325. <foo>FOO</foo>
  1326. </root>`,
  1327. bodyB: `<?xml version="1.0" encoding="UTF-8"?>
  1328. <root>
  1329. <bar>BAR</bar>
  1330. </root>`,
  1331. },
  1332. } {
  1333. t.Logf("testing: %s", tt.name)
  1334. // bodyA to typeA and typeB
  1335. {
  1336. w := httptest.NewRecorder()
  1337. c, _ := CreateTestContext(w)
  1338. c.Request, _ = http.NewRequest(
  1339. "POST", "http://example.com", bytes.NewBufferString(tt.bodyA),
  1340. )
  1341. // When it binds to typeA and typeB, it finds the body is
  1342. // not typeB but typeA.
  1343. objA := typeA{}
  1344. assert.NoError(t, c.ShouldBindBodyWith(&objA, tt.bindingA))
  1345. assert.Equal(t, typeA{"FOO"}, objA)
  1346. objB := typeB{}
  1347. assert.Error(t, c.ShouldBindBodyWith(&objB, tt.bindingB))
  1348. assert.NotEqual(t, typeB{"BAR"}, objB)
  1349. }
  1350. // bodyB to typeA and typeB
  1351. {
  1352. // When it binds to typeA and typeB, it finds the body is
  1353. // not typeA but typeB.
  1354. w := httptest.NewRecorder()
  1355. c, _ := CreateTestContext(w)
  1356. c.Request, _ = http.NewRequest(
  1357. "POST", "http://example.com", bytes.NewBufferString(tt.bodyB),
  1358. )
  1359. objA := typeA{}
  1360. assert.Error(t, c.ShouldBindBodyWith(&objA, tt.bindingA))
  1361. assert.NotEqual(t, typeA{"FOO"}, objA)
  1362. objB := typeB{}
  1363. assert.NoError(t, c.ShouldBindBodyWith(&objB, tt.bindingB))
  1364. assert.Equal(t, typeB{"BAR"}, objB)
  1365. }
  1366. }
  1367. }
  1368. func TestContextGolangContext(t *testing.T) {
  1369. c, _ := CreateTestContext(httptest.NewRecorder())
  1370. c.Request, _ = http.NewRequest("POST", "/", bytes.NewBufferString("{\"foo\":\"bar\", \"bar\":\"foo\"}"))
  1371. assert.NoError(t, c.Err())
  1372. assert.Nil(t, c.Done())
  1373. ti, ok := c.Deadline()
  1374. assert.Equal(t, ti, time.Time{})
  1375. assert.False(t, ok)
  1376. assert.Equal(t, c.Value(0), c.Request)
  1377. assert.Nil(t, c.Value("foo"))
  1378. c.Set("foo", "bar")
  1379. assert.Equal(t, "bar", c.Value("foo"))
  1380. assert.Nil(t, c.Value(1))
  1381. }
  1382. func TestWebsocketsRequired(t *testing.T) {
  1383. // Example request from spec: https://tools.ietf.org/html/rfc6455#section-1.2
  1384. c, _ := CreateTestContext(httptest.NewRecorder())
  1385. c.Request, _ = http.NewRequest("GET", "/chat", nil)
  1386. c.Request.Header.Set("Host", "server.example.com")
  1387. c.Request.Header.Set("Upgrade", "websocket")
  1388. c.Request.Header.Set("Connection", "Upgrade")
  1389. c.Request.Header.Set("Sec-WebSocket-Key", "dGhlIHNhbXBsZSBub25jZQ==")
  1390. c.Request.Header.Set("Origin", "http://example.com")
  1391. c.Request.Header.Set("Sec-WebSocket-Protocol", "chat, superchat")
  1392. c.Request.Header.Set("Sec-WebSocket-Version", "13")
  1393. assert.True(t, c.IsWebsocket())
  1394. // Normal request, no websocket required.
  1395. c, _ = CreateTestContext(httptest.NewRecorder())
  1396. c.Request, _ = http.NewRequest("GET", "/chat", nil)
  1397. c.Request.Header.Set("Host", "server.example.com")
  1398. assert.False(t, c.IsWebsocket())
  1399. }
  1400. func TestGetRequestHeaderValue(t *testing.T) {
  1401. c, _ := CreateTestContext(httptest.NewRecorder())
  1402. c.Request, _ = http.NewRequest("GET", "/chat", nil)
  1403. c.Request.Header.Set("Gin-Version", "1.0.0")
  1404. assert.Equal(t, "1.0.0", c.GetHeader("Gin-Version"))
  1405. assert.Empty(t, c.GetHeader("Connection"))
  1406. }
  1407. func TestContextGetRawData(t *testing.T) {
  1408. c, _ := CreateTestContext(httptest.NewRecorder())
  1409. body := bytes.NewBufferString("Fetch binary post data")
  1410. c.Request, _ = http.NewRequest("POST", "/", body)
  1411. c.Request.Header.Add("Content-Type", MIMEPOSTForm)
  1412. data, err := c.GetRawData()
  1413. assert.Nil(t, err)
  1414. assert.Equal(t, "Fetch binary post data", string(data))
  1415. }
  1416. func TestContextRenderDataFromReader(t *testing.T) {
  1417. w := httptest.NewRecorder()
  1418. c, _ := CreateTestContext(w)
  1419. body := "#!PNG some raw data"
  1420. reader := strings.NewReader(body)
  1421. contentLength := int64(len(body))
  1422. contentType := "image/png"
  1423. extraHeaders := map[string]string{"Content-Disposition": `attachment; filename="gopher.png"`}
  1424. c.DataFromReader(http.StatusOK, contentLength, contentType, reader, extraHeaders)
  1425. assert.Equal(t, http.StatusOK, w.Code)
  1426. assert.Equal(t, body, w.Body.String())
  1427. assert.Equal(t, contentType, w.Header().Get("Content-Type"))
  1428. assert.Equal(t, fmt.Sprintf("%d", contentLength), w.Header().Get("Content-Length"))
  1429. assert.Equal(t, extraHeaders["Content-Disposition"], w.Header().Get("Content-Disposition"))
  1430. }
  1431. type TestResponseRecorder struct {
  1432. *httptest.ResponseRecorder
  1433. closeChannel chan bool
  1434. }
  1435. func (r *TestResponseRecorder) CloseNotify() <-chan bool {
  1436. return r.closeChannel
  1437. }
  1438. func (r *TestResponseRecorder) closeClient() {
  1439. r.closeChannel <- true
  1440. }
  1441. func CreateTestResponseRecorder() *TestResponseRecorder {
  1442. return &TestResponseRecorder{
  1443. httptest.NewRecorder(),
  1444. make(chan bool, 1),
  1445. }
  1446. }
  1447. func TestContextStream(t *testing.T) {
  1448. w := CreateTestResponseRecorder()
  1449. c, _ := CreateTestContext(w)
  1450. stopStream := true
  1451. c.Stream(func(w io.Writer) bool {
  1452. defer func() {
  1453. stopStream = false
  1454. }()
  1455. _, err := w.Write([]byte("test"))
  1456. assert.NoError(t, err)
  1457. return stopStream
  1458. })
  1459. assert.Equal(t, "testtest", w.Body.String())
  1460. }
  1461. func TestContextStreamWithClientGone(t *testing.T) {
  1462. w := CreateTestResponseRecorder()
  1463. c, _ := CreateTestContext(w)
  1464. c.Stream(func(writer io.Writer) bool {
  1465. defer func() {
  1466. w.closeClient()
  1467. }()
  1468. _, err := writer.Write([]byte("test"))
  1469. assert.NoError(t, err)
  1470. return true
  1471. })
  1472. assert.Equal(t, "test", w.Body.String())
  1473. }
  1474. func TestContextResetInHandler(t *testing.T) {
  1475. w := CreateTestResponseRecorder()
  1476. c, _ := CreateTestContext(w)
  1477. c.handlers = []HandlerFunc{
  1478. func(c *Context) { c.reset() },
  1479. }
  1480. assert.NotPanics(t, func() {
  1481. c.Next()
  1482. })
  1483. }