Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

96 lines
2.5KB

  1. package main
  2. import (
  3. "biukop/sfm/loan"
  4. "database/sql"
  5. "fmt"
  6. log "github.com/sirupsen/logrus"
  7. "net/http"
  8. "net/http/httputil"
  9. "strings"
  10. "time"
  11. )
  12. const apiV1Prefix = "/api/v1/"
  13. type apiV1HandlerMap struct {
  14. Method string
  15. Path string //regex
  16. Handler func(http.ResponseWriter, *http.Request, *loan.Session)
  17. }
  18. var apiV1Handler = []apiV1HandlerMap{
  19. {"POST", "login", apiV1Login},
  20. {"GET", "login", apiV1DumpRequest},
  21. }
  22. //apiV1Main version 1 main entry for all REST API
  23. //
  24. func apiV1Main(w http.ResponseWriter, r *http.Request) {
  25. logRequestDebug(httputil.DumpRequest(r, true))
  26. w.Header().Set("Content-Type", "application/json;charset=UTF-8")
  27. //try session login first, if not an empty session will be created
  28. session, e := apiV1InitSession(r)
  29. if e != nil {
  30. log.Warn("Fail to InitSession %+v", session)
  31. apiV1ServerError(w, r)
  32. return
  33. }
  34. session.RenewIfExpireSoon()
  35. session.SetRemote(r)
  36. //we have a session now, either guest or valid user
  37. //search through handler
  38. path := r.URL.Path[len(apiV1Prefix):] //strip API prefix
  39. for _, node := range apiV1Handler {
  40. if r.Method == node.Method && path == node.Path {
  41. node.Handler(w, r, &session)
  42. e = session.Write() //finish this session to DB
  43. if e != nil {
  44. log.Warnf("Failed to Save Session %+v \n reason \n%s\n", session, e.Error())
  45. }
  46. return
  47. }
  48. }
  49. //Catch for all
  50. apiV1DumpRequest(w, r, &session)
  51. }
  52. func apiV1InitSession(r *http.Request) (session loan.Session, e error) {
  53. session = loan.Session{}
  54. sid := r.Header.Get("Biukop-Session")
  55. e = session.Retrieve(r)
  56. if e == nil { //we got existing session
  57. e = session.ValidateRequest(r)
  58. if e != nil { // not successfully validated
  59. log.Warn("failed session login %+v, %s", session, time.Now().Format("RFC1132"))
  60. } //else, we have logged this user in
  61. } else if e == sql.ErrNoRows {
  62. log.Warn("DB has no corresponding session ", sid)
  63. session.InitGuest(time.Now().Add(loan.DefaultSessionDuration))
  64. e = nil //we try to init an empty one
  65. } else {
  66. log.Warn("Retrieve Session %s encountered error %s", sid, e.Error())
  67. }
  68. session.SetRemote(r) //make sure they are using latest remote
  69. return
  70. }
  71. func apiV1ErrorCheck(e error) {
  72. if nil != e {
  73. panic(e.Error()) //TODO: detailed error check, truck all caller
  74. }
  75. }
  76. func apiV1ServerError(w http.ResponseWriter, r *http.Request) {
  77. w.WriteHeader(500)
  78. fmt.Fprintf(w, "Server Internal Error "+time.Now().Format("RFC1132"))
  79. //write log
  80. dump := logRequestDebug(httputil.DumpRequest(r, true))
  81. dump = strings.TrimSpace(dump)
  82. log.Warn("Unhandled Protocol = %s path= %s", r.Method, r.URL.Path)
  83. }