requests_test.go 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032
  1. package httpx
  2. import (
  3. "bytes"
  4. "fmt"
  5. "io"
  6. "net/http"
  7. "net/http/httptest"
  8. "strconv"
  9. "strings"
  10. "testing"
  11. "zero/core/httprouter"
  12. "github.com/stretchr/testify/assert"
  13. )
  14. const (
  15. applicationJsonWithUtf8 = "application/json; charset=utf-8"
  16. contentLength = "Content-Length"
  17. )
  18. func TestGetRemoteAddr(t *testing.T) {
  19. host := "8.8.8.8"
  20. r, err := http.NewRequest(http.MethodGet, "/", strings.NewReader(""))
  21. assert.Nil(t, err)
  22. r.Header.Set(xForwardFor, host)
  23. assert.Equal(t, host, GetRemoteAddr(r))
  24. }
  25. func TestParseForm(t *testing.T) {
  26. var v struct {
  27. Name string `form:"name"`
  28. Age int `form:"age"`
  29. Percent float64 `form:"percent,optional"`
  30. }
  31. r, err := http.NewRequest(http.MethodGet, "http://hello.com/a?name=hello&age=18&percent=3.4", nil)
  32. assert.Nil(t, err)
  33. err = Parse(r, &v)
  34. assert.Nil(t, err)
  35. assert.Equal(t, "hello", v.Name)
  36. assert.Equal(t, 18, v.Age)
  37. assert.Equal(t, 3.4, v.Percent)
  38. }
  39. func TestParseFormOutOfRange(t *testing.T) {
  40. var v struct {
  41. Age int `form:"age,range=[10:20)"`
  42. }
  43. tests := []struct {
  44. url string
  45. pass bool
  46. }{
  47. {
  48. url: "http://hello.com/a?age=5",
  49. pass: false,
  50. },
  51. {
  52. url: "http://hello.com/a?age=10",
  53. pass: true,
  54. },
  55. {
  56. url: "http://hello.com/a?age=15",
  57. pass: true,
  58. },
  59. {
  60. url: "http://hello.com/a?age=20",
  61. pass: false,
  62. },
  63. {
  64. url: "http://hello.com/a?age=28",
  65. pass: false,
  66. },
  67. }
  68. for _, test := range tests {
  69. r, err := http.NewRequest(http.MethodGet, test.url, nil)
  70. assert.Nil(t, err)
  71. err = Parse(r, &v)
  72. if test.pass {
  73. assert.Nil(t, err)
  74. } else {
  75. assert.NotNil(t, err)
  76. }
  77. }
  78. }
  79. func TestParseMultipartForm(t *testing.T) {
  80. var v struct {
  81. Name string `form:"name"`
  82. Age int `form:"age"`
  83. }
  84. body := strings.Replace(`----------------------------220477612388154780019383
  85. Content-Disposition: form-data; name="name"
  86. kevin
  87. ----------------------------220477612388154780019383
  88. Content-Disposition: form-data; name="age"
  89. 18
  90. ----------------------------220477612388154780019383--`, "\n", "\r\n", -1)
  91. r := httptest.NewRequest(http.MethodPost, "http://localhost:3333/", strings.NewReader(body))
  92. r.Header.Set(ContentType, "multipart/form-data; boundary=--------------------------220477612388154780019383")
  93. err := Parse(r, &v)
  94. assert.Nil(t, err)
  95. assert.Equal(t, "kevin", v.Name)
  96. assert.Equal(t, 18, v.Age)
  97. }
  98. func TestParseRequired(t *testing.T) {
  99. v := struct {
  100. Name string `form:"name"`
  101. Percent float64 `form:"percent"`
  102. }{}
  103. r, err := http.NewRequest(http.MethodGet, "http://hello.com/a?name=hello", nil)
  104. assert.Nil(t, err)
  105. err = Parse(r, &v)
  106. assert.NotNil(t, err)
  107. }
  108. func TestParseSlice(t *testing.T) {
  109. body := `names=%5B%22first%22%2C%22second%22%5D`
  110. reader := strings.NewReader(body)
  111. r, err := http.NewRequest(http.MethodPost, "http://hello.com/", reader)
  112. assert.Nil(t, err)
  113. r.Header.Set("Content-Type", "application/x-www-form-urlencoded")
  114. router := httprouter.NewPatRouter()
  115. err = router.Handle(http.MethodPost, "/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  116. v := struct {
  117. Names []string `form:"names"`
  118. }{}
  119. err = Parse(r, &v)
  120. assert.Nil(t, err)
  121. assert.Equal(t, 2, len(v.Names))
  122. assert.Equal(t, "first", v.Names[0])
  123. assert.Equal(t, "second", v.Names[1])
  124. }))
  125. assert.Nil(t, err)
  126. rr := httptest.NewRecorder()
  127. router.ServeHTTP(rr, r)
  128. }
  129. func TestParseJsonPost(t *testing.T) {
  130. r, err := http.NewRequest(http.MethodPost, "http://hello.com/kevin/2017?nickname=whatever&zipcode=200000",
  131. bytes.NewBufferString(`{"location": "shanghai", "time": 20170912}`))
  132. assert.Nil(t, err)
  133. r.Header.Set(ContentType, ApplicationJson)
  134. router := httprouter.NewPatRouter()
  135. err = router.Handle(http.MethodPost, "/:name/:year", http.HandlerFunc(func(
  136. w http.ResponseWriter, r *http.Request) {
  137. v := struct {
  138. Name string `path:"name"`
  139. Year int `path:"year"`
  140. Nickname string `form:"nickname"`
  141. Zipcode int64 `form:"zipcode"`
  142. Location string `json:"location"`
  143. Time int64 `json:"time"`
  144. }{}
  145. err = Parse(r, &v)
  146. assert.Nil(t, err)
  147. _, err = io.WriteString(w, fmt.Sprintf("%s:%d:%s:%d:%s:%d", v.Name, v.Year,
  148. v.Nickname, v.Zipcode, v.Location, v.Time))
  149. assert.Nil(t, err)
  150. }))
  151. assert.Nil(t, err)
  152. rr := httptest.NewRecorder()
  153. router.ServeHTTP(rr, r)
  154. assert.Equal(t, "kevin:2017:whatever:200000:shanghai:20170912", rr.Body.String())
  155. }
  156. func TestParseJsonPostWithIntSlice(t *testing.T) {
  157. r, err := http.NewRequest(http.MethodPost, "http://hello.com/kevin/2017",
  158. bytes.NewBufferString(`{"ages": [1, 2], "years": [3, 4]}`))
  159. assert.Nil(t, err)
  160. r.Header.Set(ContentType, ApplicationJson)
  161. router := httprouter.NewPatRouter()
  162. err = router.Handle(http.MethodPost, "/:name/:year", http.HandlerFunc(func(
  163. w http.ResponseWriter, r *http.Request) {
  164. v := struct {
  165. Name string `path:"name"`
  166. Year int `path:"year"`
  167. Ages []int `json:"ages"`
  168. Years []int64 `json:"years"`
  169. }{}
  170. err = Parse(r, &v)
  171. assert.Nil(t, err)
  172. assert.ElementsMatch(t, []int{1, 2}, v.Ages)
  173. assert.ElementsMatch(t, []int64{3, 4}, v.Years)
  174. }))
  175. assert.Nil(t, err)
  176. rr := httptest.NewRecorder()
  177. router.ServeHTTP(rr, r)
  178. }
  179. func TestParseJsonPostError(t *testing.T) {
  180. payload := `[{"abcd": "cdef"}]`
  181. r, err := http.NewRequest(http.MethodPost, "http://hello.com/kevin/2017?nickname=whatever&zipcode=200000",
  182. bytes.NewBufferString(payload))
  183. assert.Nil(t, err)
  184. r.Header.Set(ContentType, ApplicationJson)
  185. router := httprouter.NewPatRouter()
  186. err = router.Handle(http.MethodPost, "/:name/:year", http.HandlerFunc(
  187. func(w http.ResponseWriter, r *http.Request) {
  188. v := struct {
  189. Name string `path:"name"`
  190. Year int `path:"year"`
  191. Nickname string `form:"nickname"`
  192. Zipcode int64 `form:"zipcode"`
  193. Location string `json:"location"`
  194. Time int64 `json:"time"`
  195. }{}
  196. err = Parse(r, &v)
  197. assert.NotNil(t, err)
  198. }))
  199. assert.Nil(t, err)
  200. rr := httptest.NewRecorder()
  201. router.ServeHTTP(rr, r)
  202. }
  203. func TestParseJsonPostInvalidRequest(t *testing.T) {
  204. payload := `{"ages": ["cdef"]}`
  205. r, err := http.NewRequest(http.MethodPost, "http://hello.com/",
  206. bytes.NewBufferString(payload))
  207. assert.Nil(t, err)
  208. r.Header.Set(ContentType, ApplicationJson)
  209. router := httprouter.NewPatRouter()
  210. err = router.Handle(http.MethodPost, "/", http.HandlerFunc(
  211. func(w http.ResponseWriter, r *http.Request) {
  212. v := struct {
  213. Ages []int `json:"ages"`
  214. }{}
  215. err = Parse(r, &v)
  216. assert.NotNil(t, err)
  217. }))
  218. assert.Nil(t, err)
  219. rr := httptest.NewRecorder()
  220. router.ServeHTTP(rr, r)
  221. }
  222. func TestParseJsonPostRequired(t *testing.T) {
  223. r, err := http.NewRequest(http.MethodPost, "http://hello.com/kevin/2017",
  224. bytes.NewBufferString(`{"location": "shanghai"`))
  225. assert.Nil(t, err)
  226. r.Header.Set(ContentType, ApplicationJson)
  227. router := httprouter.NewPatRouter()
  228. err = router.Handle(http.MethodPost, "/:name/:year", http.HandlerFunc(
  229. func(w http.ResponseWriter, r *http.Request) {
  230. v := struct {
  231. Name string `path:"name"`
  232. Year int `path:"year"`
  233. Location string `json:"location"`
  234. Time int64 `json:"time"`
  235. }{}
  236. err = Parse(r, &v)
  237. assert.NotNil(t, err)
  238. }))
  239. assert.Nil(t, err)
  240. rr := httptest.NewRecorder()
  241. router.ServeHTTP(rr, r)
  242. }
  243. func TestParsePath(t *testing.T) {
  244. r, err := http.NewRequest(http.MethodGet, "http://hello.com/kevin/2017", nil)
  245. assert.Nil(t, err)
  246. router := httprouter.NewPatRouter()
  247. err = router.Handle(http.MethodGet, "/:name/:year", http.HandlerFunc(
  248. func(w http.ResponseWriter, r *http.Request) {
  249. v := struct {
  250. Name string `path:"name"`
  251. Year int `path:"year"`
  252. }{}
  253. err = Parse(r, &v)
  254. assert.Nil(t, err)
  255. _, err = io.WriteString(w, fmt.Sprintf("%s in %d", v.Name, v.Year))
  256. assert.Nil(t, err)
  257. }))
  258. assert.Nil(t, err)
  259. rr := httptest.NewRecorder()
  260. router.ServeHTTP(rr, r)
  261. assert.Equal(t, "kevin in 2017", rr.Body.String())
  262. }
  263. func TestParsePathRequired(t *testing.T) {
  264. r, err := http.NewRequest(http.MethodGet, "http://hello.com/kevin", nil)
  265. assert.Nil(t, err)
  266. router := httprouter.NewPatRouter()
  267. err = router.Handle(http.MethodGet, "/:name/", http.HandlerFunc(
  268. func(w http.ResponseWriter, r *http.Request) {
  269. v := struct {
  270. Name string `path:"name"`
  271. Year int `path:"year"`
  272. }{}
  273. err = Parse(r, &v)
  274. assert.NotNil(t, err)
  275. }))
  276. assert.Nil(t, err)
  277. rr := httptest.NewRecorder()
  278. router.ServeHTTP(rr, r)
  279. }
  280. func TestParseQuery(t *testing.T) {
  281. r, err := http.NewRequest(http.MethodGet, "http://hello.com/kevin/2017?nickname=whatever&zipcode=200000", nil)
  282. assert.Nil(t, err)
  283. router := httprouter.NewPatRouter()
  284. err = router.Handle(http.MethodGet, "/:name/:year", http.HandlerFunc(
  285. func(w http.ResponseWriter, r *http.Request) {
  286. v := struct {
  287. Nickname string `form:"nickname"`
  288. Zipcode int64 `form:"zipcode"`
  289. }{}
  290. err = Parse(r, &v)
  291. assert.Nil(t, err)
  292. _, err = io.WriteString(w, fmt.Sprintf("%s:%d", v.Nickname, v.Zipcode))
  293. assert.Nil(t, err)
  294. }))
  295. assert.Nil(t, err)
  296. rr := httptest.NewRecorder()
  297. router.ServeHTTP(rr, r)
  298. assert.Equal(t, "whatever:200000", rr.Body.String())
  299. }
  300. func TestParseQueryRequired(t *testing.T) {
  301. r, err := http.NewRequest(http.MethodPost, "http://hello.com/kevin/2017?nickname=whatever", nil)
  302. assert.Nil(t, err)
  303. router := httprouter.NewPatRouter()
  304. err = router.Handle(http.MethodPost, "/:name/:year", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  305. v := struct {
  306. Nickname string `form:"nickname"`
  307. Zipcode int64 `form:"zipcode"`
  308. }{}
  309. err = Parse(r, &v)
  310. assert.NotNil(t, err)
  311. }))
  312. assert.Nil(t, err)
  313. rr := httptest.NewRecorder()
  314. router.ServeHTTP(rr, r)
  315. }
  316. func TestParseOptional(t *testing.T) {
  317. r, err := http.NewRequest(http.MethodGet, "http://hello.com/kevin/2017?nickname=whatever&zipcode=", nil)
  318. assert.Nil(t, err)
  319. router := httprouter.NewPatRouter()
  320. err = router.Handle(http.MethodGet, "/:name/:year", http.HandlerFunc(
  321. func(w http.ResponseWriter, r *http.Request) {
  322. v := struct {
  323. Nickname string `form:"nickname"`
  324. Zipcode int64 `form:"zipcode,optional"`
  325. }{}
  326. err = Parse(r, &v)
  327. assert.Nil(t, err)
  328. _, err = io.WriteString(w, fmt.Sprintf("%s:%d", v.Nickname, v.Zipcode))
  329. assert.Nil(t, err)
  330. }))
  331. assert.Nil(t, err)
  332. rr := httptest.NewRecorder()
  333. router.ServeHTTP(rr, r)
  334. assert.Equal(t, "whatever:0", rr.Body.String())
  335. }
  336. func TestParseNestedInRequestEmpty(t *testing.T) {
  337. r, err := http.NewRequest(http.MethodPost, "http://hello.com/kevin/2017", bytes.NewBufferString("{}"))
  338. assert.Nil(t, err)
  339. type (
  340. Request struct {
  341. Name string `path:"name"`
  342. Year int `path:"year"`
  343. }
  344. Audio struct {
  345. Volume int `json:"volume"`
  346. }
  347. WrappedRequest struct {
  348. Request
  349. Audio Audio `json:"audio,optional"`
  350. }
  351. )
  352. router := httprouter.NewPatRouter()
  353. err = router.Handle(http.MethodPost, "/:name/:year", http.HandlerFunc(
  354. func(w http.ResponseWriter, r *http.Request) {
  355. var v WrappedRequest
  356. err = Parse(r, &v)
  357. assert.Nil(t, err)
  358. _, err = io.WriteString(w, fmt.Sprintf("%s:%d", v.Name, v.Year))
  359. assert.Nil(t, err)
  360. }))
  361. assert.Nil(t, err)
  362. rr := httptest.NewRecorder()
  363. router.ServeHTTP(rr, r)
  364. assert.Equal(t, "kevin:2017", rr.Body.String())
  365. }
  366. func TestParsePtrInRequest(t *testing.T) {
  367. r, err := http.NewRequest(http.MethodPost, "http://hello.com/kevin/2017",
  368. bytes.NewBufferString(`{"audio": {"volume": 100}}`))
  369. assert.Nil(t, err)
  370. r.Header.Set(ContentType, ApplicationJson)
  371. type (
  372. Request struct {
  373. Name string `path:"name"`
  374. Year int `path:"year"`
  375. }
  376. Audio struct {
  377. Volume int `json:"volume"`
  378. }
  379. WrappedRequest struct {
  380. Request
  381. Audio *Audio `json:"audio,optional"`
  382. }
  383. )
  384. router := httprouter.NewPatRouter()
  385. err = router.Handle(http.MethodPost, "/:name/:year", http.HandlerFunc(
  386. func(w http.ResponseWriter, r *http.Request) {
  387. var v WrappedRequest
  388. err = Parse(r, &v)
  389. assert.Nil(t, err)
  390. _, err = io.WriteString(w, fmt.Sprintf("%s:%d:%d", v.Name, v.Year, v.Audio.Volume))
  391. assert.Nil(t, err)
  392. }))
  393. assert.Nil(t, err)
  394. rr := httptest.NewRecorder()
  395. router.ServeHTTP(rr, r)
  396. assert.Equal(t, "kevin:2017:100", rr.Body.String())
  397. }
  398. func TestParsePtrInRequestEmpty(t *testing.T) {
  399. r, err := http.NewRequest(http.MethodPost, "http://hello.com/kevin", bytes.NewBufferString("{}"))
  400. assert.Nil(t, err)
  401. type (
  402. Audio struct {
  403. Volume int `json:"volume"`
  404. }
  405. WrappedRequest struct {
  406. Audio *Audio `json:"audio,optional"`
  407. }
  408. )
  409. router := httprouter.NewPatRouter()
  410. err = router.Handle(http.MethodPost, "/kevin", http.HandlerFunc(
  411. func(w http.ResponseWriter, r *http.Request) {
  412. var v WrappedRequest
  413. err = Parse(r, &v)
  414. assert.Nil(t, err)
  415. }))
  416. assert.Nil(t, err)
  417. rr := httptest.NewRecorder()
  418. router.ServeHTTP(rr, r)
  419. }
  420. func TestParseQueryOptional(t *testing.T) {
  421. r, err := http.NewRequest(http.MethodGet, "http://hello.com/kevin/2017?nickname=whatever&zipcode=", nil)
  422. assert.Nil(t, err)
  423. router := httprouter.NewPatRouter()
  424. err = router.Handle(http.MethodGet, "/:name/:year", http.HandlerFunc(
  425. func(w http.ResponseWriter, r *http.Request) {
  426. v := struct {
  427. Nickname string `form:"nickname"`
  428. Zipcode int64 `form:"zipcode,optional"`
  429. }{}
  430. err = Parse(r, &v)
  431. assert.Nil(t, err)
  432. _, err = io.WriteString(w, fmt.Sprintf("%s:%d", v.Nickname, v.Zipcode))
  433. assert.Nil(t, err)
  434. }))
  435. assert.Nil(t, err)
  436. rr := httptest.NewRecorder()
  437. router.ServeHTTP(rr, r)
  438. assert.Equal(t, "whatever:0", rr.Body.String())
  439. }
  440. func TestParse(t *testing.T) {
  441. r, err := http.NewRequest(http.MethodGet, "http://hello.com/kevin/2017?nickname=whatever&zipcode=200000", nil)
  442. assert.Nil(t, err)
  443. router := httprouter.NewPatRouter()
  444. err = router.Handle(http.MethodGet, "/:name/:year", http.HandlerFunc(
  445. func(w http.ResponseWriter, r *http.Request) {
  446. v := struct {
  447. Name string `path:"name"`
  448. Year int `path:"year"`
  449. Nickname string `form:"nickname"`
  450. Zipcode int64 `form:"zipcode"`
  451. }{}
  452. err = Parse(r, &v)
  453. assert.Nil(t, err)
  454. _, err = io.WriteString(w, fmt.Sprintf("%s:%d:%s:%d", v.Name, v.Year, v.Nickname, v.Zipcode))
  455. assert.Nil(t, err)
  456. }))
  457. assert.Nil(t, err)
  458. rr := httptest.NewRecorder()
  459. router.ServeHTTP(rr, r)
  460. assert.Equal(t, "kevin:2017:whatever:200000", rr.Body.String())
  461. }
  462. func TestParseWrappedRequest(t *testing.T) {
  463. r, err := http.NewRequest(http.MethodGet, "http://hello.com/kevin/2017", nil)
  464. assert.Nil(t, err)
  465. type (
  466. Request struct {
  467. Name string `path:"name"`
  468. Year int `path:"year"`
  469. }
  470. WrappedRequest struct {
  471. Request
  472. }
  473. )
  474. router := httprouter.NewPatRouter()
  475. err = router.Handle(http.MethodGet, "/:name/:year", http.HandlerFunc(
  476. func(w http.ResponseWriter, r *http.Request) {
  477. var v WrappedRequest
  478. err = Parse(r, &v)
  479. assert.Nil(t, err)
  480. _, err = io.WriteString(w, fmt.Sprintf("%s:%d", v.Name, v.Year))
  481. }))
  482. assert.Nil(t, err)
  483. rr := httptest.NewRecorder()
  484. router.ServeHTTP(rr, r)
  485. assert.Equal(t, "kevin:2017", rr.Body.String())
  486. }
  487. func TestParseWrappedGetRequestWithJsonHeader(t *testing.T) {
  488. r, err := http.NewRequest(http.MethodGet, "http://hello.com/kevin/2017", nil)
  489. assert.Nil(t, err)
  490. r.Header.Set(ContentType, applicationJsonWithUtf8)
  491. type (
  492. Request struct {
  493. Name string `path:"name"`
  494. Year int `path:"year"`
  495. }
  496. WrappedRequest struct {
  497. Request
  498. }
  499. )
  500. router := httprouter.NewPatRouter()
  501. err = router.Handle(http.MethodGet, "/:name/:year", http.HandlerFunc(
  502. func(w http.ResponseWriter, r *http.Request) {
  503. var v WrappedRequest
  504. err = Parse(r, &v)
  505. assert.Nil(t, err)
  506. _, err = io.WriteString(w, fmt.Sprintf("%s:%d", v.Name, v.Year))
  507. assert.Nil(t, err)
  508. }))
  509. assert.Nil(t, err)
  510. rr := httptest.NewRecorder()
  511. router.ServeHTTP(rr, r)
  512. assert.Equal(t, "kevin:2017", rr.Body.String())
  513. }
  514. func TestParseWrappedHeadRequestWithJsonHeader(t *testing.T) {
  515. r, err := http.NewRequest(http.MethodHead, "http://hello.com/kevin/2017", nil)
  516. assert.Nil(t, err)
  517. r.Header.Set(ContentType, applicationJsonWithUtf8)
  518. type (
  519. Request struct {
  520. Name string `path:"name"`
  521. Year int `path:"year"`
  522. }
  523. WrappedRequest struct {
  524. Request
  525. }
  526. )
  527. router := httprouter.NewPatRouter()
  528. err = router.Handle(http.MethodHead, "/:name/:year", http.HandlerFunc(
  529. func(w http.ResponseWriter, r *http.Request) {
  530. var v WrappedRequest
  531. err = Parse(r, &v)
  532. assert.Nil(t, err)
  533. _, err = io.WriteString(w, fmt.Sprintf("%s:%d", v.Name, v.Year))
  534. assert.Nil(t, err)
  535. }))
  536. assert.Nil(t, err)
  537. rr := httptest.NewRecorder()
  538. router.ServeHTTP(rr, r)
  539. assert.Equal(t, "kevin:2017", rr.Body.String())
  540. }
  541. func TestParseWrappedRequestPtr(t *testing.T) {
  542. r, err := http.NewRequest(http.MethodGet, "http://hello.com/kevin/2017", nil)
  543. assert.Nil(t, err)
  544. type (
  545. Request struct {
  546. Name string `path:"name"`
  547. Year int `path:"year"`
  548. }
  549. WrappedRequest struct {
  550. *Request
  551. }
  552. )
  553. router := httprouter.NewPatRouter()
  554. err = router.Handle(http.MethodGet, "/:name/:year", http.HandlerFunc(
  555. func(w http.ResponseWriter, r *http.Request) {
  556. var v WrappedRequest
  557. err = Parse(r, &v)
  558. assert.Nil(t, err)
  559. _, err = io.WriteString(w, fmt.Sprintf("%s:%d", v.Name, v.Year))
  560. assert.Nil(t, err)
  561. }))
  562. assert.Nil(t, err)
  563. rr := httptest.NewRecorder()
  564. router.ServeHTTP(rr, r)
  565. assert.Equal(t, "kevin:2017", rr.Body.String())
  566. }
  567. func TestParseWithAll(t *testing.T) {
  568. r, err := http.NewRequest(http.MethodPost, "http://hello.com/kevin/2017?nickname=whatever&zipcode=200000",
  569. bytes.NewBufferString(`{"location": "shanghai", "time": 20170912}`))
  570. assert.Nil(t, err)
  571. r.Header.Set(ContentType, ApplicationJson)
  572. router := httprouter.NewPatRouter()
  573. err = router.Handle(http.MethodPost, "/:name/:year", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
  574. v := struct {
  575. Name string `path:"name"`
  576. Year int `path:"year"`
  577. Nickname string `form:"nickname"`
  578. Zipcode int64 `form:"zipcode"`
  579. Location string `json:"location"`
  580. Time int64 `json:"time"`
  581. }{}
  582. err = Parse(r, &v)
  583. assert.Nil(t, err)
  584. _, err = io.WriteString(w, fmt.Sprintf("%s:%d:%s:%d:%s:%d", v.Name, v.Year,
  585. v.Nickname, v.Zipcode, v.Location, v.Time))
  586. assert.Nil(t, err)
  587. }))
  588. assert.Nil(t, err)
  589. rr := httptest.NewRecorder()
  590. router.ServeHTTP(rr, r)
  591. assert.Equal(t, "kevin:2017:whatever:200000:shanghai:20170912", rr.Body.String())
  592. }
  593. func TestParseWithAllUtf8(t *testing.T) {
  594. r, err := http.NewRequest(http.MethodPost, "http://hello.com/kevin/2017?nickname=whatever&zipcode=200000",
  595. bytes.NewBufferString(`{"location": "shanghai", "time": 20170912}`))
  596. assert.Nil(t, err)
  597. r.Header.Set(ContentType, applicationJsonWithUtf8)
  598. router := httprouter.NewPatRouter()
  599. err = router.Handle(http.MethodPost, "/:name/:year", http.HandlerFunc(
  600. func(w http.ResponseWriter, r *http.Request) {
  601. v := struct {
  602. Name string `path:"name"`
  603. Year int `path:"year"`
  604. Nickname string `form:"nickname"`
  605. Zipcode int64 `form:"zipcode"`
  606. Location string `json:"location"`
  607. Time int64 `json:"time"`
  608. }{}
  609. err = Parse(r, &v)
  610. assert.Nil(t, err)
  611. _, err = io.WriteString(w, fmt.Sprintf("%s:%d:%s:%d:%s:%d", v.Name, v.Year,
  612. v.Nickname, v.Zipcode, v.Location, v.Time))
  613. assert.Nil(t, err)
  614. }))
  615. assert.Nil(t, err)
  616. rr := httptest.NewRecorder()
  617. router.ServeHTTP(rr, r)
  618. assert.Equal(t, "kevin:2017:whatever:200000:shanghai:20170912", rr.Body.String())
  619. }
  620. func TestParseWithMissingForm(t *testing.T) {
  621. r, err := http.NewRequest(http.MethodPost, "http://hello.com/kevin/2017?nickname=whatever",
  622. bytes.NewBufferString(`{"location": "shanghai", "time": 20170912}`))
  623. assert.Nil(t, err)
  624. router := httprouter.NewPatRouter()
  625. err = router.Handle(http.MethodPost, "/:name/:year", http.HandlerFunc(
  626. func(w http.ResponseWriter, r *http.Request) {
  627. v := struct {
  628. Name string `path:"name"`
  629. Year int `path:"year"`
  630. Nickname string `form:"nickname"`
  631. Zipcode int64 `form:"zipcode"`
  632. Location string `json:"location"`
  633. Time int64 `json:"time"`
  634. }{}
  635. err = Parse(r, &v)
  636. assert.NotNil(t, err)
  637. assert.Equal(t, "field zipcode is not set", err.Error())
  638. }))
  639. assert.Nil(t, err)
  640. rr := httptest.NewRecorder()
  641. router.ServeHTTP(rr, r)
  642. }
  643. func TestParseWithMissingAllForms(t *testing.T) {
  644. r, err := http.NewRequest(http.MethodPost, "http://hello.com/kevin/2017",
  645. bytes.NewBufferString(`{"location": "shanghai", "time": 20170912}`))
  646. assert.Nil(t, err)
  647. router := httprouter.NewPatRouter()
  648. err = router.Handle(http.MethodPost, "/:name/:year", http.HandlerFunc(
  649. func(w http.ResponseWriter, r *http.Request) {
  650. v := struct {
  651. Name string `path:"name"`
  652. Year int `path:"year"`
  653. Nickname string `form:"nickname"`
  654. Zipcode int64 `form:"zipcode"`
  655. Location string `json:"location"`
  656. Time int64 `json:"time"`
  657. }{}
  658. err = Parse(r, &v)
  659. assert.NotNil(t, err)
  660. }))
  661. assert.Nil(t, err)
  662. rr := httptest.NewRecorder()
  663. router.ServeHTTP(rr, r)
  664. }
  665. func TestParseWithMissingJson(t *testing.T) {
  666. r, err := http.NewRequest(http.MethodPost, "http://hello.com/kevin/2017?nickname=whatever&zipcode=200000",
  667. bytes.NewBufferString(`{"location": "shanghai"}`))
  668. assert.Nil(t, err)
  669. router := httprouter.NewPatRouter()
  670. err = router.Handle(http.MethodPost, "/:name/:year", http.HandlerFunc(
  671. func(w http.ResponseWriter, r *http.Request) {
  672. v := struct {
  673. Name string `path:"name"`
  674. Year int `path:"year"`
  675. Nickname string `form:"nickname"`
  676. Zipcode int64 `form:"zipcode"`
  677. Location string `json:"location"`
  678. Time int64 `json:"time"`
  679. }{}
  680. err = Parse(r, &v)
  681. assert.NotEqual(t, io.EOF, err)
  682. assert.NotNil(t, Parse(r, &v))
  683. }))
  684. assert.Nil(t, err)
  685. rr := httptest.NewRecorder()
  686. router.ServeHTTP(rr, r)
  687. }
  688. func TestParseWithMissingAllJsons(t *testing.T) {
  689. r, err := http.NewRequest(http.MethodGet, "http://hello.com/kevin/2017?nickname=whatever&zipcode=200000", nil)
  690. assert.Nil(t, err)
  691. router := httprouter.NewPatRouter()
  692. err = router.Handle(http.MethodGet, "/:name/:year", http.HandlerFunc(
  693. func(w http.ResponseWriter, r *http.Request) {
  694. v := struct {
  695. Name string `path:"name"`
  696. Year int `path:"year"`
  697. Nickname string `form:"nickname"`
  698. Zipcode int64 `form:"zipcode"`
  699. Location string `json:"location"`
  700. Time int64 `json:"time"`
  701. }{}
  702. err = Parse(r, &v)
  703. assert.NotEqual(t, io.EOF, err)
  704. assert.NotNil(t, err)
  705. }))
  706. assert.Nil(t, err)
  707. rr := httptest.NewRecorder()
  708. router.ServeHTTP(rr, r)
  709. }
  710. func TestParseWithMissingPath(t *testing.T) {
  711. r, err := http.NewRequest(http.MethodPost, "http://hello.com/2017?nickname=whatever&zipcode=200000",
  712. bytes.NewBufferString(`{"location": "shanghai", "time": 20170912}`))
  713. assert.Nil(t, err)
  714. router := httprouter.NewPatRouter()
  715. err = router.Handle(http.MethodPost, "/:name/:year", http.HandlerFunc(
  716. func(w http.ResponseWriter, r *http.Request) {
  717. v := struct {
  718. Name string `path:"name"`
  719. Year int `path:"year"`
  720. Nickname string `form:"nickname"`
  721. Zipcode int64 `form:"zipcode"`
  722. Location string `json:"location"`
  723. Time int64 `json:"time"`
  724. }{}
  725. err = Parse(r, &v)
  726. assert.NotNil(t, err)
  727. assert.Equal(t, "field name is not set", err.Error())
  728. }))
  729. assert.Nil(t, err)
  730. rr := httptest.NewRecorder()
  731. router.ServeHTTP(rr, r)
  732. }
  733. func TestParseWithMissingAllPaths(t *testing.T) {
  734. r, err := http.NewRequest(http.MethodPost, "http://hello.com/?nickname=whatever&zipcode=200000",
  735. bytes.NewBufferString(`{"location": "shanghai", "time": 20170912}`))
  736. assert.Nil(t, err)
  737. router := httprouter.NewPatRouter()
  738. err = router.Handle(http.MethodPost, "/:name/:year", http.HandlerFunc(
  739. func(w http.ResponseWriter, r *http.Request) {
  740. v := struct {
  741. Name string `path:"name"`
  742. Year int `path:"year"`
  743. Nickname string `form:"nickname"`
  744. Zipcode int64 `form:"zipcode"`
  745. Location string `json:"location"`
  746. Time int64 `json:"time"`
  747. }{}
  748. err = Parse(r, &v)
  749. assert.NotNil(t, err)
  750. }))
  751. assert.Nil(t, err)
  752. rr := httptest.NewRecorder()
  753. router.ServeHTTP(rr, r)
  754. }
  755. func TestParseGetWithContentLengthHeader(t *testing.T) {
  756. r, err := http.NewRequest(http.MethodGet, "http://hello.com/kevin/2017?nickname=whatever&zipcode=200000", nil)
  757. assert.Nil(t, err)
  758. r.Header.Set(ContentType, ApplicationJson)
  759. r.Header.Set(contentLength, "1024")
  760. router := httprouter.NewPatRouter()
  761. err = router.Handle(http.MethodGet, "/:name/:year", http.HandlerFunc(
  762. func(w http.ResponseWriter, r *http.Request) {
  763. v := struct {
  764. Name string `path:"name"`
  765. Year int `path:"year"`
  766. Nickname string `form:"nickname"`
  767. Zipcode int64 `form:"zipcode"`
  768. Location string `json:"location"`
  769. Time int64 `json:"time"`
  770. }{}
  771. err = Parse(r, &v)
  772. assert.NotNil(t, err)
  773. }))
  774. assert.Nil(t, err)
  775. rr := httptest.NewRecorder()
  776. router.ServeHTTP(rr, r)
  777. }
  778. func TestParseJsonPostWithTypeMismatch(t *testing.T) {
  779. r, err := http.NewRequest(http.MethodPost, "http://hello.com/kevin/2017?nickname=whatever&zipcode=200000",
  780. bytes.NewBufferString(`{"time": "20170912"}`))
  781. assert.Nil(t, err)
  782. r.Header.Set(ContentType, applicationJsonWithUtf8)
  783. router := httprouter.NewPatRouter()
  784. err = router.Handle(http.MethodPost, "/:name/:year", http.HandlerFunc(
  785. func(w http.ResponseWriter, r *http.Request) {
  786. v := struct {
  787. Name string `path:"name"`
  788. Year int `path:"year"`
  789. Nickname string `form:"nickname"`
  790. Zipcode int64 `form:"zipcode"`
  791. Time int64 `json:"time"`
  792. }{}
  793. err = Parse(r, &v)
  794. assert.NotNil(t, err)
  795. }))
  796. assert.Nil(t, err)
  797. rr := httptest.NewRecorder()
  798. router.ServeHTTP(rr, r)
  799. }
  800. func TestParseJsonPostWithInt2String(t *testing.T) {
  801. r, err := http.NewRequest(http.MethodPost, "http://hello.com/kevin/2017",
  802. bytes.NewBufferString(`{"time": 20170912}`))
  803. assert.Nil(t, err)
  804. r.Header.Set(ContentType, applicationJsonWithUtf8)
  805. router := httprouter.NewPatRouter()
  806. err = router.Handle(http.MethodPost, "/:name/:year", http.HandlerFunc(
  807. func(w http.ResponseWriter, r *http.Request) {
  808. v := struct {
  809. Name string `path:"name"`
  810. Year int `path:"year"`
  811. Time string `json:"time"`
  812. }{}
  813. err = Parse(r, &v)
  814. assert.NotNil(t, err)
  815. }))
  816. assert.Nil(t, err)
  817. rr := httptest.NewRecorder()
  818. router.ServeHTTP(rr, r)
  819. }
  820. func BenchmarkParseRaw(b *testing.B) {
  821. r, err := http.NewRequest(http.MethodGet, "http://hello.com/a?name=hello&age=18&percent=3.4", nil)
  822. if err != nil {
  823. b.Fatal(err)
  824. }
  825. for i := 0; i < b.N; i++ {
  826. v := struct {
  827. Name string `form:"name"`
  828. Age int `form:"age"`
  829. Percent float64 `form:"percent,optional"`
  830. }{}
  831. v.Name = r.FormValue("name")
  832. v.Age, err = strconv.Atoi(r.FormValue("age"))
  833. if err != nil {
  834. b.Fatal(err)
  835. }
  836. v.Percent, err = strconv.ParseFloat(r.FormValue("percent"), 64)
  837. if err != nil {
  838. b.Fatal(err)
  839. }
  840. }
  841. }
  842. func BenchmarkParseAuto(b *testing.B) {
  843. r, err := http.NewRequest(http.MethodGet, "http://hello.com/a?name=hello&age=18&percent=3.4", nil)
  844. if err != nil {
  845. b.Fatal(err)
  846. }
  847. for i := 0; i < b.N; i++ {
  848. v := struct {
  849. Name string `form:"name"`
  850. Age int `form:"age"`
  851. Percent float64 `form:"percent,optional"`
  852. }{}
  853. if err = Parse(r, &v); err != nil {
  854. b.Fatal(err)
  855. }
  856. }
  857. }