router.go 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. package main
  2. import (
  3. "notabug.org/apiote/amuse/front"
  4. "notabug.org/apiote/amuse/libamuse"
  5. "notabug.org/apiote/amuse/network"
  6. "notabug.org/apiote/amuse/utils"
  7. "crypto/sha256"
  8. "encoding/base64"
  9. "errors"
  10. "flag"
  11. "fmt"
  12. "io"
  13. "mime"
  14. "net/http"
  15. "os"
  16. //"path/filepath"
  17. "strconv"
  18. "strings"
  19. )
  20. func person(w http.ResponseWriter, r *http.Request) {
  21. acceptLanguages := r.Header.Get("Accept-Language")
  22. etag := r.Header.Get("Etag")
  23. mimetype := strings.Split(r.Header.Get("Accept"), ",")[0]
  24. defer recovery(acceptLanguages, mimetype, w)
  25. path := strings.Split(r.URL.Path[1:], "/")
  26. _, err := strconv.ParseInt(path[1], 10, 64)
  27. if err != nil {
  28. renderError(400, w, err, acceptLanguages, mimetype)
  29. return
  30. } else if len(path) > 2 {
  31. renderError(404, w, nil, acceptLanguages, mimetype)
  32. return
  33. }
  34. person, err := libamuse.ShowPerson(path[1], etag, acceptLanguages, mimetype)
  35. render(person, err, w, acceptLanguages, mimetype)
  36. }
  37. func tvSerie(w http.ResponseWriter, r *http.Request) {
  38. acceptLanguages := r.Header.Get("Accept-Language")
  39. etag := r.Header.Get("Etag")
  40. mimetype := strings.Split(r.Header.Get("Accept"), ",")[0]
  41. defer recovery(acceptLanguages, mimetype, w)
  42. path := strings.Split(r.URL.Path[1:], "/")
  43. _, err := strconv.ParseInt(path[1], 10, 64)
  44. if err != nil {
  45. renderError(400, w, err, acceptLanguages, mimetype)
  46. return
  47. } else if len(path) > 2 {
  48. renderError(404, w, nil, acceptLanguages, mimetype)
  49. return
  50. }
  51. tvSerie, err := libamuse.ShowTvSerie(path[1], etag, acceptLanguages, mimetype)
  52. render(tvSerie, err, w, acceptLanguages, mimetype)
  53. }
  54. func film(w http.ResponseWriter, r *http.Request) {
  55. acceptLanguages := r.Header.Get("Accept-Language")
  56. mimetype := strings.Split(r.Header.Get("Accept"), ",")[0]
  57. defer recovery(acceptLanguages, mimetype, w)
  58. path := strings.Split(r.URL.Path[1:], "/")
  59. _, err := strconv.ParseInt(path[1], 10, 64)
  60. if err != nil {
  61. renderError(400, w, err, acceptLanguages, mimetype)
  62. return
  63. } else if len(path) > 2 {
  64. renderError(404, w, nil, acceptLanguages, mimetype)
  65. return
  66. }
  67. film, err := libamuse.ShowFilm(path[1], acceptLanguages, mimetype)
  68. render(film, err, w, acceptLanguages, mimetype)
  69. }
  70. func book(w http.ResponseWriter, r *http.Request) {
  71. acceptLanguages := r.Header.Get("Accept-Language")
  72. mimetype := strings.Split(r.Header.Get("Accept"), ",")[0]
  73. defer recovery(acceptLanguages, mimetype, w)
  74. path := strings.Split(r.URL.Path[1:], "/")
  75. if len(path) > 2 {
  76. renderError(404, w, nil, acceptLanguages, mimetype)
  77. return
  78. }
  79. book, err := libamuse.ShowBook(path[1], acceptLanguages, mimetype)
  80. render(book, err, w, acceptLanguages, mimetype)
  81. }
  82. func bookSerie(w http.ResponseWriter, r *http.Request) {
  83. acceptLanguages := r.Header.Get("Accept-Language")
  84. mimetype := strings.Split(r.Header.Get("Accept"), ",")[0]
  85. defer recovery(acceptLanguages, mimetype, w)
  86. path := strings.Split(r.URL.Path[1:], "/")
  87. if len(path) > 2 {
  88. renderError(404, w, nil, acceptLanguages, mimetype)
  89. return
  90. }
  91. bookSerie, err := libamuse.ShowBookSerie(path[1], acceptLanguages, mimetype)
  92. render(bookSerie, err, w, acceptLanguages, mimetype)
  93. }
  94. func search(w http.ResponseWriter, r *http.Request) {
  95. acceptLanguages := r.Header.Get("Accept-Language")
  96. mimetype := strings.Split(r.Header.Get("Accept"), ",")[0]
  97. defer recovery(acceptLanguages, mimetype, w)
  98. path := strings.Split(r.URL.Path[1:], "/")
  99. if len(path) > 2 {
  100. renderError(404, w, nil, acceptLanguages, mimetype)
  101. return
  102. }
  103. query := r.URL.Query().Get("q")
  104. page := r.URL.Query().Get("page")
  105. results, err := libamuse.PerformSearch(query, acceptLanguages, mimetype, page)
  106. render(results, err, w, acceptLanguages, mimetype)
  107. }
  108. func index(w http.ResponseWriter, r *http.Request) {
  109. acceptLanguages := r.Header.Get("Accept-Language")
  110. mimetype := strings.Split(r.Header.Get("Accept"), ",")[0]
  111. defer recovery(acceptLanguages, mimetype, w)
  112. path := strings.Split(r.URL.Path[1:], "/")
  113. if path[0] != "" {
  114. renderError(404, w, nil, acceptLanguages, mimetype)
  115. return
  116. }
  117. index, err := libamuse.ShowIndex(acceptLanguages, mimetype)
  118. render(index, err, w, acceptLanguages, mimetype)
  119. }
  120. func about(w http.ResponseWriter, r *http.Request) {
  121. acceptLanguages := r.Header.Get("Accept-Language")
  122. mimetype := strings.Split(r.Header.Get("Accept"), ",")[0]
  123. defer recovery(acceptLanguages, mimetype, w)
  124. about, err := libamuse.ShowAbout(acceptLanguages, mimetype)
  125. render(about, err, w, acceptLanguages, mimetype)
  126. }
  127. func static(w http.ResponseWriter, r *http.Request) {
  128. etagReq := r.Header.Get("If-None-Match")
  129. f, err := os.Open(utils.DataHome + "/" + r.URL.Path[1:])
  130. if err != nil {
  131. w.WriteHeader(500)
  132. return
  133. }
  134. defer f.Close()
  135. h := sha256.New()
  136. if _, err := io.Copy(h, f); err != nil {
  137. w.WriteHeader(500)
  138. return
  139. }
  140. etag := base64.StdEncoding.EncodeToString(h.Sum(nil))
  141. mime.AddExtensionType(".woff2", "font/woff2")
  142. w.Header().Set("ETag", etag)
  143. if etagReq == etag {
  144. w.WriteHeader(304)
  145. } else {
  146. s := strings.Split(f.Name(), ".")
  147. ext := "." + s[len(s)-1]
  148. mimetype := mime.TypeByExtension(ext)
  149. w.Header().Set("Content-Type", mimetype+"; charset=utf-8")
  150. f.Seek(0, 0)
  151. if _, err := io.Copy(w, f); err != nil {
  152. w.WriteHeader(500)
  153. }
  154. }
  155. }
  156. func main() {
  157. port := flag.Int("p", 5008, "port to run amuse on")
  158. dataHome := flag.String("d", "/usr/local/share/amuse", "data directory")
  159. flag.Parse()
  160. portStr := fmt.Sprintf(":%d", *port)
  161. utils.DataHome = *dataHome
  162. libamuse.InitDB()
  163. http.HandleFunc("/", index)
  164. http.HandleFunc("/static/", static)
  165. http.HandleFunc("/about", about)
  166. http.HandleFunc("/items/", search)
  167. http.HandleFunc("/films/", film)
  168. http.HandleFunc("/tvseries/", tvSerie)
  169. http.HandleFunc("/persons/", person)
  170. http.HandleFunc("/books/", book)
  171. http.HandleFunc("/bookseries/", bookSerie)
  172. fmt.Printf("running on %s\n", portStr)
  173. e := http.ListenAndServe(portStr, nil)
  174. if e != nil {
  175. fmt.Println(e)
  176. }
  177. }
  178. func recovery(languages, mimetype string, w http.ResponseWriter) {
  179. if r := recover(); r != nil {
  180. renderError(500, w, errors.New(r.(string)), languages, mimetype)
  181. }
  182. }
  183. func render(result string, e error, w http.ResponseWriter, languages, mimetype string) {
  184. if e != nil {
  185. fmt.Println(e)
  186. if _, ok := e.(front.NoSuchRendererError); ok {
  187. renderError(406, w, e, languages, mimetype)
  188. } else if httpError, ok := e.(network.HttpError); ok {
  189. renderError(httpError.Status, w, httpError, languages, mimetype)
  190. } else {
  191. renderError(500, w, e, languages, mimetype)
  192. }
  193. } else {
  194. fmt.Fprint(w, result)
  195. }
  196. }
  197. func renderError(code int, w http.ResponseWriter, e error, languages, mimetype string) {
  198. w.WriteHeader(code)
  199. if code != 406 {
  200. errorPage, err := libamuse.ShowErrorPage(code, languages, mimetype)
  201. if err != nil {
  202. fmt.Fprintf(w, "Fatal error while rendering error %d.\nContact admin.", code)
  203. }
  204. fmt.Fprint(w, errorPage)
  205. }
  206. }