context_test.go 52 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745
  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. }
  285. func TestContextHandlerName(t *testing.T) {
  286. c, _ := CreateTestContext(httptest.NewRecorder())
  287. c.handlers = HandlersChain{func(c *Context) {}, handlerNameTest}
  288. assert.Regexp(t, "^(.*/vendor/)?github.com/gin-gonic/gin.handlerNameTest$", c.HandlerName())
  289. }
  290. func handlerNameTest(c *Context) {
  291. }
  292. var handlerTest HandlerFunc = func(c *Context) {
  293. }
  294. func TestContextHandler(t *testing.T) {
  295. c, _ := CreateTestContext(httptest.NewRecorder())
  296. c.handlers = HandlersChain{func(c *Context) {}, handlerTest}
  297. assert.Equal(t, reflect.ValueOf(handlerTest).Pointer(), reflect.ValueOf(c.Handler()).Pointer())
  298. }
  299. func TestContextQuery(t *testing.T) {
  300. c, _ := CreateTestContext(httptest.NewRecorder())
  301. c.Request, _ = http.NewRequest("GET", "http://example.com/?foo=bar&page=10&id=", nil)
  302. value, ok := c.GetQuery("foo")
  303. assert.True(t, ok)
  304. assert.Equal(t, "bar", value)
  305. assert.Equal(t, "bar", c.DefaultQuery("foo", "none"))
  306. assert.Equal(t, "bar", c.Query("foo"))
  307. value, ok = c.GetQuery("page")
  308. assert.True(t, ok)
  309. assert.Equal(t, "10", value)
  310. assert.Equal(t, "10", c.DefaultQuery("page", "0"))
  311. assert.Equal(t, "10", c.Query("page"))
  312. value, ok = c.GetQuery("id")
  313. assert.True(t, ok)
  314. assert.Empty(t, value)
  315. assert.Empty(t, c.DefaultQuery("id", "nada"))
  316. assert.Empty(t, c.Query("id"))
  317. value, ok = c.GetQuery("NoKey")
  318. assert.False(t, ok)
  319. assert.Empty(t, value)
  320. assert.Equal(t, "nada", c.DefaultQuery("NoKey", "nada"))
  321. assert.Empty(t, c.Query("NoKey"))
  322. // postform should not mess
  323. value, ok = c.GetPostForm("page")
  324. assert.False(t, ok)
  325. assert.Empty(t, value)
  326. assert.Empty(t, c.PostForm("foo"))
  327. }
  328. func TestContextQueryAndPostForm(t *testing.T) {
  329. c, _ := CreateTestContext(httptest.NewRecorder())
  330. body := bytes.NewBufferString("foo=bar&page=11&both=&foo=second")
  331. c.Request, _ = http.NewRequest("POST",
  332. "/?both=GET&id=main&id=omit&array[]=first&array[]=second&ids[a]=hi&ids[b]=3.14", body)
  333. c.Request.Header.Add("Content-Type", MIMEPOSTForm)
  334. assert.Equal(t, "bar", c.DefaultPostForm("foo", "none"))
  335. assert.Equal(t, "bar", c.PostForm("foo"))
  336. assert.Empty(t, c.Query("foo"))
  337. value, ok := c.GetPostForm("page")
  338. assert.True(t, ok)
  339. assert.Equal(t, "11", value)
  340. assert.Equal(t, "11", c.DefaultPostForm("page", "0"))
  341. assert.Equal(t, "11", c.PostForm("page"))
  342. assert.Empty(t, c.Query("page"))
  343. value, ok = c.GetPostForm("both")
  344. assert.True(t, ok)
  345. assert.Empty(t, value)
  346. assert.Empty(t, c.PostForm("both"))
  347. assert.Empty(t, c.DefaultPostForm("both", "nothing"))
  348. assert.Equal(t, "GET", c.Query("both"), "GET")
  349. value, ok = c.GetQuery("id")
  350. assert.True(t, ok)
  351. assert.Equal(t, "main", value)
  352. assert.Equal(t, "000", c.DefaultPostForm("id", "000"))
  353. assert.Equal(t, "main", c.Query("id"))
  354. assert.Empty(t, c.PostForm("id"))
  355. value, ok = c.GetQuery("NoKey")
  356. assert.False(t, ok)
  357. assert.Empty(t, value)
  358. value, ok = c.GetPostForm("NoKey")
  359. assert.False(t, ok)
  360. assert.Empty(t, value)
  361. assert.Equal(t, "nada", c.DefaultPostForm("NoKey", "nada"))
  362. assert.Equal(t, "nothing", c.DefaultQuery("NoKey", "nothing"))
  363. assert.Empty(t, c.PostForm("NoKey"))
  364. assert.Empty(t, c.Query("NoKey"))
  365. var obj struct {
  366. Foo string `form:"foo"`
  367. ID string `form:"id"`
  368. Page int `form:"page"`
  369. Both string `form:"both"`
  370. Array []string `form:"array[]"`
  371. }
  372. assert.NoError(t, c.Bind(&obj))
  373. assert.Equal(t, "bar", obj.Foo, "bar")
  374. assert.Equal(t, "main", obj.ID, "main")
  375. assert.Equal(t, 11, obj.Page, 11)
  376. assert.Empty(t, obj.Both)
  377. assert.Equal(t, []string{"first", "second"}, obj.Array)
  378. values, ok := c.GetQueryArray("array[]")
  379. assert.True(t, ok)
  380. assert.Equal(t, "first", values[0])
  381. assert.Equal(t, "second", values[1])
  382. values = c.QueryArray("array[]")
  383. assert.Equal(t, "first", values[0])
  384. assert.Equal(t, "second", values[1])
  385. values = c.QueryArray("nokey")
  386. assert.Equal(t, 0, len(values))
  387. values = c.QueryArray("both")
  388. assert.Equal(t, 1, len(values))
  389. assert.Equal(t, "GET", values[0])
  390. dicts, ok := c.GetQueryMap("ids")
  391. assert.True(t, ok)
  392. assert.Equal(t, "hi", dicts["a"])
  393. assert.Equal(t, "3.14", dicts["b"])
  394. dicts, ok = c.GetQueryMap("nokey")
  395. assert.False(t, ok)
  396. assert.Equal(t, 0, len(dicts))
  397. dicts, ok = c.GetQueryMap("both")
  398. assert.False(t, ok)
  399. assert.Equal(t, 0, len(dicts))
  400. dicts, ok = c.GetQueryMap("array")
  401. assert.False(t, ok)
  402. assert.Equal(t, 0, len(dicts))
  403. dicts = c.QueryMap("ids")
  404. assert.Equal(t, "hi", dicts["a"])
  405. assert.Equal(t, "3.14", dicts["b"])
  406. dicts = c.QueryMap("nokey")
  407. assert.Equal(t, 0, len(dicts))
  408. }
  409. func TestContextPostFormMultipart(t *testing.T) {
  410. c, _ := CreateTestContext(httptest.NewRecorder())
  411. c.Request = createMultipartRequest()
  412. var obj struct {
  413. Foo string `form:"foo"`
  414. Bar string `form:"bar"`
  415. BarAsInt int `form:"bar"`
  416. Array []string `form:"array"`
  417. ID string `form:"id"`
  418. TimeLocal time.Time `form:"time_local" time_format:"02/01/2006 15:04"`
  419. TimeUTC time.Time `form:"time_utc" time_format:"02/01/2006 15:04" time_utc:"1"`
  420. TimeLocation time.Time `form:"time_location" time_format:"02/01/2006 15:04" time_location:"Asia/Tokyo"`
  421. BlankTime time.Time `form:"blank_time" time_format:"02/01/2006 15:04"`
  422. }
  423. assert.NoError(t, c.Bind(&obj))
  424. assert.Equal(t, "bar", obj.Foo)
  425. assert.Equal(t, "10", obj.Bar)
  426. assert.Equal(t, 10, obj.BarAsInt)
  427. assert.Equal(t, []string{"first", "second"}, obj.Array)
  428. assert.Empty(t, obj.ID)
  429. assert.Equal(t, "31/12/2016 14:55", obj.TimeLocal.Format("02/01/2006 15:04"))
  430. assert.Equal(t, time.Local, obj.TimeLocal.Location())
  431. assert.Equal(t, "31/12/2016 14:55", obj.TimeUTC.Format("02/01/2006 15:04"))
  432. assert.Equal(t, time.UTC, obj.TimeUTC.Location())
  433. loc, _ := time.LoadLocation("Asia/Tokyo")
  434. assert.Equal(t, "31/12/2016 14:55", obj.TimeLocation.Format("02/01/2006 15:04"))
  435. assert.Equal(t, loc, obj.TimeLocation.Location())
  436. assert.True(t, obj.BlankTime.IsZero())
  437. value, ok := c.GetQuery("foo")
  438. assert.False(t, ok)
  439. assert.Empty(t, value)
  440. assert.Empty(t, c.Query("bar"))
  441. assert.Equal(t, "nothing", c.DefaultQuery("id", "nothing"))
  442. value, ok = c.GetPostForm("foo")
  443. assert.True(t, ok)
  444. assert.Equal(t, "bar", value)
  445. assert.Equal(t, "bar", c.PostForm("foo"))
  446. value, ok = c.GetPostForm("array")
  447. assert.True(t, ok)
  448. assert.Equal(t, "first", value)
  449. assert.Equal(t, "first", c.PostForm("array"))
  450. assert.Equal(t, "10", c.DefaultPostForm("bar", "nothing"))
  451. value, ok = c.GetPostForm("id")
  452. assert.True(t, ok)
  453. assert.Empty(t, value)
  454. assert.Empty(t, c.PostForm("id"))
  455. assert.Empty(t, c.DefaultPostForm("id", "nothing"))
  456. value, ok = c.GetPostForm("nokey")
  457. assert.False(t, ok)
  458. assert.Empty(t, value)
  459. assert.Equal(t, "nothing", c.DefaultPostForm("nokey", "nothing"))
  460. values, ok := c.GetPostFormArray("array")
  461. assert.True(t, ok)
  462. assert.Equal(t, "first", values[0])
  463. assert.Equal(t, "second", values[1])
  464. values = c.PostFormArray("array")
  465. assert.Equal(t, "first", values[0])
  466. assert.Equal(t, "second", values[1])
  467. values = c.PostFormArray("nokey")
  468. assert.Equal(t, 0, len(values))
  469. values = c.PostFormArray("foo")
  470. assert.Equal(t, 1, len(values))
  471. assert.Equal(t, "bar", values[0])
  472. dicts, ok := c.GetPostFormMap("names")
  473. assert.True(t, ok)
  474. assert.Equal(t, "thinkerou", dicts["a"])
  475. assert.Equal(t, "tianou", dicts["b"])
  476. dicts, ok = c.GetPostFormMap("nokey")
  477. assert.False(t, ok)
  478. assert.Equal(t, 0, len(dicts))
  479. dicts = c.PostFormMap("names")
  480. assert.Equal(t, "thinkerou", dicts["a"])
  481. assert.Equal(t, "tianou", dicts["b"])
  482. dicts = c.PostFormMap("nokey")
  483. assert.Equal(t, 0, len(dicts))
  484. }
  485. func TestContextSetCookie(t *testing.T) {
  486. c, _ := CreateTestContext(httptest.NewRecorder())
  487. c.SetCookie("user", "gin", 1, "/", "localhost", true, true)
  488. assert.Equal(t, "user=gin; Path=/; Domain=localhost; Max-Age=1; HttpOnly; Secure", c.Writer.Header().Get("Set-Cookie"))
  489. }
  490. func TestContextSetCookiePathEmpty(t *testing.T) {
  491. c, _ := CreateTestContext(httptest.NewRecorder())
  492. c.SetCookie("user", "gin", 1, "", "localhost", true, true)
  493. assert.Equal(t, "user=gin; Path=/; Domain=localhost; Max-Age=1; HttpOnly; Secure", c.Writer.Header().Get("Set-Cookie"))
  494. }
  495. func TestContextGetCookie(t *testing.T) {
  496. c, _ := CreateTestContext(httptest.NewRecorder())
  497. c.Request, _ = http.NewRequest("GET", "/get", nil)
  498. c.Request.Header.Set("Cookie", "user=gin")
  499. cookie, _ := c.Cookie("user")
  500. assert.Equal(t, "gin", cookie)
  501. _, err := c.Cookie("nokey")
  502. assert.Error(t, err)
  503. }
  504. func TestContextBodyAllowedForStatus(t *testing.T) {
  505. // todo(thinkerou): go1.6 not support StatusProcessing
  506. assert.False(t, false, bodyAllowedForStatus(102))
  507. assert.False(t, false, bodyAllowedForStatus(http.StatusNoContent))
  508. assert.False(t, false, bodyAllowedForStatus(http.StatusNotModified))
  509. assert.True(t, true, bodyAllowedForStatus(http.StatusInternalServerError))
  510. }
  511. type TestPanicRender struct {
  512. }
  513. func (*TestPanicRender) Render(http.ResponseWriter) error {
  514. return errors.New("TestPanicRender")
  515. }
  516. func (*TestPanicRender) WriteContentType(http.ResponseWriter) {}
  517. func TestContextRenderPanicIfErr(t *testing.T) {
  518. defer func() {
  519. r := recover()
  520. assert.Equal(t, "TestPanicRender", fmt.Sprint(r))
  521. }()
  522. w := httptest.NewRecorder()
  523. c, _ := CreateTestContext(w)
  524. c.Render(http.StatusOK, &TestPanicRender{})
  525. assert.Fail(t, "Panic not detected")
  526. }
  527. // Tests that the response is serialized as JSON
  528. // and Content-Type is set to application/json
  529. // and special HTML characters are escaped
  530. func TestContextRenderJSON(t *testing.T) {
  531. w := httptest.NewRecorder()
  532. c, _ := CreateTestContext(w)
  533. c.JSON(http.StatusCreated, H{"foo": "bar", "html": "<b>"})
  534. assert.Equal(t, http.StatusCreated, w.Code)
  535. assert.Equal(t, "{\"foo\":\"bar\",\"html\":\"\\u003cb\\u003e\"}", w.Body.String())
  536. assert.Equal(t, "application/json; charset=utf-8", w.Header().Get("Content-Type"))
  537. }
  538. // Tests that the response is serialized as JSONP
  539. // and Content-Type is set to application/javascript
  540. func TestContextRenderJSONP(t *testing.T) {
  541. w := httptest.NewRecorder()
  542. c, _ := CreateTestContext(w)
  543. c.Request, _ = http.NewRequest("GET", "http://example.com/?callback=x", nil)
  544. c.JSONP(http.StatusCreated, H{"foo": "bar"})
  545. assert.Equal(t, http.StatusCreated, w.Code)
  546. assert.Equal(t, "x({\"foo\":\"bar\"})", w.Body.String())
  547. assert.Equal(t, "application/javascript; charset=utf-8", w.Header().Get("Content-Type"))
  548. }
  549. // Tests that the response is serialized as JSONP
  550. // and Content-Type is set to application/json
  551. func TestContextRenderJSONPWithoutCallback(t *testing.T) {
  552. w := httptest.NewRecorder()
  553. c, _ := CreateTestContext(w)
  554. c.Request, _ = http.NewRequest("GET", "http://example.com", nil)
  555. c.JSONP(http.StatusCreated, H{"foo": "bar"})
  556. assert.Equal(t, http.StatusCreated, w.Code)
  557. assert.Equal(t, "{\"foo\":\"bar\"}", w.Body.String())
  558. assert.Equal(t, "application/json; charset=utf-8", w.Header().Get("Content-Type"))
  559. }
  560. // Tests that no JSON is rendered if code is 204
  561. func TestContextRenderNoContentJSON(t *testing.T) {
  562. w := httptest.NewRecorder()
  563. c, _ := CreateTestContext(w)
  564. c.JSON(http.StatusNoContent, H{"foo": "bar"})
  565. assert.Equal(t, http.StatusNoContent, w.Code)
  566. assert.Empty(t, w.Body.String())
  567. assert.Equal(t, "application/json; charset=utf-8", w.Header().Get("Content-Type"))
  568. }
  569. // Tests that the response is serialized as JSON
  570. // we change the content-type before
  571. func TestContextRenderAPIJSON(t *testing.T) {
  572. w := httptest.NewRecorder()
  573. c, _ := CreateTestContext(w)
  574. c.Header("Content-Type", "application/vnd.api+json")
  575. c.JSON(http.StatusCreated, H{"foo": "bar"})
  576. assert.Equal(t, http.StatusCreated, w.Code)
  577. assert.Equal(t, "{\"foo\":\"bar\"}", w.Body.String())
  578. assert.Equal(t, "application/vnd.api+json", w.Header().Get("Content-Type"))
  579. }
  580. // Tests that no Custom JSON is rendered if code is 204
  581. func TestContextRenderNoContentAPIJSON(t *testing.T) {
  582. w := httptest.NewRecorder()
  583. c, _ := CreateTestContext(w)
  584. c.Header("Content-Type", "application/vnd.api+json")
  585. c.JSON(http.StatusNoContent, H{"foo": "bar"})
  586. assert.Equal(t, http.StatusNoContent, w.Code)
  587. assert.Empty(t, w.Body.String())
  588. assert.Equal(t, w.Header().Get("Content-Type"), "application/vnd.api+json")
  589. }
  590. // Tests that the response is serialized as JSON
  591. // and Content-Type is set to application/json
  592. func TestContextRenderIndentedJSON(t *testing.T) {
  593. w := httptest.NewRecorder()
  594. c, _ := CreateTestContext(w)
  595. c.IndentedJSON(http.StatusCreated, H{"foo": "bar", "bar": "foo", "nested": H{"foo": "bar"}})
  596. assert.Equal(t, http.StatusCreated, w.Code)
  597. assert.Equal(t, "{\n \"bar\": \"foo\",\n \"foo\": \"bar\",\n \"nested\": {\n \"foo\": \"bar\"\n }\n}", w.Body.String())
  598. assert.Equal(t, "application/json; charset=utf-8", w.Header().Get("Content-Type"))
  599. }
  600. // Tests that no Custom JSON is rendered if code is 204
  601. func TestContextRenderNoContentIndentedJSON(t *testing.T) {
  602. w := httptest.NewRecorder()
  603. c, _ := CreateTestContext(w)
  604. c.IndentedJSON(http.StatusNoContent, H{"foo": "bar", "bar": "foo", "nested": H{"foo": "bar"}})
  605. assert.Equal(t, http.StatusNoContent, w.Code)
  606. assert.Empty(t, w.Body.String())
  607. assert.Equal(t, "application/json; charset=utf-8", w.Header().Get("Content-Type"))
  608. }
  609. // Tests that the response is serialized as Secure JSON
  610. // and Content-Type is set to application/json
  611. func TestContextRenderSecureJSON(t *testing.T) {
  612. w := httptest.NewRecorder()
  613. c, router := CreateTestContext(w)
  614. router.SecureJsonPrefix("&&&START&&&")
  615. c.SecureJSON(http.StatusCreated, []string{"foo", "bar"})
  616. assert.Equal(t, http.StatusCreated, w.Code)
  617. assert.Equal(t, "&&&START&&&[\"foo\",\"bar\"]", w.Body.String())
  618. assert.Equal(t, "application/json; charset=utf-8", w.Header().Get("Content-Type"))
  619. }
  620. // Tests that no Custom JSON is rendered if code is 204
  621. func TestContextRenderNoContentSecureJSON(t *testing.T) {
  622. w := httptest.NewRecorder()
  623. c, _ := CreateTestContext(w)
  624. c.SecureJSON(http.StatusNoContent, []string{"foo", "bar"})
  625. assert.Equal(t, http.StatusNoContent, w.Code)
  626. assert.Empty(t, w.Body.String())
  627. assert.Equal(t, "application/json; charset=utf-8", w.Header().Get("Content-Type"))
  628. }
  629. func TestContextRenderNoContentAsciiJSON(t *testing.T) {
  630. w := httptest.NewRecorder()
  631. c, _ := CreateTestContext(w)
  632. c.AsciiJSON(http.StatusNoContent, []string{"lang", "Go语言"})
  633. assert.Equal(t, http.StatusNoContent, w.Code)
  634. assert.Empty(t, w.Body.String())
  635. assert.Equal(t, "application/json", w.Header().Get("Content-Type"))
  636. }
  637. // Tests that the response executes the templates
  638. // and responds with Content-Type set to text/html
  639. func TestContextRenderHTML(t *testing.T) {
  640. w := httptest.NewRecorder()
  641. c, router := CreateTestContext(w)
  642. templ := template.Must(template.New("t").Parse(`Hello {{.name}}`))
  643. router.SetHTMLTemplate(templ)
  644. c.HTML(http.StatusCreated, "t", H{"name": "alexandernyquist"})
  645. assert.Equal(t, http.StatusCreated, w.Code)
  646. assert.Equal(t, "Hello alexandernyquist", w.Body.String())
  647. assert.Equal(t, "text/html; charset=utf-8", w.Header().Get("Content-Type"))
  648. }
  649. func TestContextRenderHTML2(t *testing.T) {
  650. w := httptest.NewRecorder()
  651. c, router := CreateTestContext(w)
  652. // print debug warning log when Engine.trees > 0
  653. router.addRoute("GET", "/", HandlersChain{func(_ *Context) {}})
  654. assert.Len(t, router.trees, 1)
  655. templ := template.Must(template.New("t").Parse(`Hello {{.name}}`))
  656. re := captureOutput(t, func() {
  657. SetMode(DebugMode)
  658. router.SetHTMLTemplate(templ)
  659. SetMode(TestMode)
  660. })
  661. 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)
  662. c.HTML(http.StatusCreated, "t", H{"name": "alexandernyquist"})
  663. assert.Equal(t, http.StatusCreated, w.Code)
  664. assert.Equal(t, "Hello alexandernyquist", w.Body.String())
  665. assert.Equal(t, "text/html; charset=utf-8", w.Header().Get("Content-Type"))
  666. }
  667. // Tests that no HTML is rendered if code is 204
  668. func TestContextRenderNoContentHTML(t *testing.T) {
  669. w := httptest.NewRecorder()
  670. c, router := CreateTestContext(w)
  671. templ := template.Must(template.New("t").Parse(`Hello {{.name}}`))
  672. router.SetHTMLTemplate(templ)
  673. c.HTML(http.StatusNoContent, "t", H{"name": "alexandernyquist"})
  674. assert.Equal(t, http.StatusNoContent, w.Code)
  675. assert.Empty(t, w.Body.String())
  676. assert.Equal(t, "text/html; charset=utf-8", w.Header().Get("Content-Type"))
  677. }
  678. // TestContextXML tests that the response is serialized as XML
  679. // and Content-Type is set to application/xml
  680. func TestContextRenderXML(t *testing.T) {
  681. w := httptest.NewRecorder()
  682. c, _ := CreateTestContext(w)
  683. c.XML(http.StatusCreated, H{"foo": "bar"})
  684. assert.Equal(t, http.StatusCreated, w.Code)
  685. assert.Equal(t, "<map><foo>bar</foo></map>", w.Body.String())
  686. assert.Equal(t, "application/xml; charset=utf-8", w.Header().Get("Content-Type"))
  687. }
  688. // Tests that no XML is rendered if code is 204
  689. func TestContextRenderNoContentXML(t *testing.T) {
  690. w := httptest.NewRecorder()
  691. c, _ := CreateTestContext(w)
  692. c.XML(http.StatusNoContent, H{"foo": "bar"})
  693. assert.Equal(t, http.StatusNoContent, w.Code)
  694. assert.Empty(t, w.Body.String())
  695. assert.Equal(t, "application/xml; charset=utf-8", w.Header().Get("Content-Type"))
  696. }
  697. // TestContextString tests that the response is returned
  698. // with Content-Type set to text/plain
  699. func TestContextRenderString(t *testing.T) {
  700. w := httptest.NewRecorder()
  701. c, _ := CreateTestContext(w)
  702. c.String(http.StatusCreated, "test %s %d", "string", 2)
  703. assert.Equal(t, http.StatusCreated, w.Code)
  704. assert.Equal(t, "test string 2", w.Body.String())
  705. assert.Equal(t, "text/plain; charset=utf-8", w.Header().Get("Content-Type"))
  706. }
  707. // Tests that no String is rendered if code is 204
  708. func TestContextRenderNoContentString(t *testing.T) {
  709. w := httptest.NewRecorder()
  710. c, _ := CreateTestContext(w)
  711. c.String(http.StatusNoContent, "test %s %d", "string", 2)
  712. assert.Equal(t, http.StatusNoContent, w.Code)
  713. assert.Empty(t, w.Body.String())
  714. assert.Equal(t, "text/plain; charset=utf-8", w.Header().Get("Content-Type"))
  715. }
  716. // TestContextString tests that the response is returned
  717. // with Content-Type set to text/html
  718. func TestContextRenderHTMLString(t *testing.T) {
  719. w := httptest.NewRecorder()
  720. c, _ := CreateTestContext(w)
  721. c.Header("Content-Type", "text/html; charset=utf-8")
  722. c.String(http.StatusCreated, "<html>%s %d</html>", "string", 3)
  723. assert.Equal(t, http.StatusCreated, w.Code)
  724. assert.Equal(t, "<html>string 3</html>", w.Body.String())
  725. assert.Equal(t, "text/html; charset=utf-8", w.Header().Get("Content-Type"))
  726. }
  727. // Tests that no HTML String is rendered if code is 204
  728. func TestContextRenderNoContentHTMLString(t *testing.T) {
  729. w := httptest.NewRecorder()
  730. c, _ := CreateTestContext(w)
  731. c.Header("Content-Type", "text/html; charset=utf-8")
  732. c.String(http.StatusNoContent, "<html>%s %d</html>", "string", 3)
  733. assert.Equal(t, http.StatusNoContent, w.Code)
  734. assert.Empty(t, w.Body.String())
  735. assert.Equal(t, "text/html; charset=utf-8", w.Header().Get("Content-Type"))
  736. }
  737. // TestContextData tests that the response can be written from `bytesting`
  738. // with specified MIME type
  739. func TestContextRenderData(t *testing.T) {
  740. w := httptest.NewRecorder()
  741. c, _ := CreateTestContext(w)
  742. c.Data(http.StatusCreated, "text/csv", []byte(`foo,bar`))
  743. assert.Equal(t, http.StatusCreated, w.Code)
  744. assert.Equal(t, "foo,bar", w.Body.String())
  745. assert.Equal(t, "text/csv", w.Header().Get("Content-Type"))
  746. }
  747. // Tests that no Custom Data is rendered if code is 204
  748. func TestContextRenderNoContentData(t *testing.T) {
  749. w := httptest.NewRecorder()
  750. c, _ := CreateTestContext(w)
  751. c.Data(http.StatusNoContent, "text/csv", []byte(`foo,bar`))
  752. assert.Equal(t, http.StatusNoContent, w.Code)
  753. assert.Empty(t, w.Body.String())
  754. assert.Equal(t, "text/csv", w.Header().Get("Content-Type"))
  755. }
  756. func TestContextRenderSSE(t *testing.T) {
  757. w := httptest.NewRecorder()
  758. c, _ := CreateTestContext(w)
  759. c.SSEvent("float", 1.5)
  760. c.Render(-1, sse.Event{
  761. Id: "123",
  762. Data: "text",
  763. })
  764. c.SSEvent("chat", H{
  765. "foo": "bar",
  766. "bar": "foo",
  767. })
  768. 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))
  769. }
  770. func TestContextRenderFile(t *testing.T) {
  771. w := httptest.NewRecorder()
  772. c, _ := CreateTestContext(w)
  773. c.Request, _ = http.NewRequest("GET", "/", nil)
  774. c.File("./gin.go")
  775. assert.Equal(t, http.StatusOK, w.Code)
  776. assert.Contains(t, w.Body.String(), "func New() *Engine {")
  777. assert.Equal(t, "text/plain; charset=utf-8", w.Header().Get("Content-Type"))
  778. }
  779. // TestContextRenderYAML tests that the response is serialized as YAML
  780. // and Content-Type is set to application/x-yaml
  781. func TestContextRenderYAML(t *testing.T) {
  782. w := httptest.NewRecorder()
  783. c, _ := CreateTestContext(w)
  784. c.YAML(http.StatusCreated, H{"foo": "bar"})
  785. assert.Equal(t, http.StatusCreated, w.Code)
  786. assert.Equal(t, "foo: bar\n", w.Body.String())
  787. assert.Equal(t, "application/x-yaml; charset=utf-8", w.Header().Get("Content-Type"))
  788. }
  789. // TestContextRenderProtoBuf tests that the response is serialized as ProtoBuf
  790. // and Content-Type is set to application/x-protobuf
  791. // and we just use the example protobuf to check if the response is correct
  792. func TestContextRenderProtoBuf(t *testing.T) {
  793. w := httptest.NewRecorder()
  794. c, _ := CreateTestContext(w)
  795. reps := []int64{int64(1), int64(2)}
  796. label := "test"
  797. data := &testdata.Test{
  798. Label: &label,
  799. Reps: reps,
  800. }
  801. c.ProtoBuf(http.StatusCreated, data)
  802. protoData, err := proto.Marshal(data)
  803. assert.NoError(t, err)
  804. assert.Equal(t, http.StatusCreated, w.Code)
  805. assert.Equal(t, string(protoData), w.Body.String())
  806. assert.Equal(t, "application/x-protobuf", w.Header().Get("Content-Type"))
  807. }
  808. func TestContextHeaders(t *testing.T) {
  809. c, _ := CreateTestContext(httptest.NewRecorder())
  810. c.Header("Content-Type", "text/plain")
  811. c.Header("X-Custom", "value")
  812. assert.Equal(t, "text/plain", c.Writer.Header().Get("Content-Type"))
  813. assert.Equal(t, "value", c.Writer.Header().Get("X-Custom"))
  814. c.Header("Content-Type", "text/html")
  815. c.Header("X-Custom", "")
  816. assert.Equal(t, "text/html", c.Writer.Header().Get("Content-Type"))
  817. _, exist := c.Writer.Header()["X-Custom"]
  818. assert.False(t, exist)
  819. }
  820. // TODO
  821. func TestContextRenderRedirectWithRelativePath(t *testing.T) {
  822. w := httptest.NewRecorder()
  823. c, _ := CreateTestContext(w)
  824. c.Request, _ = http.NewRequest("POST", "http://example.com", nil)
  825. assert.Panics(t, func() { c.Redirect(299, "/new_path") })
  826. assert.Panics(t, func() { c.Redirect(309, "/new_path") })
  827. c.Redirect(http.StatusMovedPermanently, "/path")
  828. c.Writer.WriteHeaderNow()
  829. assert.Equal(t, http.StatusMovedPermanently, w.Code)
  830. assert.Equal(t, "/path", w.Header().Get("Location"))
  831. }
  832. func TestContextRenderRedirectWithAbsolutePath(t *testing.T) {
  833. w := httptest.NewRecorder()
  834. c, _ := CreateTestContext(w)
  835. c.Request, _ = http.NewRequest("POST", "http://example.com", nil)
  836. c.Redirect(http.StatusFound, "http://google.com")
  837. c.Writer.WriteHeaderNow()
  838. assert.Equal(t, http.StatusFound, w.Code)
  839. assert.Equal(t, "http://google.com", w.Header().Get("Location"))
  840. }
  841. func TestContextRenderRedirectWith201(t *testing.T) {
  842. w := httptest.NewRecorder()
  843. c, _ := CreateTestContext(w)
  844. c.Request, _ = http.NewRequest("POST", "http://example.com", nil)
  845. c.Redirect(http.StatusCreated, "/resource")
  846. c.Writer.WriteHeaderNow()
  847. assert.Equal(t, http.StatusCreated, w.Code)
  848. assert.Equal(t, "/resource", w.Header().Get("Location"))
  849. }
  850. func TestContextRenderRedirectAll(t *testing.T) {
  851. c, _ := CreateTestContext(httptest.NewRecorder())
  852. c.Request, _ = http.NewRequest("POST", "http://example.com", nil)
  853. assert.Panics(t, func() { c.Redirect(http.StatusOK, "/resource") })
  854. assert.Panics(t, func() { c.Redirect(http.StatusAccepted, "/resource") })
  855. assert.Panics(t, func() { c.Redirect(299, "/resource") })
  856. assert.Panics(t, func() { c.Redirect(309, "/resource") })
  857. assert.NotPanics(t, func() { c.Redirect(http.StatusMultipleChoices, "/resource") })
  858. // todo(thinkerou): go1.6 not support StatusPermanentRedirect(308)
  859. // when we upgrade go version we can use http.StatusPermanentRedirect
  860. assert.NotPanics(t, func() { c.Redirect(308, "/resource") })
  861. }
  862. func TestContextNegotiationWithJSON(t *testing.T) {
  863. w := httptest.NewRecorder()
  864. c, _ := CreateTestContext(w)
  865. c.Request, _ = http.NewRequest("POST", "", nil)
  866. c.Negotiate(http.StatusOK, Negotiate{
  867. Offered: []string{MIMEJSON, MIMEXML},
  868. Data: H{"foo": "bar"},
  869. })
  870. assert.Equal(t, http.StatusOK, w.Code)
  871. assert.Equal(t, "{\"foo\":\"bar\"}", w.Body.String())
  872. assert.Equal(t, "application/json; charset=utf-8", w.Header().Get("Content-Type"))
  873. }
  874. func TestContextNegotiationWithXML(t *testing.T) {
  875. w := httptest.NewRecorder()
  876. c, _ := CreateTestContext(w)
  877. c.Request, _ = http.NewRequest("POST", "", nil)
  878. c.Negotiate(http.StatusOK, Negotiate{
  879. Offered: []string{MIMEXML, MIMEJSON},
  880. Data: H{"foo": "bar"},
  881. })
  882. assert.Equal(t, http.StatusOK, w.Code)
  883. assert.Equal(t, "<map><foo>bar</foo></map>", w.Body.String())
  884. assert.Equal(t, "application/xml; charset=utf-8", w.Header().Get("Content-Type"))
  885. }
  886. func TestContextNegotiationWithHTML(t *testing.T) {
  887. w := httptest.NewRecorder()
  888. c, router := CreateTestContext(w)
  889. c.Request, _ = http.NewRequest("POST", "", nil)
  890. templ := template.Must(template.New("t").Parse(`Hello {{.name}}`))
  891. router.SetHTMLTemplate(templ)
  892. c.Negotiate(http.StatusOK, Negotiate{
  893. Offered: []string{MIMEHTML},
  894. Data: H{"name": "gin"},
  895. HTMLName: "t",
  896. })
  897. assert.Equal(t, http.StatusOK, w.Code)
  898. assert.Equal(t, "Hello gin", w.Body.String())
  899. assert.Equal(t, "text/html; charset=utf-8", w.Header().Get("Content-Type"))
  900. }
  901. func TestContextNegotiationNotSupport(t *testing.T) {
  902. w := httptest.NewRecorder()
  903. c, _ := CreateTestContext(w)
  904. c.Request, _ = http.NewRequest("POST", "", nil)
  905. c.Negotiate(http.StatusOK, Negotiate{
  906. Offered: []string{MIMEPOSTForm},
  907. })
  908. assert.Equal(t, http.StatusNotAcceptable, w.Code)
  909. assert.Equal(t, c.index, abortIndex)
  910. assert.True(t, c.IsAborted())
  911. }
  912. func TestContextNegotiationFormat(t *testing.T) {
  913. c, _ := CreateTestContext(httptest.NewRecorder())
  914. c.Request, _ = http.NewRequest("POST", "", nil)
  915. assert.Panics(t, func() { c.NegotiateFormat() })
  916. assert.Equal(t, MIMEJSON, c.NegotiateFormat(MIMEJSON, MIMEXML))
  917. assert.Equal(t, MIMEHTML, c.NegotiateFormat(MIMEHTML, MIMEJSON))
  918. }
  919. func TestContextNegotiationFormatWithAccept(t *testing.T) {
  920. c, _ := CreateTestContext(httptest.NewRecorder())
  921. c.Request, _ = http.NewRequest("POST", "/", nil)
  922. c.Request.Header.Add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8")
  923. assert.Equal(t, MIMEXML, c.NegotiateFormat(MIMEJSON, MIMEXML))
  924. assert.Equal(t, MIMEHTML, c.NegotiateFormat(MIMEXML, MIMEHTML))
  925. assert.Empty(t, c.NegotiateFormat(MIMEJSON))
  926. }
  927. func TestContextNegotiationFormatCustom(t *testing.T) {
  928. c, _ := CreateTestContext(httptest.NewRecorder())
  929. c.Request, _ = http.NewRequest("POST", "/", nil)
  930. c.Request.Header.Add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8")
  931. c.Accepted = nil
  932. c.SetAccepted(MIMEJSON, MIMEXML)
  933. assert.Equal(t, MIMEJSON, c.NegotiateFormat(MIMEJSON, MIMEXML))
  934. assert.Equal(t, MIMEXML, c.NegotiateFormat(MIMEXML, MIMEHTML))
  935. assert.Equal(t, MIMEJSON, c.NegotiateFormat(MIMEJSON))
  936. }
  937. func TestContextIsAborted(t *testing.T) {
  938. c, _ := CreateTestContext(httptest.NewRecorder())
  939. assert.False(t, c.IsAborted())
  940. c.Abort()
  941. assert.True(t, c.IsAborted())
  942. c.Next()
  943. assert.True(t, c.IsAborted())
  944. c.index++
  945. assert.True(t, c.IsAborted())
  946. }
  947. // TestContextData tests that the response can be written from `bytesting`
  948. // with specified MIME type
  949. func TestContextAbortWithStatus(t *testing.T) {
  950. w := httptest.NewRecorder()
  951. c, _ := CreateTestContext(w)
  952. c.index = 4
  953. c.AbortWithStatus(http.StatusUnauthorized)
  954. assert.Equal(t, abortIndex, c.index)
  955. assert.Equal(t, http.StatusUnauthorized, c.Writer.Status())
  956. assert.Equal(t, http.StatusUnauthorized, w.Code)
  957. assert.True(t, c.IsAborted())
  958. }
  959. type testJSONAbortMsg struct {
  960. Foo string `json:"foo"`
  961. Bar string `json:"bar"`
  962. }
  963. func TestContextAbortWithStatusJSON(t *testing.T) {
  964. w := httptest.NewRecorder()
  965. c, _ := CreateTestContext(w)
  966. c.index = 4
  967. in := new(testJSONAbortMsg)
  968. in.Bar = "barValue"
  969. in.Foo = "fooValue"
  970. c.AbortWithStatusJSON(http.StatusUnsupportedMediaType, in)
  971. assert.Equal(t, abortIndex, c.index)
  972. assert.Equal(t, http.StatusUnsupportedMediaType, c.Writer.Status())
  973. assert.Equal(t, http.StatusUnsupportedMediaType, w.Code)
  974. assert.True(t, c.IsAborted())
  975. contentType := w.Header().Get("Content-Type")
  976. assert.Equal(t, "application/json; charset=utf-8", contentType)
  977. buf := new(bytes.Buffer)
  978. _, err := buf.ReadFrom(w.Body)
  979. assert.NoError(t, err)
  980. jsonStringBody := buf.String()
  981. assert.Equal(t, fmt.Sprint(`{"foo":"fooValue","bar":"barValue"}`), jsonStringBody)
  982. }
  983. func TestContextError(t *testing.T) {
  984. c, _ := CreateTestContext(httptest.NewRecorder())
  985. assert.Empty(t, c.Errors)
  986. c.Error(errors.New("first error")) // nolint: errcheck
  987. assert.Len(t, c.Errors, 1)
  988. assert.Equal(t, "Error #01: first error\n", c.Errors.String())
  989. c.Error(&Error{ // nolint: errcheck
  990. Err: errors.New("second error"),
  991. Meta: "some data 2",
  992. Type: ErrorTypePublic,
  993. })
  994. assert.Len(t, c.Errors, 2)
  995. assert.Equal(t, errors.New("first error"), c.Errors[0].Err)
  996. assert.Nil(t, c.Errors[0].Meta)
  997. assert.Equal(t, ErrorTypePrivate, c.Errors[0].Type)
  998. assert.Equal(t, errors.New("second error"), c.Errors[1].Err)
  999. assert.Equal(t, "some data 2", c.Errors[1].Meta)
  1000. assert.Equal(t, ErrorTypePublic, c.Errors[1].Type)
  1001. assert.Equal(t, c.Errors.Last(), c.Errors[1])
  1002. defer func() {
  1003. if recover() == nil {
  1004. t.Error("didn't panic")
  1005. }
  1006. }()
  1007. c.Error(nil) // nolint: errcheck
  1008. }
  1009. func TestContextTypedError(t *testing.T) {
  1010. c, _ := CreateTestContext(httptest.NewRecorder())
  1011. c.Error(errors.New("externo 0")).SetType(ErrorTypePublic) // nolint: errcheck
  1012. c.Error(errors.New("interno 0")).SetType(ErrorTypePrivate) // nolint: errcheck
  1013. for _, err := range c.Errors.ByType(ErrorTypePublic) {
  1014. assert.Equal(t, ErrorTypePublic, err.Type)
  1015. }
  1016. for _, err := range c.Errors.ByType(ErrorTypePrivate) {
  1017. assert.Equal(t, ErrorTypePrivate, err.Type)
  1018. }
  1019. assert.Equal(t, []string{"externo 0", "interno 0"}, c.Errors.Errors())
  1020. }
  1021. func TestContextAbortWithError(t *testing.T) {
  1022. w := httptest.NewRecorder()
  1023. c, _ := CreateTestContext(w)
  1024. c.AbortWithError(http.StatusUnauthorized, errors.New("bad input")).SetMeta("some input") // nolint: errcheck
  1025. assert.Equal(t, http.StatusUnauthorized, w.Code)
  1026. assert.Equal(t, abortIndex, c.index)
  1027. assert.True(t, c.IsAborted())
  1028. }
  1029. func TestContextClientIP(t *testing.T) {
  1030. c, _ := CreateTestContext(httptest.NewRecorder())
  1031. c.Request, _ = http.NewRequest("POST", "/", nil)
  1032. c.Request.Header.Set("X-Real-IP", " 10.10.10.10 ")
  1033. c.Request.Header.Set("X-Forwarded-For", " 20.20.20.20, 30.30.30.30")
  1034. c.Request.Header.Set("X-Appengine-Remote-Addr", "50.50.50.50")
  1035. c.Request.RemoteAddr = " 40.40.40.40:42123 "
  1036. assert.Equal(t, "20.20.20.20", c.ClientIP())
  1037. c.Request.Header.Del("X-Forwarded-For")
  1038. assert.Equal(t, "10.10.10.10", c.ClientIP())
  1039. c.Request.Header.Set("X-Forwarded-For", "30.30.30.30 ")
  1040. assert.Equal(t, "30.30.30.30", c.ClientIP())
  1041. c.Request.Header.Del("X-Forwarded-For")
  1042. c.Request.Header.Del("X-Real-IP")
  1043. c.engine.AppEngine = true
  1044. assert.Equal(t, "50.50.50.50", c.ClientIP())
  1045. c.Request.Header.Del("X-Appengine-Remote-Addr")
  1046. assert.Equal(t, "40.40.40.40", c.ClientIP())
  1047. // no port
  1048. c.Request.RemoteAddr = "50.50.50.50"
  1049. assert.Empty(t, c.ClientIP())
  1050. }
  1051. func TestContextContentType(t *testing.T) {
  1052. c, _ := CreateTestContext(httptest.NewRecorder())
  1053. c.Request, _ = http.NewRequest("POST", "/", nil)
  1054. c.Request.Header.Set("Content-Type", "application/json; charset=utf-8")
  1055. assert.Equal(t, "application/json", c.ContentType())
  1056. }
  1057. func TestContextAutoBindJSON(t *testing.T) {
  1058. c, _ := CreateTestContext(httptest.NewRecorder())
  1059. c.Request, _ = http.NewRequest("POST", "/", bytes.NewBufferString("{\"foo\":\"bar\", \"bar\":\"foo\"}"))
  1060. c.Request.Header.Add("Content-Type", MIMEJSON)
  1061. var obj struct {
  1062. Foo string `json:"foo"`
  1063. Bar string `json:"bar"`
  1064. }
  1065. assert.NoError(t, c.Bind(&obj))
  1066. assert.Equal(t, "foo", obj.Bar)
  1067. assert.Equal(t, "bar", obj.Foo)
  1068. assert.Empty(t, c.Errors)
  1069. }
  1070. func TestContextBindWithJSON(t *testing.T) {
  1071. w := httptest.NewRecorder()
  1072. c, _ := CreateTestContext(w)
  1073. c.Request, _ = http.NewRequest("POST", "/", bytes.NewBufferString("{\"foo\":\"bar\", \"bar\":\"foo\"}"))
  1074. c.Request.Header.Add("Content-Type", MIMEXML) // set fake content-type
  1075. var obj struct {
  1076. Foo string `json:"foo"`
  1077. Bar string `json:"bar"`
  1078. }
  1079. assert.NoError(t, c.BindJSON(&obj))
  1080. assert.Equal(t, "foo", obj.Bar)
  1081. assert.Equal(t, "bar", obj.Foo)
  1082. assert.Equal(t, 0, w.Body.Len())
  1083. }
  1084. func TestContextBindWithXML(t *testing.T) {
  1085. w := httptest.NewRecorder()
  1086. c, _ := CreateTestContext(w)
  1087. c.Request, _ = http.NewRequest("POST", "/", bytes.NewBufferString(`<?xml version="1.0" encoding="UTF-8"?>
  1088. <root>
  1089. <foo>FOO</foo>
  1090. <bar>BAR</bar>
  1091. </root>`))
  1092. c.Request.Header.Add("Content-Type", MIMEXML) // set fake content-type
  1093. var obj struct {
  1094. Foo string `xml:"foo"`
  1095. Bar string `xml:"bar"`
  1096. }
  1097. assert.NoError(t, c.BindXML(&obj))
  1098. assert.Equal(t, "FOO", obj.Foo)
  1099. assert.Equal(t, "BAR", obj.Bar)
  1100. assert.Equal(t, 0, w.Body.Len())
  1101. }
  1102. func TestContextBindWithQuery(t *testing.T) {
  1103. w := httptest.NewRecorder()
  1104. c, _ := CreateTestContext(w)
  1105. c.Request, _ = http.NewRequest("POST", "/?foo=bar&bar=foo", bytes.NewBufferString("foo=unused"))
  1106. var obj struct {
  1107. Foo string `form:"foo"`
  1108. Bar string `form:"bar"`
  1109. }
  1110. assert.NoError(t, c.BindQuery(&obj))
  1111. assert.Equal(t, "foo", obj.Bar)
  1112. assert.Equal(t, "bar", obj.Foo)
  1113. assert.Equal(t, 0, w.Body.Len())
  1114. }
  1115. func TestContextBindWithYAML(t *testing.T) {
  1116. w := httptest.NewRecorder()
  1117. c, _ := CreateTestContext(w)
  1118. c.Request, _ = http.NewRequest("POST", "/", bytes.NewBufferString("foo: bar\nbar: foo"))
  1119. c.Request.Header.Add("Content-Type", MIMEXML) // set fake content-type
  1120. var obj struct {
  1121. Foo string `yaml:"foo"`
  1122. Bar string `yaml:"bar"`
  1123. }
  1124. assert.NoError(t, c.BindYAML(&obj))
  1125. assert.Equal(t, "foo", obj.Bar)
  1126. assert.Equal(t, "bar", obj.Foo)
  1127. assert.Equal(t, 0, w.Body.Len())
  1128. }
  1129. func TestContextBadAutoBind(t *testing.T) {
  1130. w := httptest.NewRecorder()
  1131. c, _ := CreateTestContext(w)
  1132. c.Request, _ = http.NewRequest("POST", "http://example.com", bytes.NewBufferString("\"foo\":\"bar\", \"bar\":\"foo\"}"))
  1133. c.Request.Header.Add("Content-Type", MIMEJSON)
  1134. var obj struct {
  1135. Foo string `json:"foo"`
  1136. Bar string `json:"bar"`
  1137. }
  1138. assert.False(t, c.IsAborted())
  1139. assert.Error(t, c.Bind(&obj))
  1140. c.Writer.WriteHeaderNow()
  1141. assert.Empty(t, obj.Bar)
  1142. assert.Empty(t, obj.Foo)
  1143. assert.Equal(t, http.StatusBadRequest, w.Code)
  1144. assert.True(t, c.IsAborted())
  1145. }
  1146. func TestContextAutoShouldBindJSON(t *testing.T) {
  1147. c, _ := CreateTestContext(httptest.NewRecorder())
  1148. c.Request, _ = http.NewRequest("POST", "/", bytes.NewBufferString("{\"foo\":\"bar\", \"bar\":\"foo\"}"))
  1149. c.Request.Header.Add("Content-Type", MIMEJSON)
  1150. var obj struct {
  1151. Foo string `json:"foo"`
  1152. Bar string `json:"bar"`
  1153. }
  1154. assert.NoError(t, c.ShouldBind(&obj))
  1155. assert.Equal(t, "foo", obj.Bar)
  1156. assert.Equal(t, "bar", obj.Foo)
  1157. assert.Empty(t, c.Errors)
  1158. }
  1159. func TestContextShouldBindWithJSON(t *testing.T) {
  1160. w := httptest.NewRecorder()
  1161. c, _ := CreateTestContext(w)
  1162. c.Request, _ = http.NewRequest("POST", "/", bytes.NewBufferString("{\"foo\":\"bar\", \"bar\":\"foo\"}"))
  1163. c.Request.Header.Add("Content-Type", MIMEXML) // set fake content-type
  1164. var obj struct {
  1165. Foo string `json:"foo"`
  1166. Bar string `json:"bar"`
  1167. }
  1168. assert.NoError(t, c.ShouldBindJSON(&obj))
  1169. assert.Equal(t, "foo", obj.Bar)
  1170. assert.Equal(t, "bar", obj.Foo)
  1171. assert.Equal(t, 0, w.Body.Len())
  1172. }
  1173. func TestContextShouldBindWithXML(t *testing.T) {
  1174. w := httptest.NewRecorder()
  1175. c, _ := CreateTestContext(w)
  1176. c.Request, _ = http.NewRequest("POST", "/", bytes.NewBufferString(`<?xml version="1.0" encoding="UTF-8"?>
  1177. <root>
  1178. <foo>FOO</foo>
  1179. <bar>BAR</bar>
  1180. </root>`))
  1181. c.Request.Header.Add("Content-Type", MIMEXML) // set fake content-type
  1182. var obj struct {
  1183. Foo string `xml:"foo"`
  1184. Bar string `xml:"bar"`
  1185. }
  1186. assert.NoError(t, c.ShouldBindXML(&obj))
  1187. assert.Equal(t, "FOO", obj.Foo)
  1188. assert.Equal(t, "BAR", obj.Bar)
  1189. assert.Equal(t, 0, w.Body.Len())
  1190. }
  1191. func TestContextShouldBindWithQuery(t *testing.T) {
  1192. w := httptest.NewRecorder()
  1193. c, _ := CreateTestContext(w)
  1194. c.Request, _ = http.NewRequest("POST", "/?foo=bar&bar=foo&Foo=bar1&Bar=foo1", bytes.NewBufferString("foo=unused"))
  1195. var obj struct {
  1196. Foo string `form:"foo"`
  1197. Bar string `form:"bar"`
  1198. Foo1 string `form:"Foo"`
  1199. Bar1 string `form:"Bar"`
  1200. }
  1201. assert.NoError(t, c.ShouldBindQuery(&obj))
  1202. assert.Equal(t, "foo", obj.Bar)
  1203. assert.Equal(t, "bar", obj.Foo)
  1204. assert.Equal(t, "foo1", obj.Bar1)
  1205. assert.Equal(t, "bar1", obj.Foo1)
  1206. assert.Equal(t, 0, w.Body.Len())
  1207. }
  1208. func TestContextShouldBindWithYAML(t *testing.T) {
  1209. w := httptest.NewRecorder()
  1210. c, _ := CreateTestContext(w)
  1211. c.Request, _ = http.NewRequest("POST", "/", bytes.NewBufferString("foo: bar\nbar: foo"))
  1212. c.Request.Header.Add("Content-Type", MIMEXML) // set fake content-type
  1213. var obj struct {
  1214. Foo string `yaml:"foo"`
  1215. Bar string `yaml:"bar"`
  1216. }
  1217. assert.NoError(t, c.ShouldBindYAML(&obj))
  1218. assert.Equal(t, "foo", obj.Bar)
  1219. assert.Equal(t, "bar", obj.Foo)
  1220. assert.Equal(t, 0, w.Body.Len())
  1221. }
  1222. func TestContextBadAutoShouldBind(t *testing.T) {
  1223. w := httptest.NewRecorder()
  1224. c, _ := CreateTestContext(w)
  1225. c.Request, _ = http.NewRequest("POST", "http://example.com", bytes.NewBufferString("\"foo\":\"bar\", \"bar\":\"foo\"}"))
  1226. c.Request.Header.Add("Content-Type", MIMEJSON)
  1227. var obj struct {
  1228. Foo string `json:"foo"`
  1229. Bar string `json:"bar"`
  1230. }
  1231. assert.False(t, c.IsAborted())
  1232. assert.Error(t, c.ShouldBind(&obj))
  1233. assert.Empty(t, obj.Bar)
  1234. assert.Empty(t, obj.Foo)
  1235. assert.False(t, c.IsAborted())
  1236. }
  1237. func TestContextShouldBindBodyWith(t *testing.T) {
  1238. type typeA struct {
  1239. Foo string `json:"foo" xml:"foo" binding:"required"`
  1240. }
  1241. type typeB struct {
  1242. Bar string `json:"bar" xml:"bar" binding:"required"`
  1243. }
  1244. for _, tt := range []struct {
  1245. name string
  1246. bindingA, bindingB binding.BindingBody
  1247. bodyA, bodyB string
  1248. }{
  1249. {
  1250. name: "JSON & JSON",
  1251. bindingA: binding.JSON,
  1252. bindingB: binding.JSON,
  1253. bodyA: `{"foo":"FOO"}`,
  1254. bodyB: `{"bar":"BAR"}`,
  1255. },
  1256. {
  1257. name: "JSON & XML",
  1258. bindingA: binding.JSON,
  1259. bindingB: binding.XML,
  1260. bodyA: `{"foo":"FOO"}`,
  1261. bodyB: `<?xml version="1.0" encoding="UTF-8"?>
  1262. <root>
  1263. <bar>BAR</bar>
  1264. </root>`,
  1265. },
  1266. {
  1267. name: "XML & XML",
  1268. bindingA: binding.XML,
  1269. bindingB: binding.XML,
  1270. bodyA: `<?xml version="1.0" encoding="UTF-8"?>
  1271. <root>
  1272. <foo>FOO</foo>
  1273. </root>`,
  1274. bodyB: `<?xml version="1.0" encoding="UTF-8"?>
  1275. <root>
  1276. <bar>BAR</bar>
  1277. </root>`,
  1278. },
  1279. } {
  1280. t.Logf("testing: %s", tt.name)
  1281. // bodyA to typeA and typeB
  1282. {
  1283. w := httptest.NewRecorder()
  1284. c, _ := CreateTestContext(w)
  1285. c.Request, _ = http.NewRequest(
  1286. "POST", "http://example.com", bytes.NewBufferString(tt.bodyA),
  1287. )
  1288. // When it binds to typeA and typeB, it finds the body is
  1289. // not typeB but typeA.
  1290. objA := typeA{}
  1291. assert.NoError(t, c.ShouldBindBodyWith(&objA, tt.bindingA))
  1292. assert.Equal(t, typeA{"FOO"}, objA)
  1293. objB := typeB{}
  1294. assert.Error(t, c.ShouldBindBodyWith(&objB, tt.bindingB))
  1295. assert.NotEqual(t, typeB{"BAR"}, objB)
  1296. }
  1297. // bodyB to typeA and typeB
  1298. {
  1299. // When it binds to typeA and typeB, it finds the body is
  1300. // not typeA but typeB.
  1301. w := httptest.NewRecorder()
  1302. c, _ := CreateTestContext(w)
  1303. c.Request, _ = http.NewRequest(
  1304. "POST", "http://example.com", bytes.NewBufferString(tt.bodyB),
  1305. )
  1306. objA := typeA{}
  1307. assert.Error(t, c.ShouldBindBodyWith(&objA, tt.bindingA))
  1308. assert.NotEqual(t, typeA{"FOO"}, objA)
  1309. objB := typeB{}
  1310. assert.NoError(t, c.ShouldBindBodyWith(&objB, tt.bindingB))
  1311. assert.Equal(t, typeB{"BAR"}, objB)
  1312. }
  1313. }
  1314. }
  1315. func TestContextGolangContext(t *testing.T) {
  1316. c, _ := CreateTestContext(httptest.NewRecorder())
  1317. c.Request, _ = http.NewRequest("POST", "/", bytes.NewBufferString("{\"foo\":\"bar\", \"bar\":\"foo\"}"))
  1318. assert.NoError(t, c.Err())
  1319. assert.Nil(t, c.Done())
  1320. ti, ok := c.Deadline()
  1321. assert.Equal(t, ti, time.Time{})
  1322. assert.False(t, ok)
  1323. assert.Equal(t, c.Value(0), c.Request)
  1324. assert.Nil(t, c.Value("foo"))
  1325. c.Set("foo", "bar")
  1326. assert.Equal(t, "bar", c.Value("foo"))
  1327. assert.Nil(t, c.Value(1))
  1328. }
  1329. func TestWebsocketsRequired(t *testing.T) {
  1330. // Example request from spec: https://tools.ietf.org/html/rfc6455#section-1.2
  1331. c, _ := CreateTestContext(httptest.NewRecorder())
  1332. c.Request, _ = http.NewRequest("GET", "/chat", nil)
  1333. c.Request.Header.Set("Host", "server.example.com")
  1334. c.Request.Header.Set("Upgrade", "websocket")
  1335. c.Request.Header.Set("Connection", "Upgrade")
  1336. c.Request.Header.Set("Sec-WebSocket-Key", "dGhlIHNhbXBsZSBub25jZQ==")
  1337. c.Request.Header.Set("Origin", "http://example.com")
  1338. c.Request.Header.Set("Sec-WebSocket-Protocol", "chat, superchat")
  1339. c.Request.Header.Set("Sec-WebSocket-Version", "13")
  1340. assert.True(t, c.IsWebsocket())
  1341. // Normal request, no websocket required.
  1342. c, _ = CreateTestContext(httptest.NewRecorder())
  1343. c.Request, _ = http.NewRequest("GET", "/chat", nil)
  1344. c.Request.Header.Set("Host", "server.example.com")
  1345. assert.False(t, c.IsWebsocket())
  1346. }
  1347. func TestGetRequestHeaderValue(t *testing.T) {
  1348. c, _ := CreateTestContext(httptest.NewRecorder())
  1349. c.Request, _ = http.NewRequest("GET", "/chat", nil)
  1350. c.Request.Header.Set("Gin-Version", "1.0.0")
  1351. assert.Equal(t, "1.0.0", c.GetHeader("Gin-Version"))
  1352. assert.Empty(t, c.GetHeader("Connection"))
  1353. }
  1354. func TestContextGetRawData(t *testing.T) {
  1355. c, _ := CreateTestContext(httptest.NewRecorder())
  1356. body := bytes.NewBufferString("Fetch binary post data")
  1357. c.Request, _ = http.NewRequest("POST", "/", body)
  1358. c.Request.Header.Add("Content-Type", MIMEPOSTForm)
  1359. data, err := c.GetRawData()
  1360. assert.Nil(t, err)
  1361. assert.Equal(t, "Fetch binary post data", string(data))
  1362. }
  1363. func TestContextRenderDataFromReader(t *testing.T) {
  1364. w := httptest.NewRecorder()
  1365. c, _ := CreateTestContext(w)
  1366. body := "#!PNG some raw data"
  1367. reader := strings.NewReader(body)
  1368. contentLength := int64(len(body))
  1369. contentType := "image/png"
  1370. extraHeaders := map[string]string{"Content-Disposition": `attachment; filename="gopher.png"`}
  1371. c.DataFromReader(http.StatusOK, contentLength, contentType, reader, extraHeaders)
  1372. assert.Equal(t, http.StatusOK, w.Code)
  1373. assert.Equal(t, body, w.Body.String())
  1374. assert.Equal(t, contentType, w.Header().Get("Content-Type"))
  1375. assert.Equal(t, fmt.Sprintf("%d", contentLength), w.Header().Get("Content-Length"))
  1376. assert.Equal(t, extraHeaders["Content-Disposition"], w.Header().Get("Content-Disposition"))
  1377. }
  1378. type TestResponseRecorder struct {
  1379. *httptest.ResponseRecorder
  1380. closeChannel chan bool
  1381. }
  1382. func (r *TestResponseRecorder) CloseNotify() <-chan bool {
  1383. return r.closeChannel
  1384. }
  1385. func (r *TestResponseRecorder) closeClient() {
  1386. r.closeChannel <- true
  1387. }
  1388. func CreateTestResponseRecorder() *TestResponseRecorder {
  1389. return &TestResponseRecorder{
  1390. httptest.NewRecorder(),
  1391. make(chan bool, 1),
  1392. }
  1393. }
  1394. func TestContextStream(t *testing.T) {
  1395. w := CreateTestResponseRecorder()
  1396. c, _ := CreateTestContext(w)
  1397. stopStream := true
  1398. c.Stream(func(w io.Writer) bool {
  1399. defer func() {
  1400. stopStream = false
  1401. }()
  1402. _, err := w.Write([]byte("test"))
  1403. assert.NoError(t, err)
  1404. return stopStream
  1405. })
  1406. assert.Equal(t, "testtest", w.Body.String())
  1407. }
  1408. func TestContextStreamWithClientGone(t *testing.T) {
  1409. w := CreateTestResponseRecorder()
  1410. c, _ := CreateTestContext(w)
  1411. c.Stream(func(writer io.Writer) bool {
  1412. defer func() {
  1413. w.closeClient()
  1414. }()
  1415. _, err := writer.Write([]byte("test"))
  1416. assert.NoError(t, err)
  1417. return true
  1418. })
  1419. assert.Equal(t, "test", w.Body.String())
  1420. }