serve.go 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. /*
  2. Copyright © 2022 NAME HERE <EMAIL ADDRESS>
  3. */
  4. package cmd
  5. import (
  6. "html/template"
  7. "log"
  8. "net/http"
  9. "github.com/spf13/cobra"
  10. "github.com/t0n3/sakuin/web"
  11. )
  12. type fileItem struct {
  13. Name string
  14. Size string
  15. Date string
  16. IsDir bool
  17. Path string
  18. }
  19. type templateVariables struct {
  20. Path []breadcrumb
  21. Files []fileItem
  22. }
  23. type breadcrumb struct {
  24. Name string
  25. Path string
  26. }
  27. var dataDir string
  28. // serveCmd represents the serve command
  29. var serveCmd = &cobra.Command{
  30. Use: "serve",
  31. Short: "Start the HTTP server",
  32. Run: func(cmd *cobra.Command, args []string) {
  33. log.Println("Starting Sakuin HTTP Server")
  34. mux := http.NewServeMux()
  35. mux.Handle("/assets/", web.AssetsHandler("/assets/", "dist"))
  36. mux.HandleFunc("/", serve)
  37. http.ListenAndServe(":3000", mux)
  38. },
  39. }
  40. func init() {
  41. rootCmd.AddCommand(serveCmd)
  42. // Here you will define your flags and configuration settings.
  43. // Cobra supports Persistent Flags which will work for this command
  44. // and all subcommands, e.g.:
  45. // serveCmd.PersistentFlags().String("foo", "", "A help for foo")
  46. // Cobra supports local flags which will only run when this command
  47. // is called directly, e.g.:
  48. // serveCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
  49. }
  50. func serve(w http.ResponseWriter, r *http.Request) {
  51. templateVars := templateVariables{}
  52. // Prepare the template
  53. tmpl, err := template.ParseFS(web.Index, "index.html")
  54. if err != nil {
  55. // Log the detailed error
  56. log.Println(err.Error())
  57. // Return a generic "Internal Server Error" message
  58. http.Error(w, http.StatusText(500), 500)
  59. return
  60. }
  61. // Return file listing in the template
  62. if err := tmpl.ExecuteTemplate(w, "index.html", templateVars); err != nil {
  63. log.Println(err.Error())
  64. http.Error(w, http.StatusText(500), 500)
  65. }
  66. log.Printf("200 - DIR %s\n", "/")
  67. // // Filepath, from the root data dir
  68. // fp := filepath.Join(dataDir, filepath.Clean(r.URL.Path))
  69. // // Cleaned filepath, without the root data dir, used for template rendering purpose
  70. // cfp := strings.Replace(fp, dataDir, "", 1)
  71. // // Return a 404 if the template doesn't exist
  72. // info, err := os.Stat(fp)
  73. // if err != nil {
  74. // if os.IsNotExist(err) {
  75. // http.NotFound(w, r)
  76. // log.Println(fmt.Sprintf("404 - %s", cfp))
  77. // return
  78. // }
  79. // }
  80. // Return a 404 if the request is for a directory
  81. // if info.IsDir() {
  82. // files, err := ioutil.ReadDir(fp)
  83. // if err != nil {
  84. // log.Fatal(err)
  85. // }
  86. // // Init template variables
  87. // tplVars := templateVariables{}
  88. // // Construct the breadcrumb
  89. // path := strings.Split(cfp, "/")
  90. // for len(path) > 0 {
  91. // b := breadcrumb{
  92. // Name: path[len(path)-1],
  93. // Path: strings.Join(path, "/"),
  94. // }
  95. // path = path[:len(path)-1]
  96. // tplVars.Path = append(tplVars.Path, b)
  97. // }
  98. // // Since the breadcrumb built is not very ordered...
  99. // // REVERSE ALL THE THINGS
  100. // for left, right := 0, len(tplVars.Path)-1; left < right; left, right = left+1, right-1 {
  101. // tplVars.Path[left], tplVars.Path[right] = tplVars.Path[right], tplVars.Path[left]
  102. // }
  103. // // Establish list of files in the current directory
  104. // for _, f := range files {
  105. // tplVars.Files = append(tplVars.Files, fileItem{
  106. // Name: f.Name(),
  107. // Size: humanize.Bytes(uint64(f.Size())),
  108. // Date: humanize.Time(f.ModTime()),
  109. // IsDir: f.IsDir(),
  110. // Path: filepath.Join(cfp, filepath.Clean(f.Name())),
  111. // })
  112. // }
  113. // // Prepare the template
  114. // tmpl, err := template.ParseFiles(lp)
  115. // if err != nil {
  116. // // Log the detailed error
  117. // log.Println(err.Error())
  118. // // Return a generic "Internal Server Error" message
  119. // http.Error(w, http.StatusText(500), 500)
  120. // return
  121. // }
  122. // // Return file listing in the template
  123. // if err := tmpl.ExecuteTemplate(w, "layout", tplVars); err != nil {
  124. // log.Println(err.Error())
  125. // http.Error(w, http.StatusText(500), 500)
  126. // }
  127. // log.Println(fmt.Sprintf("200 - DIR %s", cfp))
  128. // return
  129. // }
  130. // if !info.IsDir() {
  131. // http.ServeFile(w, r, fp)
  132. // log.Println(fmt.Sprintf("200 - FILE %s", cfp))
  133. // return
  134. // }
  135. }