You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

211 lines
4.7 KiB

5 years ago
  1. package govue2
  2. //go-bindata-assetfs --pkg=govue govue-runtime/...
  3. import (
  4. "fmt"
  5. "git.ouxuan.net/3136352472/go-service-template/jsruntime"
  6. "git.ouxuan.net/3136352472/go-service-template/pool"
  7. "github.com/elazarl/go-bindata-assetfs"
  8. "io/ioutil"
  9. "log"
  10. "net/http"
  11. "os"
  12. "path/filepath"
  13. "time"
  14. )
  15. type GoVue struct {
  16. StaticPath string
  17. UseJsPath string
  18. ErrorPage404 string
  19. Resources *assetfs.AssetFS
  20. IsDebugMode bool
  21. jsRuntimePool *pool.JsRuntimePool
  22. CacheSec int64
  23. }
  24. func NewGoVueDefaultConfig(debug bool) (gv *GoVue, err error) {
  25. gv = &GoVue{
  26. Resources: assetFS(),
  27. IsDebugMode: debug,
  28. }
  29. err = gv.initRender(debug)
  30. return
  31. }
  32. func NewGoVue(useJsPath string, staticPath string, debug bool) (gv *GoVue, err error) {
  33. gv = &GoVue{
  34. StaticPath: staticPath,
  35. UseJsPath: useJsPath,
  36. Resources: assetFS(),
  37. IsDebugMode: debug,
  38. }
  39. err = gv.initRender(debug)
  40. return
  41. }
  42. func (gv *GoVue) SetCacheSec(cacheSec int64) {
  43. gv.CacheSec = cacheSec
  44. }
  45. func (gv *GoVue) SetErrorPage404(page string) {
  46. gv.ErrorPage404 = page
  47. }
  48. func SetPoolConfig(config pool.Config) {
  49. pool.DefaultConfig = config
  50. }
  51. func (gv *GoVue) initRender(debug bool) (err error) {
  52. if gv.StaticPath == "" {
  53. gv.StaticPath = filepath.Join(getSelfFilePath(), "static")
  54. }
  55. if gv.UseJsPath == "" {
  56. gv.UseJsPath = filepath.Join(gv.StaticPath, "use.js")
  57. }
  58. headerScript, err := gv.Resources.Asset(filepath.Join("govue-runtime", "header.js"))
  59. if err != nil {
  60. return
  61. }
  62. polyfill, err := gv.Resources.Asset(filepath.Join("govue-runtime", "polyfill.js"))
  63. if err != nil {
  64. return
  65. }
  66. mainScript, err := gv.Resources.Asset(filepath.Join("govue-runtime", "runtime.js"))
  67. if err != nil {
  68. return
  69. }
  70. govueScriptFile := "govue.js"
  71. govueScript, err := gv.Resources.Asset(filepath.Join("govue-runtime", govueScriptFile))
  72. if err != nil {
  73. return
  74. }
  75. gv.jsRuntimePool = pool.NewJsRuntimePool(string(mainScript), gv.UseJsPath, gv.StaticPath, jsruntime.Relys{
  76. jsruntime.Rely{
  77. Src: string(headerScript),
  78. },
  79. jsruntime.Rely{
  80. Src: string(polyfill),
  81. },
  82. jsruntime.Rely{
  83. Src: string(govueScript),
  84. },
  85. }, jsruntime.ModeSync, debug)
  86. return
  87. }
  88. func (gv *GoVue) PoolLog() {
  89. gv.jsRuntimePool.Log()
  90. }
  91. func (gv *GoVue) StartPoolLog() {
  92. go func() {
  93. defer func() {
  94. recover()
  95. log.Println("统计协程异常")
  96. }()
  97. lastidle := 0
  98. lastactive := 0
  99. for {
  100. all, idle, active := gv.jsRuntimePool.NumInfo()
  101. if idle != lastidle || active != lastactive {
  102. fmt.Println("渲染协程数量变动变动:所有:", all, "空闲:", idle, "活动:", active)
  103. }
  104. lastidle = idle
  105. lastactive = active
  106. time.Sleep(time.Second)
  107. }
  108. }()
  109. }
  110. func (gv *GoVue) LoadStaticResources(request *http.Request, goExtDataS ...interface{}) (result []byte, err error) {
  111. cacheKey := fmt.Sprintf("%s|%s", request.URL.Path, request.URL.RawQuery)
  112. if gv.CacheSec > 0 {
  113. html := GetCache(cacheKey)
  114. if html != "" {
  115. //log.Println("加载缓存")
  116. return []byte(html), nil
  117. }
  118. }
  119. //log.Println("非缓存", cacheKey)
  120. var staticDir string
  121. var filePath = request.URL.Path
  122. if gv.StaticPath == "" {
  123. staticDir = filepath.Join(getSelfFilePath(), "static")
  124. } else {
  125. staticDir = gv.StaticPath
  126. }
  127. filePath = filepath.Join(staticDir, filePath)
  128. fi, err := os.Stat(filePath)
  129. if err == nil {
  130. if fi.IsDir() {
  131. defaultPath := []string{"index.html"}
  132. for e := range defaultPath {
  133. path := filepath.Join(filePath, defaultPath[e])
  134. _, err := os.Stat(path)
  135. if err == nil {
  136. filePath = path
  137. break
  138. }
  139. }
  140. }
  141. }
  142. result, err = ioutil.ReadFile(filePath)
  143. if err != nil {
  144. result, err = gv.renderErrPage(404, request, goExtDataS...)
  145. if gv.CacheSec > 0 {
  146. SetCache(cacheKey, string(result), gv.CacheSec)
  147. }
  148. return
  149. }
  150. if filepath.Ext(filePath) != ".html" {
  151. return
  152. }
  153. err = gv.jsRuntimePool.JsRuntimeCall(func(jr *jsruntime.JsRuntime) {
  154. err = jr.Render(filePath, fmt.Sprintf("http://%s%s", request.Host, request.RequestURI), string(result), nil, func(data string) {
  155. result = []byte(data)
  156. if gv.CacheSec > 0 {
  157. SetCache(cacheKey, string(result), gv.CacheSec)
  158. }
  159. })
  160. if err != nil {
  161. result = []byte(err.Error())
  162. }
  163. })
  164. return
  165. }
  166. func (gv *GoVue) renderErrPage(errCode int, request *http.Request, goExtDataS ...interface{}) (result []byte, err error) {
  167. filePath := gv.ErrorPage404
  168. if filePath == "" {
  169. return []byte("页面不存在"), err
  170. }
  171. result, _ = ioutil.ReadFile(filePath)
  172. var goExtData interface{}
  173. if len(goExtDataS) > 0 {
  174. goExtData = goExtDataS[0]
  175. }
  176. err = gv.jsRuntimePool.JsRuntimeCall(func(jr *jsruntime.JsRuntime) {
  177. err = jr.Render(filePath, fmt.Sprintf("http://%s%s", request.Host, request.RequestURI), string(result), goExtData, func(data string) {
  178. result = []byte(data)
  179. })
  180. })
  181. return
  182. }