server_test.go 44 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761
  1. package blademaster
  2. import (
  3. "bytes"
  4. "context"
  5. "crypto/tls"
  6. "encoding/json"
  7. "encoding/xml"
  8. "fmt"
  9. "io/ioutil"
  10. "net/http"
  11. "os"
  12. "path"
  13. "path/filepath"
  14. "regexp"
  15. "strconv"
  16. "strings"
  17. "sync"
  18. "sync/atomic"
  19. "testing"
  20. "time"
  21. "go-common/library/ecode"
  22. "go-common/library/log"
  23. "go-common/library/net/http/blademaster/binding"
  24. "go-common/library/net/http/blademaster/render"
  25. "go-common/library/net/http/blademaster/tests"
  26. "go-common/library/net/metadata"
  27. xtime "go-common/library/time"
  28. "github.com/gogo/protobuf/proto"
  29. "github.com/pkg/errors"
  30. "github.com/stretchr/testify/assert"
  31. )
  32. var (
  33. sonce sync.Once
  34. once sync.Once
  35. curEngine atomic.Value
  36. ByteContent = []byte(`<html>
  37. <meta http-equiv="refresh" content="0;uri=http://www.bilibili.com/">
  38. </html>`)
  39. CertPEM = `-----BEGIN CERTIFICATE-----
  40. MIIDJzCCAg8CCQDHIbk1Vp7UbzANBgkqhkiG9w0BAQsFADCBkDELMAkGA1UEBhMC
  41. Q04xETAPBgNVBAgMCFNoYW5naGFpMREwDwYDVQQHDAhTaGFuZ2hhaTERMA8GA1UE
  42. CgwIYmlsaWJpbGkxETAPBgNVBAsMCGJpbGliaWxpMRUwEwYDVQQDDAxiaWxpYmls
  43. aS5jb20xHjAcBgkqhkiG9w0BCQEWD2l0QGJpbGliaWxpLmNvbTAeFw0xNzExMDcw
  44. NDI1MzJaFw0xODExMDcwNDI1MzJaMBoxGDAWBgNVBAMMD2xvY2FsaG9zdDoxODA4
  45. MTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALNKS9f7sEE+xx2SiIgI
  46. tfmUVi3HkbWRWiZxZ82gRQnYUvgNsQUenyMH4ukViC7rEqBomscP0YjWhIvunhKe
  47. RzXqWxZyKF86lL0+n1X+USESWdMQe8nYhCAwTE3JIykBrqjEiYMSI5TLwQrqFUJ9
  48. nd7EywdlUgolJFO2pbltU9a8stlto9OOLXo5veb30nAW5tnDF5Q1jlKBRpGV4+Wy
  49. 3Tn9V9a6mPaoLQOLQzLWfjIWok0UKdYOWZUwmfboFloI0J0VA8Dn3qr2VGEucUG4
  50. C5pIzV7/ke0Ymca8H2O1Gt5jrhbieY1XLP7NEoic1xdKTa6TLbReWTUEfqErCD3X
  51. b28CAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAS+tB9PDV0tzFYtVzaWGrqypfnbEC
  52. l5XoT6kRKn3Pf74MQQDMmuPCNZqf8aznx7+inzf4xeMsM68mkbaWvDkD2W8rSn47
  53. tnFZNPLzlP5sXrt1RgfEK1azVOqX+PSNqDxFetB/smvsVr0EduX0tcmSNMChzx7I
  54. Igy/I93TVf/hzu3MubZlCjTIQEvfek/Qc/eei7SQYS3dauSKaLfOwMdan9U2gmSr
  55. byb4f0vI1wuBSAEceJMrHcPGNgibAUMBMdSOYljYxSgmC0gFW68aD3gdn1Z/KOyd
  56. r1VaEkBHRoXvVUYPrFDFYO4nP65aZBLWgIn/EtilNektlAZhljSzk6bWXA==
  57. -----END CERTIFICATE-----
  58. `
  59. KeyPEM = `-----BEGIN RSA PRIVATE KEY-----
  60. MIIEowIBAAKCAQEAs0pL1/uwQT7HHZKIiAi1+ZRWLceRtZFaJnFnzaBFCdhS+A2x
  61. BR6fIwfi6RWILusSoGiaxw/RiNaEi+6eEp5HNepbFnIoXzqUvT6fVf5RIRJZ0xB7
  62. ydiEIDBMTckjKQGuqMSJgxIjlMvBCuoVQn2d3sTLB2VSCiUkU7aluW1T1ryy2W2j
  63. 044tejm95vfScBbm2cMXlDWOUoFGkZXj5bLdOf1X1rqY9qgtA4tDMtZ+MhaiTRQp
  64. 1g5ZlTCZ9ugWWgjQnRUDwOfeqvZUYS5xQbgLmkjNXv+R7RiZxrwfY7Ua3mOuFuJ5
  65. jVcs/s0SiJzXF0pNrpMttF5ZNQR+oSsIPddvbwIDAQABAoIBACLW2hwTNXHIQCr3
  66. 8X31q17fO0vUDvVoVEtKGDC15xR9q8m152MmSygkfSxr2bW8SjdPfFwYL9BWVxVV
  67. /fOCPDY23xJihoPSv1py08WDEMLLbRb9igB0CWCz4e/vmNx8DjOPVWVZ3f4pBc8Y
  68. I59zB31lYkqCnsmH5CI8SMHag8MjPmzc7TtoROUbV0rcyoOx/JwrgwuGsC/UP9GY
  69. Oj021xiLcwP5qD4sBIuXxIPx9zwCDowujjBQ3ViSgcQk92Z1fsPMBvKYUuP2hHcZ
  70. M/Dnuzz/OyzfP0u3Aq+VpQlXHVmEptU6kfFjK8X3J9tWr7PAvAaFqIs2xL5p6gz8
  71. q50gfzkCgYEA5Wa89L30UD17s+2RT2Slg5fmSvn2gO0Dz2Dhav/G2UPfbW+22rAC
  72. iotIfnF4IuA6QQX6tW5L/nVbLYQUtWNxzWsYCQAbRrBQi1BBfh0EOli52ZicuWd3
  73. 6rOqeOzqsXRdyrwVnpfKf1Hdh7Dc++zG920ktXbC33jgGDLmSLxnysMCgYEAyBQf
  74. du67z3//yOt3z+zl1Tug3t/ioPSWijrlUtsqbRuOWvxRwUtyOB4Tm171j5sWPiJu
  75. YOisOvjrRI2L9xjdtP4HTAiO4//YiNkCHdFiyHTzMqb1RBbHVQZ6eFmjvdmrgIkG
  76. 4vXt3mZ1kQY264APB99W+BKFtLDPvaz+Hgy9xeUCgYEAhPMcA8OrOm3Hqam/k4HD
  77. Ixb/0ug3YtT6Zk/BlN+UAQsDDEu4b9meP2klpJJii+PkHxc2C7xWsqyVITXxQobV
  78. x7WPgnfbVwaMR5FFw69RafdODrwR6Kn8p7tkyxyTkDDewsZqyTUzmMJ7X06zZBX/
  79. 4hoRMlIX8qf9SEkHiZQXmz0CgYAGNamsVUh67iwQHk6/o0iWz5z0jdpIyI6Lh7xq
  80. T+cHL93BMSeQajkHSNeu8MmKRXPxRbxLQa1mvyb+H66CYsEuxtuPHozgwqYDyUhp
  81. iIAaXJbXsZrXHCXfm63dYlrUn5bVDGusS5mwV1m6wIif0n+k7OeUF28S5pHr/xx7
  82. 7kVNiQKBgDeXBYkZIRlm0PwtmZcoAU9bVK2m7MnLj6G/MebpzSwSFbbFhxZnnwS9
  83. EOUtzcssIiFpJiN+ZKFOV+9S9ylYFSYlxGwrWvE3+nmzm8X04tsYhvjO5Q1w1Egs
  84. U31DFsHpaXEAfBc7ugLimKKKbptJJDPzUfUtXIltCxI9YCzFFRXY
  85. -----END RSA PRIVATE KEY-----
  86. `
  87. )
  88. const (
  89. SockAddr = "localhost:18080"
  90. AdHocSockAddr = "localhost:18081"
  91. )
  92. func cleanup(dir string) {
  93. matches, err := filepath.Glob(dir)
  94. if err != nil {
  95. return
  96. }
  97. for _, p := range matches {
  98. os.RemoveAll(p)
  99. }
  100. }
  101. func setupLogging() {
  102. dir, err := ioutil.TempDir("", "blademaster")
  103. defer func() {
  104. baseDir := path.Dir(dir)
  105. cleanup(path.Join(baseDir, "blademaster*"))
  106. }()
  107. if err != nil {
  108. panic(err)
  109. }
  110. for l, f := range map[string]string{
  111. "info.log": "/dev/stdout",
  112. "warning.log": "/dev/stdout",
  113. "error.log": "/dev/stderr",
  114. } {
  115. p := filepath.Join(dir, l)
  116. if err := os.Symlink(f, p); err != nil {
  117. panic(err)
  118. }
  119. }
  120. logConf := &log.Config{
  121. Dir: dir,
  122. }
  123. log.Init(logConf)
  124. }
  125. func init() {
  126. if os.Getenv("TEST_LOGGING") == "1" {
  127. setupLogging()
  128. }
  129. }
  130. func startTestServer() {
  131. _httpDSN = "tcp://0.0.0.0:18090/?maxlisten=20000&timeout=1s&readtimeout=1s&writetimeout=1s"
  132. engine := NewServer(nil)
  133. engine.GET("/test", func(ctx *Context) {
  134. ctx.JSON("", nil)
  135. })
  136. engine.GET("/mirrortest", func(ctx *Context) {
  137. ctx.JSON(strconv.FormatBool(metadata.Bool(ctx, metadata.Mirror)), nil)
  138. })
  139. engine.Start()
  140. }
  141. func TestServer2(t *testing.T) {
  142. sonce.Do(startTestServer)
  143. resp, err := http.Get("http://localhost:18090/test")
  144. if err != nil {
  145. t.Errorf("HTTPServ: get error(%v)", err)
  146. }
  147. if resp.StatusCode != http.StatusOK {
  148. t.Errorf("http.Get get error code:%d", resp.StatusCode)
  149. }
  150. resp.Body.Close()
  151. }
  152. func BenchmarkServer2(b *testing.B) {
  153. once.Do(startServer)
  154. b.ResetTimer()
  155. b.RunParallel(func(pb *testing.PB) {
  156. for pb.Next() {
  157. resp, err := http.Get("http://localhost:18090/test")
  158. if err != nil {
  159. b.Errorf("HTTPServ: get error(%v)", err)
  160. continue
  161. }
  162. if resp.StatusCode != http.StatusOK {
  163. b.Errorf("HTTPServ: get error status code:%d", resp.StatusCode)
  164. }
  165. resp.Body.Close()
  166. }
  167. })
  168. }
  169. func TestDSNParse(t *testing.T) {
  170. conf := parseDSN("tcp://0.0.0.0:18090/?maxlisten=20000&timeout=1s&readTimeout=1s&writeTimeout=1s")
  171. assert.Equal(t, ServerConfig{
  172. Network: "tcp",
  173. Addr: "0.0.0.0:18090",
  174. Timeout: xtime.Duration(time.Second),
  175. ReadTimeout: xtime.Duration(time.Second),
  176. WriteTimeout: xtime.Duration(time.Second),
  177. }, *conf)
  178. conf = parseDSN("unix:///temp/bm.sock?maxlisten=20000&timeout=2s&readTimeout=1s&writeTimeout=1s")
  179. assert.Equal(t, ServerConfig{
  180. Network: "unix",
  181. Addr: "/temp/bm.sock",
  182. Timeout: xtime.Duration(time.Second * 2),
  183. ReadTimeout: xtime.Duration(time.Second),
  184. WriteTimeout: xtime.Duration(time.Second),
  185. }, *conf)
  186. }
  187. type Timestamp struct {
  188. Now int64 `json:"now"`
  189. }
  190. type Archive struct {
  191. Mids []int64 `json:"mids" form:"mids,split" validate:"dive,gt=1,required"`
  192. Cid int `json:"cid" form:"cid" validate:"max=10,min=1"`
  193. Title string `json:"title" form:"title" validate:"required"`
  194. Content string `json:"content" form:"content"`
  195. }
  196. type DevResp struct {
  197. Code int `json:"code"`
  198. Data *Device `json:"data"`
  199. }
  200. func uri(base, path string) string {
  201. return fmt.Sprintf("%s://%s%s", "http", base, path)
  202. }
  203. func now() Timestamp {
  204. return Timestamp{
  205. Now: time.Now().Unix(),
  206. }
  207. }
  208. func setupHandler(engine *Engine) {
  209. // engine.GET("/", func(ctx *Context) {
  210. // ctx.Status(200)
  211. // })
  212. engine.Use(CORS(), CSRF(), Mobile())
  213. // set the global timeout is 2 second
  214. engine.conf.Timeout = xtime.Duration(time.Second * 2)
  215. engine.Ping(func(ctx *Context) {
  216. ctx.AbortWithStatus(200)
  217. })
  218. engine.Register(func(ctx *Context) {
  219. ctx.JSONMap(map[string]interface{}{
  220. "region": "aws",
  221. }, nil)
  222. })
  223. engine.HEAD("/head", func(ctx *Context) {
  224. ctx.Status(200)
  225. })
  226. engine.GET("/get", func(ctx *Context) {
  227. ctx.String(200, "%s", "pong")
  228. })
  229. engine.POST("/post", func(ctx *Context) {
  230. ctx.String(200, "%s", "pong")
  231. })
  232. engine.PUT("/put", func(ctx *Context) {
  233. ctx.String(200, "%s", "pong")
  234. })
  235. engine.DELETE("/delete", func(ctx *Context) {
  236. ctx.String(200, "%s", "pong")
  237. })
  238. engine.GET("/json", func(ctx *Context) {
  239. ctx.JSON(now(), nil)
  240. })
  241. engine.GET("/null-json", func(ctx *Context) {
  242. ctx.JSON(nil, nil)
  243. })
  244. engine.GET("/err", func(ctx *Context) {
  245. ctx.JSON(now(), errors.New("A error raised from handler func"))
  246. })
  247. engine.GET("/xml", func(ctx *Context) {
  248. ctx.XML(now(), nil)
  249. })
  250. engine.GET("/bytes", func(ctx *Context) {
  251. ctx.Bytes(200, "text/html", ByteContent)
  252. })
  253. engine.GET("/bench", func(ctx *Context) {
  254. ctx.JSON(now(), nil)
  255. })
  256. engine.GET("/sleep5", func(ctx *Context) {
  257. time.Sleep(time.Second * 30)
  258. ctx.JSON(now(), nil)
  259. })
  260. engine.GET("/timeout", func(ctx *Context) {
  261. start := time.Now()
  262. <-ctx.Done()
  263. ctx.String(200, "Timeout within %s", time.Since(start))
  264. })
  265. engine.GET("/timeout-from-method-config", func(ctx *Context) {
  266. start := time.Now()
  267. <-ctx.Done()
  268. ctx.String(200, "Timeout within %s", time.Since(start))
  269. })
  270. engine.SetMethodConfig("/timeout-from-method-config", &MethodConfig{Timeout: xtime.Duration(time.Second * 3)})
  271. engine.GET("/redirect", func(ctx *Context) {
  272. ctx.Redirect(301, "/bytes")
  273. })
  274. engine.GET("/panic", func(_ *Context) {
  275. panic("Oupps, Houston, we have a problem")
  276. })
  277. engine.GET("/json-map", func(ctx *Context) {
  278. ctx.JSONMap(map[string]interface{}{
  279. "tid": 1,
  280. }, nil)
  281. })
  282. engine.GET("/bind", func(ctx *Context) {
  283. v := new(Archive)
  284. err := ctx.Bind(v)
  285. if err != nil {
  286. return
  287. }
  288. ctx.JSON(v, nil)
  289. })
  290. engine.POST("/bindwith", func(ctx *Context) {
  291. v := new(Archive)
  292. err := ctx.BindWith(v, binding.JSON)
  293. if err != nil {
  294. return
  295. }
  296. ctx.JSON(v, nil)
  297. })
  298. engine.GET("/pb", func(ctx *Context) {
  299. now := &tests.Time{
  300. Now: time.Now().Unix(),
  301. }
  302. ctx.Protobuf(now, nil)
  303. })
  304. engine.GET("/pb-error", func(ctx *Context) {
  305. ctx.Protobuf(nil, ecode.RequestErr)
  306. })
  307. engine.GET("/pb-nildata-nilerr", func(ctx *Context) {
  308. ctx.Protobuf(nil, nil)
  309. })
  310. engine.GET("/pb-data-err", func(ctx *Context) {
  311. now := &tests.Time{
  312. Now: time.Now().Unix(),
  313. }
  314. ctx.Protobuf(now, ecode.RequestErr)
  315. })
  316. engine.GET("/member-blocked", func(ctx *Context) {
  317. ctx.JSON(nil, ecode.MemberBlocked)
  318. })
  319. engine.GET("/device", func(ctx *Context) {
  320. dev, ok := ctx.Get("device")
  321. if !ok {
  322. ctx.JSON(nil, ecode.RequestErr)
  323. return
  324. }
  325. ctx.JSON(dev, nil)
  326. })
  327. engine.GET("/device-from-meta", func(ctx *Context) {
  328. dev, ok := metadata.Value(ctx, "device").(*Device)
  329. if !ok {
  330. ctx.JSON(nil, ecode.RequestErr)
  331. return
  332. }
  333. ctx.JSON(dev, nil)
  334. })
  335. engine.GET("/remote-ip", func(ctx *Context) {
  336. ctx.JSON(metadata.String(ctx, metadata.RemoteIP), nil)
  337. })
  338. m1 := func() HandlerFunc {
  339. return func(ctx *Context) {
  340. ctx.Set("m1", "middleware pong")
  341. ctx.Next()
  342. }
  343. }
  344. m2 := func() func(ctx *Context) {
  345. return func(ctx *Context) {
  346. v, isok := ctx.Get("m1")
  347. if !isok {
  348. ctx.AbortWithStatus(500)
  349. return
  350. }
  351. ctx.Set("m2", v)
  352. ctx.Next()
  353. }
  354. }
  355. engine.Use(m1())
  356. engine.UseFunc(m2())
  357. engine.GET("/use", func(ctx *Context) {
  358. v, isok := ctx.Get("m2")
  359. if !isok {
  360. ctx.AbortWithStatus(500)
  361. return
  362. }
  363. ctx.String(200, "%s", v.(string))
  364. })
  365. r := engine.Group("/group", func(ctx *Context) {
  366. })
  367. r.GET("/get", func(ctx *Context) {
  368. ctx.String(200, "%s", "pong")
  369. })
  370. rr := r.Group("/abort", func(ctx *Context) {
  371. ctx.String(200, "%s", "pong")
  372. ctx.Abort()
  373. })
  374. rr.GET("", func(ctx *Context) {
  375. ctx.String(500, "never get this echo")
  376. })
  377. rrr := r.Group("/test", func(ctx *Context) {
  378. })
  379. g1 := func() HandlerFunc {
  380. return func(ctx *Context) {
  381. v, isok := ctx.Get("m2")
  382. if !isok {
  383. ctx.AbortWithStatus(500)
  384. return
  385. }
  386. ctx.Set("g1", v)
  387. ctx.Next()
  388. }
  389. }
  390. g2 := func() func(ctx *Context) {
  391. return func(ctx *Context) {
  392. v, isok := ctx.Get("g1")
  393. if !isok {
  394. ctx.AbortWithStatus(500)
  395. return
  396. }
  397. ctx.Next()
  398. ctx.String(200, "%s", v.(string))
  399. }
  400. }
  401. rrr.Use(g1()).UseFunc(g2()).GET("/use", func(ctx *Context) {})
  402. groupInject := engine.Group("/inject")
  403. engine.Inject("^/inject", func(ctx *Context) {
  404. ctx.Set("injected", "injected")
  405. })
  406. groupInject.GET("/index", func(ctx *Context) {
  407. injected, _ := ctx.Get("injected")
  408. injectedString, _ := injected.(string)
  409. ctx.String(200, strings.Join([]string{"index", injectedString}, "-"))
  410. })
  411. engine.GET("/group/test/json-status", func(ctx *Context) {
  412. ctx.JSON(nil, ecode.MemberBlocked)
  413. })
  414. engine.GET("/group/test/xml-status", func(ctx *Context) {
  415. ctx.XML(nil, ecode.MemberBlocked)
  416. })
  417. engine.GET("/group/test/proto-status", func(ctx *Context) {
  418. ctx.Protobuf(nil, ecode.MemberBlocked)
  419. })
  420. engine.GET("/group/test/json-map-status", func(ctx *Context) {
  421. ctx.JSONMap(map[string]interface{}{}, ecode.MemberBlocked)
  422. })
  423. }
  424. func startServer() {
  425. e := Default()
  426. setupHandler(e)
  427. go e.Run(SockAddr)
  428. curEngine.Store(e)
  429. time.Sleep(time.Second)
  430. }
  431. func TestSetupHandler(t *testing.T) {
  432. engine := Default()
  433. setupHandler(engine)
  434. }
  435. func TestServeUnix(t *testing.T) {
  436. engine := Default()
  437. setupHandler(engine)
  438. closed := make(chan struct{})
  439. defer func() {
  440. if err := engine.Shutdown(context.TODO()); err != nil {
  441. t.Errorf("Failed to shutdown engine: %s", err)
  442. }
  443. <-closed
  444. }()
  445. unixs, err := ioutil.TempFile("", "engine.sock")
  446. if err != nil {
  447. t.Fatalf("Failed to create temp file: %s", err)
  448. }
  449. go func() {
  450. if err := engine.RunUnix(unixs.Name()); err != nil {
  451. if errors.Cause(err) == http.ErrServerClosed {
  452. t.Logf("Server stopped due to shutting down command")
  453. } else {
  454. t.Errorf("Failed to serve with unix socket: %s", err)
  455. }
  456. }
  457. closed <- struct{}{}
  458. }()
  459. // connection test required
  460. time.Sleep(time.Second)
  461. }
  462. func shutdown() {
  463. if err := curEngine.Load().(*Engine).Shutdown(context.TODO()); err != nil {
  464. panic(err)
  465. }
  466. }
  467. func TestServeTLS(t *testing.T) {
  468. engine := New()
  469. setupHandler(engine)
  470. closed := make(chan struct{})
  471. defer func() {
  472. if err := engine.Shutdown(context.TODO()); err != nil {
  473. t.Errorf("Failed to shutdown engine: %s", err)
  474. }
  475. <-closed
  476. }()
  477. cert, err := ioutil.TempFile("", "cert.pem")
  478. if err != nil {
  479. t.Fatalf("Failed to create temp file: %s", err)
  480. }
  481. key, err := ioutil.TempFile("", "key.pem")
  482. if err != nil {
  483. t.Fatalf("Failed to create temp file: %s", err)
  484. }
  485. if _, err = cert.WriteString(CertPEM); err != nil {
  486. t.Fatalf("Failed to write cert file: %s", err)
  487. }
  488. if _, err = key.WriteString(KeyPEM); err != nil {
  489. t.Fatalf("Failed to write key file: %s", err)
  490. }
  491. go func() {
  492. if rerr := engine.RunTLS(AdHocSockAddr, cert.Name(), key.Name()); rerr != nil {
  493. if errors.Cause(rerr) == http.ErrServerClosed {
  494. t.Logf("Server stopped due to shutting down command")
  495. } else {
  496. t.Errorf("Failed to serve with tls: %s", rerr)
  497. }
  498. }
  499. closed <- struct{}{}
  500. }()
  501. tr := &http.Transport{
  502. TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
  503. }
  504. client := &http.Client{Transport: tr}
  505. resp, err := client.Get(fmt.Sprintf("%s://%s%s", "https", AdHocSockAddr, "/get"))
  506. if err != nil {
  507. t.Fatalf("Failed to send https request: %s", err)
  508. }
  509. if resp.StatusCode != http.StatusOK {
  510. t.Errorf("http.Get get error code:%d", resp.StatusCode)
  511. }
  512. resp.Body.Close()
  513. }
  514. func TestServer(t *testing.T) {
  515. once.Do(startServer)
  516. resp, err := http.Get(uri(SockAddr, "/get"))
  517. if err != nil {
  518. t.Fatalf("BladeMaster: get error(%v)", err)
  519. }
  520. if resp.StatusCode != http.StatusOK {
  521. t.Errorf("http.Get get error code:%d", resp.StatusCode)
  522. }
  523. resp.Body.Close()
  524. }
  525. func pongValidator(expected string, t *testing.T) func(*http.Response) error {
  526. return func(resp *http.Response) error {
  527. if resp.StatusCode != http.StatusOK {
  528. return fmt.Errorf("http.Get get error code: %d", resp.StatusCode)
  529. }
  530. bs, err := ioutil.ReadAll(resp.Body)
  531. if err != nil {
  532. t.Logf("ioutil.ReadAll() failed: %s", err)
  533. return err
  534. }
  535. resp.Body.Close()
  536. if ps := string(bs); ps != expected {
  537. return fmt.Errorf("Response body not expected: %s != %s", ps, expected)
  538. }
  539. return nil
  540. }
  541. }
  542. func TestPathHandle(t *testing.T) {
  543. once.Do(startServer)
  544. expected := "pong"
  545. validateFn := pongValidator(expected, t)
  546. testCase := map[string]map[string]func(*http.Response) error{
  547. "/monitor/ping": {
  548. "GET": func(resp *http.Response) error {
  549. assert.Equal(t, 200, resp.StatusCode)
  550. return nil
  551. },
  552. },
  553. "/register": {
  554. "GET": func(resp *http.Response) error {
  555. assert.Equal(t, 200, resp.StatusCode)
  556. bs, err := ioutil.ReadAll(resp.Body)
  557. assert.NoError(t, err)
  558. md := make(map[string]interface{})
  559. assert.NoError(t, json.Unmarshal(bs, &md))
  560. assert.Equal(t, "aws", md["region"])
  561. assert.Equal(t, 0, int(md["code"].(float64)))
  562. assert.Equal(t, "0", md["message"])
  563. return nil
  564. },
  565. },
  566. "/head": {
  567. "HEAD": func(resp *http.Response) error {
  568. assert.Equal(t, 200, resp.StatusCode)
  569. return nil
  570. },
  571. },
  572. "/get": {
  573. "GET": validateFn,
  574. },
  575. "/post": {
  576. "POST": validateFn,
  577. },
  578. "/put": {
  579. "PUT": validateFn,
  580. },
  581. "/delete": {
  582. "DELETE": validateFn,
  583. },
  584. "/not-exist-path": {
  585. "GET": func(resp *http.Response) error {
  586. assert.Equal(t, 404, resp.StatusCode)
  587. return nil
  588. },
  589. },
  590. }
  591. c := &http.Client{}
  592. for path := range testCase {
  593. for method := range testCase[path] {
  594. validator := testCase[path][method]
  595. req, err := http.NewRequest(method, uri(SockAddr, path), nil)
  596. if err != nil {
  597. t.Fatalf("Failed to build request: %s", err)
  598. }
  599. resp, err := c.Do(req)
  600. if err != nil {
  601. t.Fatalf("Failed to send request: %s", err)
  602. }
  603. defer resp.Body.Close()
  604. if err := validator(resp); err != nil {
  605. t.Errorf("Failed to validate request to `%s %s`: %s", method, path, err)
  606. }
  607. }
  608. }
  609. }
  610. func TestMiddleWare(t *testing.T) {
  611. once.Do(startServer)
  612. expected := "middleware pong"
  613. validateFn := pongValidator(expected, t)
  614. testCase := map[string]map[string]func(*http.Response) error{
  615. "/use": {
  616. "GET": validateFn,
  617. },
  618. "/group/test/use": {
  619. "GET": validateFn,
  620. },
  621. }
  622. c := &http.Client{}
  623. for path := range testCase {
  624. for method := range testCase[path] {
  625. validator := testCase[path][method]
  626. req, err := http.NewRequest(method, uri(SockAddr, path), nil)
  627. if err != nil {
  628. t.Fatalf("Failed to build request: %s", err)
  629. }
  630. resp, err := c.Do(req)
  631. if err != nil {
  632. t.Errorf("Failed to send request: %s", err)
  633. }
  634. defer resp.Body.Close()
  635. if err := validator(resp); err != nil {
  636. t.Errorf("Failed to validate request to `%s %s`: %s", method, path, err)
  637. }
  638. }
  639. }
  640. }
  641. func TestRouterGroup(t *testing.T) {
  642. once.Do(startServer)
  643. expected := "pong"
  644. validateFn := pongValidator(expected, t)
  645. testCase := map[string]map[string]func(*http.Response) error{
  646. "/group/get": {
  647. "GET": validateFn,
  648. },
  649. "/group/abort": {
  650. "GET": validateFn,
  651. },
  652. }
  653. c := &http.Client{}
  654. for path := range testCase {
  655. for method := range testCase[path] {
  656. validator := testCase[path][method]
  657. req, err := http.NewRequest(method, uri(SockAddr, path), nil)
  658. if err != nil {
  659. t.Fatalf("Failed to build request: %s", err)
  660. }
  661. resp, err := c.Do(req)
  662. if err != nil {
  663. t.Errorf("Failed to send request: %s", err)
  664. }
  665. defer resp.Body.Close()
  666. if err := validator(resp); err != nil {
  667. t.Errorf("Failed to validate request to `%s %s`: %s", method, path, err)
  668. }
  669. }
  670. }
  671. }
  672. func TestMonitor(t *testing.T) {
  673. once.Do(startServer)
  674. path := "/metrics"
  675. resp, err := http.Get(uri(SockAddr, path))
  676. if err != nil {
  677. t.Fatalf("Failed to send request: %s", err)
  678. }
  679. defer resp.Body.Close()
  680. assert.Equal(t, http.StatusOK, resp.StatusCode)
  681. bs, err := ioutil.ReadAll(resp.Body)
  682. assert.Equal(t, nil, err)
  683. assert.False(t, len(bs) <= 0)
  684. }
  685. func TestMetadata(t *testing.T) {
  686. once.Do(startServer)
  687. path := "/metadata"
  688. resp, err := http.Get(uri(SockAddr, path))
  689. if err != nil {
  690. t.Fatalf("Failed to send request: %s", err)
  691. }
  692. defer resp.Body.Close()
  693. assert.Equal(t, http.StatusOK, resp.StatusCode)
  694. bs, err := ioutil.ReadAll(resp.Body)
  695. assert.Equal(t, nil, err)
  696. assert.False(t, len(bs) <= 0)
  697. }
  698. func TestRender(t *testing.T) {
  699. once.Do(startServer)
  700. bodyTestCase := map[string]map[string]func([]byte) error{
  701. "/json": {
  702. "GET": func(bs []byte) error {
  703. var data struct {
  704. Code int `json:"code"`
  705. TTL int `json:"ttl"`
  706. Ts *Timestamp `json:"data"`
  707. }
  708. if err := json.Unmarshal(bs, &data); err != nil {
  709. t.Logf("json.Unmarshal() failed: %s", err)
  710. }
  711. assert.Zero(t, data.Code)
  712. assert.NotZero(t, data.Ts.Now)
  713. assert.NotZero(t, data.TTL)
  714. return nil
  715. },
  716. },
  717. "/null-json": {
  718. "GET": func(bs []byte) error {
  719. res := map[string]interface{}{}
  720. if err := json.Unmarshal(bs, &res); err != nil {
  721. t.Logf("json.Unmarshal() failed: %s", err)
  722. }
  723. if _, ok := res["data"]; ok {
  724. t.Errorf("Field `data` should be omitted")
  725. }
  726. return nil
  727. },
  728. },
  729. "/xml": {
  730. "GET": func(bs []byte) error {
  731. var ts Timestamp
  732. if err := xml.Unmarshal(bs, &ts); err != nil {
  733. t.Logf("xml.Unmarshal() failed: %s", err)
  734. }
  735. if ts.Now == 0 {
  736. return fmt.Errorf("Timestamp.Now field cannot be zero: %+v", ts)
  737. }
  738. return nil
  739. },
  740. },
  741. "/bytes": {
  742. "GET": func(bs []byte) error {
  743. respStr := string(bs)
  744. oriContent := string(ByteContent)
  745. if respStr != oriContent {
  746. return fmt.Errorf("Bytes response not expected: %s != %s", respStr, oriContent)
  747. }
  748. return nil
  749. },
  750. },
  751. "/json-map": {
  752. "GET": func(bs []byte) error {
  753. var data struct {
  754. Code int `json:"code"`
  755. Tid int `json:"tid"`
  756. Message string `json:"message"`
  757. }
  758. if err := json.Unmarshal(bs, &data); err != nil {
  759. t.Logf("json.Unmarshal() failed: %s", err)
  760. }
  761. if data.Tid != 1 || data.Code != 0 || data.Message != "0" {
  762. return fmt.Errorf("Invalid respones: %+v", data)
  763. }
  764. return nil
  765. },
  766. },
  767. }
  768. contentTypeTest := map[string]string{
  769. "/json": "application/json; charset=utf-8",
  770. "/xml": "application/xml; charset=utf-8",
  771. "/bytes": "text/html",
  772. "/json-map": "application/json; charset=utf-8",
  773. "/null-json": "application/json; charset=utf-8",
  774. }
  775. c := &http.Client{}
  776. for path := range bodyTestCase {
  777. for method := range bodyTestCase[path] {
  778. validator := bodyTestCase[path][method]
  779. expHeader := contentTypeTest[path]
  780. req, err := http.NewRequest(method, uri(SockAddr, path), nil)
  781. if err != nil {
  782. t.Fatalf("Failed to build request: %s", err)
  783. }
  784. resp, err := c.Do(req)
  785. if err != nil {
  786. t.Fatalf("Failed to send request: %s", err)
  787. }
  788. defer resp.Body.Close()
  789. if resp.StatusCode != http.StatusOK {
  790. t.Errorf("http.%s(%s) get error code: %d", method, path, resp.StatusCode)
  791. }
  792. bs, err := ioutil.ReadAll(resp.Body)
  793. if err != nil {
  794. t.Errorf("ioutil.ReadAll() failed: %s", err)
  795. }
  796. if ct := resp.Header.Get("Content-Type"); ct != expHeader {
  797. t.Errorf("Unexpected content-type header on path `%s`: expected %s got %s", path, expHeader, ct)
  798. }
  799. if err := validator(bs); err != nil {
  800. t.Errorf("Failed to validate request to `%s %s`: %s", method, path, err)
  801. }
  802. }
  803. }
  804. }
  805. func TestRedirect(t *testing.T) {
  806. c := &http.Client{
  807. CheckRedirect: func(req *http.Request, via []*http.Request) error {
  808. req.Header["Referer"] = []string{"http://www.bilibili.com/"}
  809. return nil
  810. },
  811. }
  812. req, err := http.NewRequest("GET", uri(SockAddr, "/redirect"), nil)
  813. if err != nil {
  814. t.Fatalf("Failed to build request: %s", err)
  815. }
  816. resp, err := c.Do(req)
  817. if err != nil {
  818. t.Fatalf("Failed to send request: %s", err)
  819. }
  820. defer resp.Body.Close()
  821. if resp.StatusCode != http.StatusOK {
  822. t.Errorf("Redirect test filed: %d", resp.StatusCode)
  823. }
  824. bs, err := ioutil.ReadAll(resp.Body)
  825. if err != nil {
  826. t.Errorf("ioutil.ReadAll() failed: %s", err)
  827. }
  828. respStr := string(bs)
  829. oriContent := string(ByteContent)
  830. if respStr != oriContent {
  831. t.Errorf("Bytes response not expected: %s != %s", respStr, oriContent)
  832. }
  833. }
  834. func TestCORSPreflight(t *testing.T) {
  835. once.Do(startServer)
  836. origin := "ccc.bilibili.com"
  837. c := &http.Client{}
  838. req, err := http.NewRequest("OPTIONS", uri(SockAddr, "/get"), nil)
  839. if err != nil {
  840. t.Fatalf("Failed to build request: %s", err)
  841. }
  842. req.Header.Set("Referer", "http://www.bilibili.com/")
  843. req.Header.Set("Origin", origin)
  844. resp, err := c.Do(req)
  845. if err != nil {
  846. t.Fatalf("Failed to send request: %s", err)
  847. }
  848. defer resp.Body.Close()
  849. if resp.StatusCode != http.StatusOK {
  850. t.Errorf("CORS preflight request status code unexpected: %d", resp.StatusCode)
  851. }
  852. preflightHeaders := map[string]string{
  853. "Access-Control-Allow-Origin": origin,
  854. "Access-Control-Allow-Credentials": "true",
  855. "Access-Control-Allow-Methods": "GET,POST",
  856. "Access-Control-Allow-Headers": "Origin,Content-Length,Content-Type",
  857. }
  858. for k, v := range preflightHeaders {
  859. if hv := resp.Header.Get(k); hv != v {
  860. t.Errorf("Unexpected header %s: %s != %s", k, hv, v)
  861. }
  862. }
  863. varys := map[string]int{
  864. "Origin": 0,
  865. "Access-Control-Request-Method": 0,
  866. "Access-Control-Request-Headers": 0,
  867. }
  868. reqVarys := make(map[string]int)
  869. rv := resp.Header["Vary"]
  870. for _, v := range rv {
  871. reqVarys[v] = 0
  872. }
  873. for v := range varys {
  874. if _, ok := reqVarys[v]; !ok {
  875. t.Errorf("%s is missed in Vary", v)
  876. }
  877. }
  878. }
  879. func TestCORSNormal(t *testing.T) {
  880. once.Do(startServer)
  881. origin := "ccc.bilibili.com"
  882. c := &http.Client{}
  883. req, err := http.NewRequest("GET", uri(SockAddr, "/get"), nil)
  884. if err != nil {
  885. t.Fatalf("Failed to build request: %s", err)
  886. }
  887. req.Header.Set("Referer", "http://www.bilibili.com/")
  888. req.Header.Set("Origin", origin)
  889. resp, err := c.Do(req)
  890. if err != nil {
  891. t.Fatalf("Failed to send request: %s", err)
  892. }
  893. defer resp.Body.Close()
  894. normalHeaders := map[string]string{
  895. "Access-Control-Allow-Origin": origin,
  896. "Access-Control-Allow-Credentials": "true",
  897. "Access-Control-Allow-Methods": "GET,POST",
  898. }
  899. for k, v := range normalHeaders {
  900. if hv := resp.Header.Get(k); hv != v {
  901. t.Errorf("Unexpected header %s: %s != %s", k, hv, v)
  902. }
  903. }
  904. }
  905. func TestJSONP(t *testing.T) {
  906. once.Do(startServer)
  907. origin := "ccc.bilibili.com"
  908. r := regexp.MustCompile(`onsuccess\((.*)\)`)
  909. c := &http.Client{}
  910. req, err := http.NewRequest("GET", uri(SockAddr, "/json?cross_domain=true&jsonp=jsonp&callback=onsuccess"), nil)
  911. if err != nil {
  912. t.Fatalf("Failed to build request: %s", err)
  913. }
  914. req.Header.Set("Referer", "http://www.bilibili.com/")
  915. req.Header.Set("Origin", origin)
  916. resp, err := c.Do(req)
  917. if err != nil {
  918. t.Fatalf("Failed to send request: %s", err)
  919. }
  920. defer resp.Body.Close()
  921. bs, err := ioutil.ReadAll(resp.Body)
  922. if err != nil {
  923. t.Errorf("ioutil.ReadAll() failed: %s", err)
  924. }
  925. matched := r.FindSubmatch(bs)
  926. if matched == nil {
  927. t.Errorf("Response not matched pattern: %s", r)
  928. }
  929. var data struct {
  930. Code int `json:"code"`
  931. Ts *Timestamp `json:"data"`
  932. }
  933. if err := json.Unmarshal(matched[1], &data); err != nil {
  934. t.Logf("json.Unmarshal() failed: %s", err)
  935. }
  936. if data.Code != 0 || data.Ts.Now == 0 {
  937. t.Errorf("Request should succeed but got blocked with code(%d) or Timestamp.Now field cannot be zero: %+v",
  938. data.Code, data)
  939. }
  940. }
  941. func TestCORSFailed(t *testing.T) {
  942. once.Do(startServer)
  943. c := &http.Client{}
  944. req, err := http.NewRequest("GET", uri(SockAddr, "/json?cross_domain=true&jsonp=jsonp&callback=onsuccess"), nil)
  945. if err != nil {
  946. t.Fatalf("Failed to build request: %s", err)
  947. }
  948. req.Header.Set("Referer", "http://www.bilibili2.com/")
  949. req.Header.Set("Origin", "ccc.bilibili2.com")
  950. resp, err := c.Do(req)
  951. if err != nil {
  952. t.Fatalf("Failed to send request: %s", err)
  953. }
  954. defer resp.Body.Close()
  955. if resp.StatusCode == 200 {
  956. t.Errorf("This request should be blocked, but got status %d", resp.StatusCode)
  957. }
  958. }
  959. func TestCSRF(t *testing.T) {
  960. once.Do(startServer)
  961. allowed := []string{
  962. "http://www.bilibili.com/",
  963. "http://www.biligame.com/",
  964. "http://www.im9.com/",
  965. "http://www.acg.tv/",
  966. "http://www.hdslb.com/",
  967. "http://www.bilibili.co/",
  968. // should match by appid
  969. "https://servicewechat.com/wx7564fd5313d24844/devtools/page-frame.html",
  970. "http://servicewechat.com/wx7564fd5313d24844/",
  971. "http://servicewechat.com/wx7564fd5313d24844",
  972. "http://servicewechat.com/wx618ca8c24bf06c33",
  973. // "http://bilibili.co/",
  974. // "http://hdslb.com/",
  975. // "http://acg.tv/",
  976. // "http://im9.com/",
  977. // "http://biligame.com/",
  978. // "http://bilibili.com/",
  979. }
  980. notAllowed := []string{
  981. "http://www.bilibili2.com/",
  982. "http://www.biligame2.com/",
  983. "http://www.im92.com/",
  984. "http://www.acg2.tv/",
  985. "http://www.hdslb2.com/",
  986. "http://servicewechat.com/",
  987. "http://servicewechat.com/wx7564fd5313d24842",
  988. "http://servicewechat.com/wx618ca8c24bf06c34",
  989. }
  990. c := &http.Client{}
  991. for _, r := range allowed {
  992. req, err := http.NewRequest("GET", uri(SockAddr, "/json"), nil)
  993. assert.Nil(t, err)
  994. req.Header.Set("Referer", r)
  995. resp, err := c.Do(req)
  996. assert.Nil(t, err)
  997. resp.Body.Close()
  998. assert.Equal(t, 200, resp.StatusCode)
  999. }
  1000. for _, r := range notAllowed {
  1001. req, err := http.NewRequest("GET", uri(SockAddr, "/json"), nil)
  1002. assert.Nil(t, err)
  1003. req.Header.Set("Referer", r)
  1004. resp, err := c.Do(req)
  1005. assert.Nil(t, err)
  1006. resp.Body.Close()
  1007. assert.Equal(t, 403, resp.StatusCode)
  1008. }
  1009. req, err := http.NewRequest("GET", uri(SockAddr, "/json"), nil)
  1010. assert.Nil(t, err)
  1011. resp, err := c.Do(req)
  1012. assert.Nil(t, err)
  1013. resp.Body.Close()
  1014. assert.Equal(t, 200, resp.StatusCode)
  1015. req, err = http.NewRequest("GET", uri(SockAddr, "/json?callback=123&jsonp=jsonp"), nil)
  1016. assert.Nil(t, err)
  1017. resp, err = c.Do(req)
  1018. assert.Nil(t, err)
  1019. resp.Body.Close()
  1020. assert.Equal(t, 403, resp.StatusCode)
  1021. req, err = http.NewRequest("GET", uri(SockAddr, "/json?cross_domain=123"), nil)
  1022. assert.Nil(t, err)
  1023. resp, err = c.Do(req)
  1024. assert.Nil(t, err)
  1025. resp.Body.Close()
  1026. assert.Equal(t, 403, resp.StatusCode)
  1027. }
  1028. func TestOnError(t *testing.T) {
  1029. once.Do(startServer)
  1030. c := &http.Client{}
  1031. resp, err := c.Get(uri(SockAddr, "/err"))
  1032. if err != nil {
  1033. t.Fatalf("Failed to send request: %s", err)
  1034. }
  1035. defer resp.Body.Close()
  1036. bs, err := ioutil.ReadAll(resp.Body)
  1037. if err != nil {
  1038. t.Errorf("ioutil.ReadAll() failed: %s", err)
  1039. }
  1040. var data struct {
  1041. Code int `json:"code"`
  1042. Ts *Timestamp `json:"data"`
  1043. }
  1044. if err := json.Unmarshal(bs, &data); err != nil {
  1045. t.Logf("json.Unmarshal() failed: %s", err)
  1046. }
  1047. if data.Code != ecode.ServerErr.Code() {
  1048. t.Errorf("Error code is not expected: %d != %d", data.Code, ecode.ServerErr.Code())
  1049. }
  1050. }
  1051. func TestRecovery(t *testing.T) {
  1052. once.Do(startServer)
  1053. c := &http.Client{}
  1054. resp, err := c.Get(uri(SockAddr, "/panic"))
  1055. if err != nil {
  1056. t.Fatalf("Failed to send request: %s", err)
  1057. }
  1058. if resp.StatusCode != http.StatusInternalServerError {
  1059. t.Fatalf("Expect status code 500 get %d, maybe recovery not working as expected", resp.StatusCode)
  1060. }
  1061. }
  1062. func TestGlobalTimeout(t *testing.T) {
  1063. once.Do(startServer)
  1064. t.Run("Should timeout by default", func(t *testing.T) {
  1065. c := &http.Client{}
  1066. req, err := http.NewRequest("GET", uri(SockAddr, "/timeout"), nil)
  1067. assert.Nil(t, err)
  1068. start := time.Now()
  1069. resp, err := c.Do(req)
  1070. assert.Nil(t, err)
  1071. assert.Equal(t, 200, resp.StatusCode)
  1072. assert.InDelta(t, float64(time.Second*2), float64(time.Since(start)), float64(time.Second))
  1073. })
  1074. t.Run("Should timeout by delivered", func(t *testing.T) {
  1075. c := &http.Client{}
  1076. req, err := http.NewRequest("GET", uri(SockAddr, "/timeout"), nil)
  1077. assert.Nil(t, err)
  1078. td := int64(time.Second / time.Millisecond)
  1079. req.Header.Set(_httpHeaderTimeout, strconv.FormatInt(td, 10))
  1080. start := time.Now()
  1081. resp, err := c.Do(req)
  1082. assert.Nil(t, err)
  1083. assert.Equal(t, 200, resp.StatusCode)
  1084. assert.InDelta(t, float64(time.Second), float64(time.Since(start)), float64(time.Second))
  1085. })
  1086. t.Run("Should not timeout by delivered", func(t *testing.T) {
  1087. c := &http.Client{}
  1088. req, err := http.NewRequest("GET", uri(SockAddr, "/timeout"), nil)
  1089. assert.Nil(t, err)
  1090. td := int64(time.Second * 10 / time.Millisecond)
  1091. req.Header.Set(_httpHeaderTimeout, strconv.FormatInt(td, 10))
  1092. start := time.Now()
  1093. resp, err := c.Do(req)
  1094. assert.Nil(t, err)
  1095. assert.Equal(t, 200, resp.StatusCode)
  1096. assert.InDelta(t, float64(time.Second*2), float64(time.Since(start)), float64(time.Second))
  1097. })
  1098. t.Run("Should timeout by method config", func(t *testing.T) {
  1099. c := &http.Client{}
  1100. req, err := http.NewRequest("GET", uri(SockAddr, "/timeout-from-method-config"), nil)
  1101. assert.Nil(t, err)
  1102. start := time.Now()
  1103. resp, err := c.Do(req)
  1104. assert.Nil(t, err)
  1105. assert.Equal(t, 200, resp.StatusCode)
  1106. assert.InDelta(t, float64(time.Second*3), float64(time.Since(start)), float64(time.Second))
  1107. })
  1108. }
  1109. func TestServerConfigReload(t *testing.T) {
  1110. engine := Default()
  1111. setupHandler(engine)
  1112. engine.lock.RLock()
  1113. startTm := engine.conf.Timeout
  1114. engine.lock.RUnlock()
  1115. toTm := startTm * 5
  1116. wg := &sync.WaitGroup{}
  1117. closed := make(chan struct{})
  1118. go func() {
  1119. if err := engine.Run(AdHocSockAddr); err != nil {
  1120. if errors.Cause(err) == http.ErrServerClosed {
  1121. t.Logf("Server stopped due to shutting down command")
  1122. } else {
  1123. t.Errorf("Failed to serve with tls: %s", err)
  1124. }
  1125. }
  1126. closed <- struct{}{}
  1127. }()
  1128. time.Sleep(time.Second)
  1129. clientNum := 20
  1130. for i := 0; i < clientNum; i++ {
  1131. wg.Add(1)
  1132. go func() {
  1133. defer wg.Done()
  1134. c := &http.Client{}
  1135. resp, err := c.Get(uri(AdHocSockAddr, "/get"))
  1136. if err != nil {
  1137. assert.Nil(t, err)
  1138. return
  1139. }
  1140. assert.Equal(t, http.StatusOK, resp.StatusCode)
  1141. }()
  1142. }
  1143. for i := 2; i < clientNum; i++ {
  1144. wg.Add(1)
  1145. conf := &ServerConfig{
  1146. Timeout: toTm,
  1147. }
  1148. if i%2 == 0 {
  1149. conf.Timeout = 0
  1150. }
  1151. go func() {
  1152. defer wg.Done()
  1153. err := engine.SetConfig(conf)
  1154. if conf.Timeout <= 0 {
  1155. assert.NotNil(t, err)
  1156. return
  1157. }
  1158. assert.Nil(t, err)
  1159. }()
  1160. }
  1161. wg.Wait()
  1162. engine.lock.RLock()
  1163. endTm := engine.conf.Timeout
  1164. engine.lock.RUnlock()
  1165. assert.NotEqual(t, toTm, startTm)
  1166. assert.Equal(t, toTm, endTm)
  1167. if err := engine.Shutdown(context.TODO()); err != nil {
  1168. assert.Nil(t, err)
  1169. }
  1170. <-closed
  1171. }
  1172. func TestGracefulShutdown(t *testing.T) {
  1173. engine := Default()
  1174. setupHandler(engine)
  1175. closed := make(chan struct{})
  1176. go func() {
  1177. if err := engine.Run(AdHocSockAddr); err != nil {
  1178. if errors.Cause(err) == http.ErrServerClosed {
  1179. t.Logf("Server stopped due to shutting down command")
  1180. } else {
  1181. t.Errorf("Failed to serve with tls: %s", err)
  1182. }
  1183. }
  1184. closed <- struct{}{}
  1185. }()
  1186. time.Sleep(time.Second)
  1187. clientNum := 10
  1188. wg := &sync.WaitGroup{}
  1189. for i := 0; i < clientNum; i++ {
  1190. wg.Add(1)
  1191. go func() {
  1192. defer wg.Done()
  1193. c := &http.Client{}
  1194. resp, err := c.Get(uri(AdHocSockAddr, "/sleep5"))
  1195. if err != nil {
  1196. t.Error(err)
  1197. return
  1198. }
  1199. if resp.StatusCode != http.StatusOK {
  1200. t.Errorf("Unexpected status code: %d", resp.StatusCode)
  1201. return
  1202. }
  1203. t.Logf("Request finished at: %v", time.Now())
  1204. }()
  1205. }
  1206. time.Sleep(time.Second)
  1207. t.Logf("Invoke Shutdown method at: %v", time.Now())
  1208. if err := engine.Shutdown(context.TODO()); err != nil {
  1209. t.Fatalf("Failed to shutdown engine: %s", err)
  1210. }
  1211. wg.Wait()
  1212. <-closed
  1213. }
  1214. func TestProtobuf(t *testing.T) {
  1215. once.Do(startServer)
  1216. c := &http.Client{}
  1217. t.Run("On-Success", func(t *testing.T) {
  1218. req, err := http.NewRequest("GET", uri(SockAddr, "/pb"), nil)
  1219. assert.Nil(t, err)
  1220. resp, err := c.Do(req)
  1221. assert.Nil(t, err)
  1222. defer resp.Body.Close()
  1223. assert.Equal(t, resp.StatusCode, http.StatusOK)
  1224. assert.Equal(t, resp.Header.Get("Content-Type"), "application/x-protobuf")
  1225. bs, err := ioutil.ReadAll(resp.Body)
  1226. assert.Nil(t, err)
  1227. d := &render.PB{}
  1228. err = proto.Unmarshal(bs, d)
  1229. assert.Nil(t, err)
  1230. assert.Equal(t, int(d.Code), 0)
  1231. assert.NotNil(t, d.Data)
  1232. tt := &tests.Time{}
  1233. err = proto.Unmarshal(d.Data.Value, tt)
  1234. assert.Nil(t, err)
  1235. assert.NotZero(t, tt.Now)
  1236. })
  1237. t.Run("On-Error", func(t *testing.T) {
  1238. req, err := http.NewRequest("GET", uri(SockAddr, "/pb-error"), nil)
  1239. assert.Nil(t, err)
  1240. resp, err := c.Do(req)
  1241. assert.Nil(t, err)
  1242. defer resp.Body.Close()
  1243. assert.Equal(t, resp.StatusCode, http.StatusOK)
  1244. assert.Equal(t, resp.Header.Get("Content-Type"), "application/x-protobuf")
  1245. bs, err := ioutil.ReadAll(resp.Body)
  1246. assert.Nil(t, err)
  1247. d := &render.PB{}
  1248. err = proto.Unmarshal(bs, d)
  1249. assert.Nil(t, err)
  1250. assert.Equal(t, int(d.Code), ecode.RequestErr.Code())
  1251. })
  1252. t.Run("On-NilData-NilErr", func(t *testing.T) {
  1253. req, err := http.NewRequest("GET", uri(SockAddr, "/pb-nildata-nilerr"), nil)
  1254. assert.Nil(t, err)
  1255. resp, err := c.Do(req)
  1256. assert.Nil(t, err)
  1257. defer resp.Body.Close()
  1258. assert.Equal(t, resp.StatusCode, http.StatusOK)
  1259. assert.Equal(t, resp.Header.Get("Content-Type"), "application/x-protobuf")
  1260. bs, err := ioutil.ReadAll(resp.Body)
  1261. assert.Nil(t, err)
  1262. d := &render.PB{}
  1263. err = proto.Unmarshal(bs, d)
  1264. assert.Nil(t, err)
  1265. assert.Equal(t, int(d.Code), 0)
  1266. })
  1267. t.Run("On-Data-Err", func(t *testing.T) {
  1268. req, err := http.NewRequest("GET", uri(SockAddr, "/pb-data-err"), nil)
  1269. assert.Nil(t, err)
  1270. resp, err := c.Do(req)
  1271. assert.Nil(t, err)
  1272. defer resp.Body.Close()
  1273. assert.Equal(t, resp.StatusCode, http.StatusOK)
  1274. assert.Equal(t, resp.Header.Get("Content-Type"), "application/x-protobuf")
  1275. bs, err := ioutil.ReadAll(resp.Body)
  1276. assert.Nil(t, err)
  1277. d := &render.PB{}
  1278. err = proto.Unmarshal(bs, d)
  1279. assert.Nil(t, err)
  1280. assert.Equal(t, int(d.Code), ecode.RequestErr.Code())
  1281. })
  1282. }
  1283. func TestBind(t *testing.T) {
  1284. once.Do(startServer)
  1285. c := &http.Client{}
  1286. req, err := http.NewRequest("GET", uri(SockAddr, "/bind?mids=2,3,4&title=hello&content=world&cid=8"), nil)
  1287. if err != nil {
  1288. t.Fatalf("Failed to build request: %s", err)
  1289. }
  1290. resp, err := c.Do(req)
  1291. if err != nil {
  1292. t.Fatalf("Failed to send request: %s", err)
  1293. }
  1294. assert.Equal(t, resp.StatusCode, 200)
  1295. bs, err := ioutil.ReadAll(resp.Body)
  1296. assert.NoError(t, err)
  1297. resp.Body.Close()
  1298. var p struct {
  1299. Code int `json:"code"`
  1300. Data *Archive `json:"data"`
  1301. }
  1302. if err := json.Unmarshal(bs, &p); err != nil {
  1303. t.Fatalf("Failed to json.Unmarshal: %v", resp.StatusCode)
  1304. }
  1305. assert.Equal(t, p.Code, 0)
  1306. assert.Equal(t, []int64{2, 3, 4}, p.Data.Mids)
  1307. assert.Equal(t, "hello", p.Data.Title)
  1308. assert.Equal(t, "world", p.Data.Content)
  1309. assert.Equal(t, 8, p.Data.Cid)
  1310. }
  1311. func TestBindWith(t *testing.T) {
  1312. once.Do(startServer)
  1313. a := &Archive{
  1314. Mids: []int64{2, 3, 4},
  1315. Title: "hello",
  1316. Content: "world",
  1317. Cid: 8,
  1318. }
  1319. d, err := json.Marshal(a)
  1320. if err != nil {
  1321. t.Fatalf("Failed to json.Marshal: %v", err)
  1322. }
  1323. c := &http.Client{}
  1324. req, err := http.NewRequest("POST", uri(SockAddr, "/bindwith"), bytes.NewBuffer(d))
  1325. if err != nil {
  1326. t.Fatalf("Failed to build request: %s", err)
  1327. }
  1328. resp, err := c.Do(req)
  1329. if err != nil {
  1330. t.Fatalf("Failed to send request: %s", err)
  1331. }
  1332. assert.Equal(t, resp.StatusCode, 200)
  1333. bs, err := ioutil.ReadAll(resp.Body)
  1334. assert.NoError(t, err)
  1335. resp.Body.Close()
  1336. var p struct {
  1337. Code int `json:"code"`
  1338. Data *Archive `json:"data"`
  1339. }
  1340. if err := json.Unmarshal(bs, &p); err != nil {
  1341. t.Fatalf("Failed to json.Unmarshal: %v", resp.StatusCode)
  1342. }
  1343. assert.Equal(t, p.Code, 0)
  1344. assert.Equal(t, a.Mids, p.Data.Mids)
  1345. assert.Equal(t, a.Title, p.Data.Title)
  1346. assert.Equal(t, a.Content, p.Data.Content)
  1347. assert.Equal(t, a.Cid, p.Data.Cid)
  1348. }
  1349. func TestMethodNotAllowed(t *testing.T) {
  1350. once.Do(startServer)
  1351. resp, err := http.Get(uri(SockAddr, "/post"))
  1352. assert.NoError(t, err)
  1353. bs, err := ioutil.ReadAll(resp.Body)
  1354. resp.Body.Close()
  1355. assert.NoError(t, err)
  1356. assert.Equal(t, 405, resp.StatusCode)
  1357. assert.Equal(t, http.StatusText(405), strings.TrimSpace(string(bs)))
  1358. }
  1359. func TestDevice(t *testing.T) {
  1360. testDevice(t, "/device")
  1361. }
  1362. func TestDeviceMeta(t *testing.T) {
  1363. testDevice(t, "/device-from-meta")
  1364. }
  1365. func testDevice(t *testing.T, path string) {
  1366. once.Do(startServer)
  1367. req, err := http.NewRequest("GET", uri(SockAddr, path), nil)
  1368. assert.NoError(t, err)
  1369. assert.NotNil(t, req)
  1370. req.Header.Set("Buvid", "9346b9ca66dangerous4764eede8bb2")
  1371. req.AddCookie(&http.Cookie{Name: "buvid3", Value: "25213BD4-841C-449F-8BBF-B96B58A8Fdangerousinfoc"})
  1372. req.AddCookie(&http.Cookie{Name: "sid", Value: "70***dpi"})
  1373. query := req.URL.Query()
  1374. query.Set("build", "6280")
  1375. query.Set("device", "phone")
  1376. query.Set("mobi_app", "iphone")
  1377. query.Set("platform", "ios")
  1378. query.Set("channel", "appstore")
  1379. req.URL.RawQuery = query.Encode()
  1380. resp, err := http.DefaultClient.Do(req)
  1381. assert.NoError(t, err)
  1382. assert.NotNil(t, resp)
  1383. assert.Equal(t, 200, resp.StatusCode)
  1384. defer resp.Body.Close()
  1385. rdev := new(DevResp)
  1386. bs, err := ioutil.ReadAll(resp.Body)
  1387. assert.NoError(t, err)
  1388. assert.NoError(t, json.Unmarshal(bs, rdev))
  1389. dev := rdev.Data
  1390. assert.Equal(t, "70***dpi", dev.Sid)
  1391. assert.Equal(t, int64(6280), dev.Build)
  1392. assert.Equal(t, "phone", dev.Device)
  1393. assert.Equal(t, "iphone", dev.RawMobiApp)
  1394. assert.Equal(t, "ios", dev.RawPlatform)
  1395. assert.Equal(t, "appstore", dev.Channel)
  1396. assert.Equal(t, "9346b9ca66dangerous4764eede8bb2", dev.Buvid)
  1397. assert.Equal(t, "25213BD4-841C-449F-8BBF-B96B58A8Fdangerousinfoc", dev.Buvid3)
  1398. assert.Equal(t, PlatIPhone, dev.Plat())
  1399. assert.Equal(t, false, dev.IsAndroid())
  1400. assert.Equal(t, true, dev.IsIOS())
  1401. assert.Equal(t, false, dev.IsOverseas())
  1402. assert.Equal(t, false, dev.InvalidChannel("*"))
  1403. assert.Equal(t, false, dev.InvalidChannel("appstore"))
  1404. assert.Equal(t, "iphone", dev.MobiApp())
  1405. assert.Equal(t, "iphone", dev.MobiAPPBuleChange())
  1406. dev.RawPlatform = "android"
  1407. dev.RawMobiApp = "android"
  1408. dev.Channel = "test.channel"
  1409. assert.Equal(t, true, dev.InvalidChannel("test.channel2"))
  1410. }
  1411. func TestRemoteIPFromContext(t *testing.T) {
  1412. once.Do(startServer)
  1413. ip := "192.168.22.33"
  1414. req, err := http.NewRequest("GET", uri(SockAddr, "/remote-ip"), nil)
  1415. assert.NoError(t, err)
  1416. assert.NotNil(t, req)
  1417. req.Header.Set(_httpHeaderRemoteIP, ip)
  1418. resp, err := http.DefaultClient.Do(req)
  1419. assert.NoError(t, err)
  1420. assert.NotNil(t, resp)
  1421. defer resp.Body.Close()
  1422. bs, err := ioutil.ReadAll(resp.Body)
  1423. assert.NoError(t, err)
  1424. var response struct {
  1425. Data string `json:"data"`
  1426. }
  1427. err = json.Unmarshal(bs, &response)
  1428. assert.NoError(t, err)
  1429. assert.Equal(t, ip, response.Data)
  1430. }
  1431. func TestNewServerMiddleware(t *testing.T) {
  1432. e := DefaultServer(nil)
  1433. // should contain 4 default handlers
  1434. assert.Len(t, e.RouterGroup.Handlers, 5)
  1435. }
  1436. func TestMethodConfig(t *testing.T) {
  1437. e := New()
  1438. tg := e.Group("/timeout").SetMethodConfig(&MethodConfig{Timeout: xtime.Duration(time.Second * 10)})
  1439. tg.GET("/default", func(ctx *Context) {})
  1440. e.GET("/timeout/5s", func(ctx *Context) {})
  1441. e.SetMethodConfig("/timeout/5s", &MethodConfig{Timeout: xtime.Duration(time.Second * 5)})
  1442. pc := e.methodConfig("/timeout/default")
  1443. assert.NotNil(t, pc)
  1444. assert.Equal(t, xtime.Duration(time.Second*10), pc.Timeout)
  1445. pc = e.methodConfig("/timeout/5s")
  1446. assert.NotNil(t, pc)
  1447. assert.Equal(t, xtime.Duration(time.Second*5), pc.Timeout)
  1448. }
  1449. func BenchmarkServer(b *testing.B) {
  1450. startServer()
  1451. defer shutdown()
  1452. b.ResetTimer()
  1453. b.RunParallel(func(pb *testing.PB) {
  1454. for pb.Next() {
  1455. resp, err := http.Get(uri(SockAddr, "/bench"))
  1456. if err != nil {
  1457. b.Errorf("HTTPServ: get error(%v)", err)
  1458. continue
  1459. }
  1460. if resp.StatusCode != http.StatusOK {
  1461. b.Errorf("HTTPServ: get error status code:%d", resp.StatusCode)
  1462. }
  1463. resp.Body.Close()
  1464. }
  1465. })
  1466. }
  1467. func TestServerWithMirror(t *testing.T) {
  1468. var response struct {
  1469. Data string `json:"data"`
  1470. }
  1471. //sonce.Do(startMirrorServer)
  1472. client := &http.Client{}
  1473. reqest, _ := http.NewRequest("GET", "http://localhost:18090/mirrortest", nil)
  1474. reqest.Header.Add("x1-bilispy-mirror", "1")
  1475. resp, err := client.Do(reqest)
  1476. assert.NoError(t, err)
  1477. assert.NotNil(t, resp)
  1478. assert.Equal(t, 200, resp.StatusCode)
  1479. bs, _ := ioutil.ReadAll(resp.Body)
  1480. err = json.Unmarshal(bs, &response)
  1481. assert.NoError(t, err)
  1482. assert.Equal(t, "true", response.Data)
  1483. resp.Body.Close()
  1484. reqest, _ = http.NewRequest("GET", "http://localhost:18090/mirrortest", nil)
  1485. reqest.Header.Add("x1-bilispy-mirror", "0")
  1486. resp, err = client.Do(reqest)
  1487. assert.NoError(t, err)
  1488. assert.NotNil(t, resp)
  1489. assert.Equal(t, 200, resp.StatusCode)
  1490. bs, _ = ioutil.ReadAll(resp.Body)
  1491. err = json.Unmarshal(bs, &response)
  1492. assert.NoError(t, err)
  1493. assert.Equal(t, "false", response.Data)
  1494. resp.Body.Close()
  1495. reqest, _ = http.NewRequest("GET", "http://localhost:18090/mirrortest", nil)
  1496. reqest.Header.Add("x1-bilispy-mirror", "xxxxxxxxxx")
  1497. resp, err = client.Do(reqest)
  1498. assert.NoError(t, err)
  1499. assert.NotNil(t, resp)
  1500. assert.Equal(t, 200, resp.StatusCode)
  1501. bs, _ = ioutil.ReadAll(resp.Body)
  1502. err = json.Unmarshal(bs, &response)
  1503. assert.NoError(t, err)
  1504. assert.Equal(t, "false", response.Data)
  1505. resp.Body.Close()
  1506. reqest, _ = http.NewRequest("GET", "http://localhost:18090/mirrortest", nil)
  1507. resp, err = client.Do(reqest)
  1508. assert.NoError(t, err)
  1509. assert.NotNil(t, resp)
  1510. assert.Equal(t, 200, resp.StatusCode)
  1511. bs, _ = ioutil.ReadAll(resp.Body)
  1512. err = json.Unmarshal(bs, &response)
  1513. assert.NoError(t, err)
  1514. assert.Equal(t, "false", response.Data)
  1515. resp.Body.Close()
  1516. }
  1517. func TestEngineInject(t *testing.T) {
  1518. once.Do(startServer)
  1519. client := &http.Client{}
  1520. resp, err := client.Get(uri(SockAddr, "/inject/index"))
  1521. assert.NoError(t, err)
  1522. defer resp.Body.Close()
  1523. bs, err := ioutil.ReadAll(resp.Body)
  1524. assert.NoError(t, err)
  1525. assert.Equal(t, "index-injected", string(bs))
  1526. }
  1527. func TestBiliStatusCode(t *testing.T) {
  1528. once.Do(startServer)
  1529. tests := map[string]int{
  1530. "/group/test/json-status": ecode.MemberBlocked.Code(),
  1531. "/group/test/xml-status": ecode.MemberBlocked.Code(),
  1532. "/group/test/proto-status": ecode.MemberBlocked.Code(),
  1533. "/group/test/json-map-status": ecode.MemberBlocked.Code(),
  1534. }
  1535. client := &http.Client{}
  1536. for path, code := range tests {
  1537. resp, err := client.Get(uri(SockAddr, path))
  1538. assert.NoError(t, err)
  1539. assert.Equal(t, resp.Header.Get("bili-status-code"), strconv.FormatInt(int64(code), 10))
  1540. }
  1541. }