|
|
|
@@ -2,8 +2,13 @@ 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/" |
|
|
|
@@ -24,14 +29,27 @@ var apiV1Handler = []apiV1HandlerMap{ |
|
|
|
func apiV1Main(w http.ResponseWriter, r *http.Request) { |
|
|
|
logRequestDebug(httputil.DumpRequest(r, true)) |
|
|
|
w.Header().Set("Content-Type", "application/json;charset=UTF-8") |
|
|
|
path := r.URL.Path[len(apiV1Prefix):] //strip API prefix |
|
|
|
|
|
|
|
session := loan.Session{} |
|
|
|
session.Retrieve(r) //TODO: check remote_addr changes in DB, to prevent possible Hack |
|
|
|
//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 |
|
|
|
} |
|
|
|
} |
|
|
|
@@ -39,8 +57,39 @@ func apiV1Main(w http.ResponseWriter, r *http.Request) { |
|
|
|
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()) |
|
|
|
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) |
|
|
|
} |