Core functionality for new aiterp.net servers
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.

94 lines
2.2 KiB

7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
  1. package wrouter
  2. import (
  3. "fmt"
  4. "net/http"
  5. "strings"
  6. "time"
  7. "git.aiterp.net/gisle/wrouter/auth"
  8. )
  9. type Route interface {
  10. Handle(path string, w http.ResponseWriter, req *http.Request, user *auth.User) bool
  11. }
  12. type Router struct {
  13. paths map[Route]string
  14. routes []Route
  15. }
  16. func (router *Router) Route(path string, route Route) {
  17. if router.paths == nil {
  18. router.paths = make(map[Route]string, 16)
  19. }
  20. router.paths[route] = path
  21. router.routes = append(router.routes, route)
  22. }
  23. func (router *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) {
  24. defer req.Body.Close()
  25. // Allow REST for clients of yore
  26. if req.Header.Get("X-Method") != "" {
  27. req.Method = strings.ToUpper(req.Header.Get("X-Method"))
  28. }
  29. // Resolve session cookies
  30. var user *auth.User
  31. var sess *auth.Session
  32. cookie, err := req.Cookie(auth.SessionCookieName)
  33. if cookie != nil && err == nil {
  34. sess = auth.FindSession(cookie.Value)
  35. if sess != nil {
  36. user = auth.FindUser(sess.UserID)
  37. }
  38. }
  39. for index, route := range router.routes {
  40. path := router.paths[route]
  41. if strings.HasPrefix(strings.ToLower(req.URL.Path), path) {
  42. // Just so the handler can replace the path properly in case of case
  43. // insensitive clients getting fancy on it.
  44. path = req.URL.Path[:len(path)]
  45. // Attach a little something for testing
  46. w.Header().Set("X-Route-Path", path)
  47. w.Header().Set("X-Route-Index", fmt.Sprint(index))
  48. if route.Handle(path, w, req, user) {
  49. if user != nil && user.LoggedOut() {
  50. auth.CloseSession(sess.ID)
  51. }
  52. return
  53. }
  54. }
  55. }
  56. w.Header().Set("Content-Type", "text/plain; charset=utf-8")
  57. w.WriteHeader(404)
  58. w.Write([]byte("Not Found: " + req.URL.Path))
  59. }
  60. func (router *Router) Resource(mount string, list, create Func, get, update, delete IDFunc) {
  61. router.Route(mount, NewResource(list, create, get, update, delete))
  62. }
  63. func (router *Router) Static(mount string, filePath string) {
  64. router.Route(mount, NewStatic(filePath))
  65. }
  66. func (router *Router) Listen(host string, port int) error {
  67. srv := &http.Server{
  68. Addr: fmt.Sprintf("%s:%d", host, port),
  69. ReadTimeout: 5 * time.Second,
  70. WriteTimeout: 10 * time.Second,
  71. IdleTimeout: 120 * time.Second,
  72. Handler: router,
  73. }
  74. return srv.ListenAndServe()
  75. }