app.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366
  1. // Copyright 2014 beego Author. All Rights Reserved.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package beego
  15. import (
  16. "fmt"
  17. "net"
  18. "net/http"
  19. "net/http/fcgi"
  20. "os"
  21. "path"
  22. "time"
  23. "github.com/astaxie/beego/grace"
  24. "github.com/astaxie/beego/logs"
  25. "github.com/astaxie/beego/utils"
  26. )
  27. var (
  28. // BeeApp is an application instance
  29. BeeApp *App
  30. )
  31. func init() {
  32. // create beego application
  33. BeeApp = NewApp()
  34. }
  35. // App defines beego application with a new PatternServeMux.
  36. type App struct {
  37. Handlers *ControllerRegister
  38. Server *http.Server
  39. }
  40. // NewApp returns a new beego application.
  41. func NewApp() *App {
  42. cr := NewControllerRegister()
  43. app := &App{Handlers: cr, Server: &http.Server{}}
  44. return app
  45. }
  46. // Run beego application.
  47. func (app *App) Run() {
  48. addr := BConfig.Listen.HTTPAddr
  49. if BConfig.Listen.HTTPPort != 0 {
  50. addr = fmt.Sprintf("%s:%d", BConfig.Listen.HTTPAddr, BConfig.Listen.HTTPPort)
  51. }
  52. var (
  53. err error
  54. l net.Listener
  55. endRunning = make(chan bool, 1)
  56. )
  57. // run cgi server
  58. if BConfig.Listen.EnableFcgi {
  59. if BConfig.Listen.EnableStdIo {
  60. if err = fcgi.Serve(nil, app.Handlers); err == nil { // standard I/O
  61. logs.Info("Use FCGI via standard I/O")
  62. } else {
  63. logs.Critical("Cannot use FCGI via standard I/O", err)
  64. }
  65. return
  66. }
  67. if BConfig.Listen.HTTPPort == 0 {
  68. // remove the Socket file before start
  69. if utils.FileExists(addr) {
  70. os.Remove(addr)
  71. }
  72. l, err = net.Listen("unix", addr)
  73. } else {
  74. l, err = net.Listen("tcp", addr)
  75. }
  76. if err != nil {
  77. logs.Critical("Listen: ", err)
  78. }
  79. if err = fcgi.Serve(l, app.Handlers); err != nil {
  80. logs.Critical("fcgi.Serve: ", err)
  81. }
  82. return
  83. }
  84. app.Server.Handler = app.Handlers
  85. app.Server.ReadTimeout = time.Duration(BConfig.Listen.ServerTimeOut) * time.Second
  86. app.Server.WriteTimeout = time.Duration(BConfig.Listen.ServerTimeOut) * time.Second
  87. app.Server.ErrorLog = logs.GetLogger("HTTP")
  88. // run graceful mode
  89. if BConfig.Listen.Graceful {
  90. httpsAddr := BConfig.Listen.HTTPSAddr
  91. app.Server.Addr = httpsAddr
  92. if BConfig.Listen.EnableHTTPS {
  93. go func() {
  94. time.Sleep(20 * time.Microsecond)
  95. if BConfig.Listen.HTTPSPort != 0 {
  96. httpsAddr = fmt.Sprintf("%s:%d", BConfig.Listen.HTTPSAddr, BConfig.Listen.HTTPSPort)
  97. app.Server.Addr = httpsAddr
  98. }
  99. server := grace.NewServer(httpsAddr, app.Handlers)
  100. server.Server.ReadTimeout = app.Server.ReadTimeout
  101. server.Server.WriteTimeout = app.Server.WriteTimeout
  102. if err := server.ListenAndServeTLS(BConfig.Listen.HTTPSCertFile, BConfig.Listen.HTTPSKeyFile); err != nil {
  103. logs.Critical("ListenAndServeTLS: ", err, fmt.Sprintf("%d", os.Getpid()))
  104. time.Sleep(100 * time.Microsecond)
  105. endRunning <- true
  106. }
  107. }()
  108. }
  109. if BConfig.Listen.EnableHTTP {
  110. go func() {
  111. server := grace.NewServer(addr, app.Handlers)
  112. server.Server.ReadTimeout = app.Server.ReadTimeout
  113. server.Server.WriteTimeout = app.Server.WriteTimeout
  114. if BConfig.Listen.ListenTCP4 {
  115. server.Network = "tcp4"
  116. }
  117. if err := server.ListenAndServe(); err != nil {
  118. logs.Critical("ListenAndServe: ", err, fmt.Sprintf("%d", os.Getpid()))
  119. time.Sleep(100 * time.Microsecond)
  120. endRunning <- true
  121. }
  122. }()
  123. }
  124. <-endRunning
  125. return
  126. }
  127. // run normal mode
  128. if BConfig.Listen.EnableHTTPS {
  129. go func() {
  130. time.Sleep(20 * time.Microsecond)
  131. if BConfig.Listen.HTTPSPort != 0 {
  132. app.Server.Addr = fmt.Sprintf("%s:%d", BConfig.Listen.HTTPSAddr, BConfig.Listen.HTTPSPort)
  133. } else if BConfig.Listen.EnableHTTP {
  134. BeeLogger.Info("Start https server error, confict with http.Please reset https port")
  135. return
  136. }
  137. logs.Info("https server Running on https://%s", app.Server.Addr)
  138. if err := app.Server.ListenAndServeTLS(BConfig.Listen.HTTPSCertFile, BConfig.Listen.HTTPSKeyFile); err != nil {
  139. logs.Critical("ListenAndServeTLS: ", err)
  140. time.Sleep(100 * time.Microsecond)
  141. endRunning <- true
  142. }
  143. }()
  144. }
  145. if BConfig.Listen.EnableHTTP {
  146. go func() {
  147. app.Server.Addr = addr
  148. logs.Info("http server Running on http://%s", app.Server.Addr)
  149. if BConfig.Listen.ListenTCP4 {
  150. ln, err := net.Listen("tcp4", app.Server.Addr)
  151. if err != nil {
  152. logs.Critical("ListenAndServe: ", err)
  153. time.Sleep(100 * time.Microsecond)
  154. endRunning <- true
  155. return
  156. }
  157. if err = app.Server.Serve(ln); err != nil {
  158. logs.Critical("ListenAndServe: ", err)
  159. time.Sleep(100 * time.Microsecond)
  160. endRunning <- true
  161. return
  162. }
  163. } else {
  164. if err := app.Server.ListenAndServe(); err != nil {
  165. logs.Critical("ListenAndServe: ", err)
  166. time.Sleep(100 * time.Microsecond)
  167. endRunning <- true
  168. }
  169. }
  170. }()
  171. }
  172. <-endRunning
  173. }
  174. // Router adds a patterned controller handler to BeeApp.
  175. // it's an alias method of App.Router.
  176. // usage:
  177. // simple router
  178. // beego.Router("/admin", &admin.UserController{})
  179. // beego.Router("/admin/index", &admin.ArticleController{})
  180. //
  181. // regex router
  182. //
  183. // beego.Router("/api/:id([0-9]+)", &controllers.RController{})
  184. //
  185. // custom rules
  186. // beego.Router("/api/list",&RestController{},"*:ListFood")
  187. // beego.Router("/api/create",&RestController{},"post:CreateFood")
  188. // beego.Router("/api/update",&RestController{},"put:UpdateFood")
  189. // beego.Router("/api/delete",&RestController{},"delete:DeleteFood")
  190. func Router(rootpath string, c ControllerInterface, mappingMethods ...string) *App {
  191. BeeApp.Handlers.Add(rootpath, c, mappingMethods...)
  192. return BeeApp
  193. }
  194. // Include will generate router file in the router/xxx.go from the controller's comments
  195. // usage:
  196. // beego.Include(&BankAccount{}, &OrderController{},&RefundController{},&ReceiptController{})
  197. // type BankAccount struct{
  198. // beego.Controller
  199. // }
  200. //
  201. // register the function
  202. // func (b *BankAccount)Mapping(){
  203. // b.Mapping("ShowAccount" , b.ShowAccount)
  204. // b.Mapping("ModifyAccount", b.ModifyAccount)
  205. //}
  206. //
  207. // //@router /account/:id [get]
  208. // func (b *BankAccount) ShowAccount(){
  209. // //logic
  210. // }
  211. //
  212. //
  213. // //@router /account/:id [post]
  214. // func (b *BankAccount) ModifyAccount(){
  215. // //logic
  216. // }
  217. //
  218. // the comments @router url methodlist
  219. // url support all the function Router's pattern
  220. // methodlist [get post head put delete options *]
  221. func Include(cList ...ControllerInterface) *App {
  222. BeeApp.Handlers.Include(cList...)
  223. return BeeApp
  224. }
  225. // RESTRouter adds a restful controller handler to BeeApp.
  226. // its' controller implements beego.ControllerInterface and
  227. // defines a param "pattern/:objectId" to visit each resource.
  228. func RESTRouter(rootpath string, c ControllerInterface) *App {
  229. Router(rootpath, c)
  230. Router(path.Join(rootpath, ":objectId"), c)
  231. return BeeApp
  232. }
  233. // AutoRouter adds defined controller handler to BeeApp.
  234. // it's same to App.AutoRouter.
  235. // if beego.AddAuto(&MainContorlller{}) and MainController has methods List and Page,
  236. // visit the url /main/list to exec List function or /main/page to exec Page function.
  237. func AutoRouter(c ControllerInterface) *App {
  238. BeeApp.Handlers.AddAuto(c)
  239. return BeeApp
  240. }
  241. // AutoPrefix adds controller handler to BeeApp with prefix.
  242. // it's same to App.AutoRouterWithPrefix.
  243. // if beego.AutoPrefix("/admin",&MainContorlller{}) and MainController has methods List and Page,
  244. // visit the url /admin/main/list to exec List function or /admin/main/page to exec Page function.
  245. func AutoPrefix(prefix string, c ControllerInterface) *App {
  246. BeeApp.Handlers.AddAutoPrefix(prefix, c)
  247. return BeeApp
  248. }
  249. // Get used to register router for Get method
  250. // usage:
  251. // beego.Get("/", func(ctx *context.Context){
  252. // ctx.Output.Body("hello world")
  253. // })
  254. func Get(rootpath string, f FilterFunc) *App {
  255. BeeApp.Handlers.Get(rootpath, f)
  256. return BeeApp
  257. }
  258. // Post used to register router for Post method
  259. // usage:
  260. // beego.Post("/api", func(ctx *context.Context){
  261. // ctx.Output.Body("hello world")
  262. // })
  263. func Post(rootpath string, f FilterFunc) *App {
  264. BeeApp.Handlers.Post(rootpath, f)
  265. return BeeApp
  266. }
  267. // Delete used to register router for Delete method
  268. // usage:
  269. // beego.Delete("/api", func(ctx *context.Context){
  270. // ctx.Output.Body("hello world")
  271. // })
  272. func Delete(rootpath string, f FilterFunc) *App {
  273. BeeApp.Handlers.Delete(rootpath, f)
  274. return BeeApp
  275. }
  276. // Put used to register router for Put method
  277. // usage:
  278. // beego.Put("/api", func(ctx *context.Context){
  279. // ctx.Output.Body("hello world")
  280. // })
  281. func Put(rootpath string, f FilterFunc) *App {
  282. BeeApp.Handlers.Put(rootpath, f)
  283. return BeeApp
  284. }
  285. // Head used to register router for Head method
  286. // usage:
  287. // beego.Head("/api", func(ctx *context.Context){
  288. // ctx.Output.Body("hello world")
  289. // })
  290. func Head(rootpath string, f FilterFunc) *App {
  291. BeeApp.Handlers.Head(rootpath, f)
  292. return BeeApp
  293. }
  294. // Options used to register router for Options method
  295. // usage:
  296. // beego.Options("/api", func(ctx *context.Context){
  297. // ctx.Output.Body("hello world")
  298. // })
  299. func Options(rootpath string, f FilterFunc) *App {
  300. BeeApp.Handlers.Options(rootpath, f)
  301. return BeeApp
  302. }
  303. // Patch used to register router for Patch method
  304. // usage:
  305. // beego.Patch("/api", func(ctx *context.Context){
  306. // ctx.Output.Body("hello world")
  307. // })
  308. func Patch(rootpath string, f FilterFunc) *App {
  309. BeeApp.Handlers.Patch(rootpath, f)
  310. return BeeApp
  311. }
  312. // Any used to register router for all methods
  313. // usage:
  314. // beego.Any("/api", func(ctx *context.Context){
  315. // ctx.Output.Body("hello world")
  316. // })
  317. func Any(rootpath string, f FilterFunc) *App {
  318. BeeApp.Handlers.Any(rootpath, f)
  319. return BeeApp
  320. }
  321. // Handler used to register a Handler router
  322. // usage:
  323. // beego.Handler("/api", func(ctx *context.Context){
  324. // ctx.Output.Body("hello world")
  325. // })
  326. func Handler(rootpath string, h http.Handler, options ...interface{}) *App {
  327. BeeApp.Handlers.Handler(rootpath, h, options...)
  328. return BeeApp
  329. }
  330. // InsertFilter adds a FilterFunc with pattern condition and action constant.
  331. // The pos means action constant including
  332. // beego.BeforeStatic, beego.BeforeRouter, beego.BeforeExec, beego.AfterExec and beego.FinishRouter.
  333. // The bool params is for setting the returnOnOutput value (false allows multiple filters to execute)
  334. func InsertFilter(pattern string, pos int, filter FilterFunc, params ...bool) *App {
  335. BeeApp.Handlers.InsertFilter(pattern, pos, filter, params...)
  336. return BeeApp
  337. }