|
- package main
-
- import (
- "biukop/sfm/loan"
- "database/sql"
- "fmt"
- log "github.com/sirupsen/logrus"
- "net/http"
- "net/http/httputil"
- "strings"
- "time"
- )
-
- const apiV1Prefix = "/api/v1/"
-
- type apiV1HandlerMap struct {
- Method string
- Path string //regex
- Handler func(http.ResponseWriter, *http.Request, *loan.Session)
- }
-
- var apiV1Handler = []apiV1HandlerMap{
- {"POST", "login", apiV1Login},
- {"GET", "login", apiV1DumpRequest},
- }
-
- //apiV1Main version 1 main entry for all REST API
- //
- func apiV1Main(w http.ResponseWriter, r *http.Request) {
- logRequestDebug(httputil.DumpRequest(r, true))
- w.Header().Set("Content-Type", "application/json;charset=UTF-8")
-
- //try session login first, if not an empty session will be created
- session, e := apiV1InitSession(r)
- if e != nil {
- log.Warn("Fail to InitSession %+v", session)
- apiV1ServerError(w, r)
- return
- }
- session.RenewIfExpireSoon()
- session.SetRemote(r)
-
- //we have a session now, either guest or valid user
- //search through handler
- path := r.URL.Path[len(apiV1Prefix):] //strip API prefix
- for _, node := range apiV1Handler {
- if r.Method == node.Method && path == node.Path {
- node.Handler(w, r, &session)
- e = session.Write() //finish this session to DB
- if e != nil {
- log.Warnf("Failed to Save Session %+v \n reason \n%s\n", session, e.Error())
- }
- return
- }
- }
- //Catch for all
- apiV1DumpRequest(w, r, &session)
- }
-
- func apiV1InitSession(r *http.Request) (session loan.Session, e error) {
- session = loan.Session{}
- sid := r.Header.Get("Biukop-Session")
- e = session.Retrieve(r)
- if e == nil { //we got existing session
- e = session.ValidateRequest(r)
- if e != nil { // not successfully validated
- log.Warn("failed session login %+v, %s", session, time.Now().Format("RFC1132"))
- } //else, we have logged this user in
- } else if e == sql.ErrNoRows {
- log.Warn("DB has no corresponding session ", sid)
- session.InitGuest(time.Now().Add(loan.DefaultSessionDuration))
- e = nil //we try to init an empty one
- } else {
- log.Warn("Retrieve Session %s encountered error %s", sid, e.Error())
- }
- session.SetRemote(r) //make sure they are using latest remote
- return
- }
-
- func apiV1ErrorCheck(e error) {
- if nil != e {
- panic(e.Error()) //TODO: detailed error check, truck all caller
- }
- }
-
- func apiV1ServerError(w http.ResponseWriter, r *http.Request) {
-
- w.WriteHeader(500)
- fmt.Fprintf(w, "Server Internal Error "+time.Now().Format("RFC1132"))
-
- //write log
- dump := logRequestDebug(httputil.DumpRequest(r, true))
- dump = strings.TrimSpace(dump)
- log.Warn("Unhandled Protocol = %s path= %s", r.Method, r.URL.Path)
- }
|