cvc/src/loreal.com/dit/cmd/ceh-cs-portal/endpoints.go

303 lines
8.0 KiB
Go

package main
import (
"database/sql"
"html/template"
"log"
"net/http"
"strconv"
"loreal.com/dit/endpoint"
"loreal.com/dit/middlewares"
"loreal.com/dit/cmd/ceh-cs-portal/restful"
"github.com/microcosm-cc/bluemonday"
)
// var seededRand *rand.Rand
var sanitizePolicy *bluemonday.Policy
var errorTemplate *template.Template
func init() {
// seededRand = rand.New(rand.NewSource(time.Now().UnixNano()))
sanitizePolicy = bluemonday.UGCPolicy()
var err error
errorTemplate, _ = template.ParseFiles("./template/error.tpl")
if err != nil {
log.Panic("[ERR] - Parsing error template", err)
}
}
func brandFilter(r *http.Request, item *map[string]interface{}) bool {
roles := r.Header.Get("roles")
if roles == "admin" {
return false
}
loginBrand := r.Header.Get("brand")
if loginBrand == "" {
return false
}
targetBrand, _ := ((*item)["brand"]).(*string)
return *targetBrand != "" && *targetBrand != loginBrand
}
func (a *App) initEndpoints() {
rt := a.getRuntime("prod")
a.Endpoints = map[string]EndpointEntry{
"api/kvstore": {Handler: a.kvstoreHandler, Middlewares: a.noAuthMiddlewares("api/kvstore")},
"api/visit": {Handler: a.pvHandler},
"error": {Handler: a.errorHandler, Middlewares: a.noAuthMiddlewares("error")},
"debug": {Handler: a.debugHandler},
"maintenance/fe/upgrade": {Handler: a.feUpgradeHandler},
"api/gw": {Handler: a.gatewayHandler},
"api/brand/": {
Handler: restful.NewHandler(
"brand",
restful.NewSQLiteAdapter(rt.db,
rt.mutex,
"Brand",
Brand{},
),
).ServeHTTP,
},
// "api/customer/": {
// Handler: restful.NewHandler(
// "customer",
// restful.NewSQLiteAdapter(rt.db,
// rt.mutex,
// "Customer",
// Customer{},
// ),
// ).SetFilter(storeFilter).ServeHTTP,
// },
}
postPrepareDB(rt)
}
//noAuthMiddlewares - middlewares without auth
func (a *App) noAuthMiddlewares(path string) []endpoint.ServerMiddleware {
return []endpoint.ServerMiddleware{
middlewares.NoCache(),
middlewares.ServerInstrumentation(path, endpoint.RequestCounter, endpoint.LatencyHistogram, endpoint.DurationsSummary),
}
}
// //webTokenAuthMiddlewares - middlewares auth by token
// func (a *App) webTokenAuthMiddlewares(path string) []endpoint.ServerMiddleware {
// return []endpoint.ServerMiddleware{
// middlewares.NoCache(),
// middlewares.WebTokenAuth(a.WebTokenAuthProvider),
// middlewares.ServerInstrumentation(path, endpoint.RequestCounter, endpoint.LatencyHistogram, endpoint.DurationsSummary),
// }
// }
//getDefaultMiddlewares - middlewares installed by defaults
func (a *App) getDefaultMiddlewares(path string) []endpoint.ServerMiddleware {
return []endpoint.ServerMiddleware{
middlewares.NoCache(),
middlewares.WebTokenAuth(a.WebTokenAuthProvider),
// middlewares.BasicAuthOrTokenAuthWithRole(a.AuthProvider, "", "user,admin"),
middlewares.ServerInstrumentation(
path,
endpoint.RequestCounter,
endpoint.LatencyHistogram,
endpoint.DurationsSummary,
),
}
}
func (a *App) getEnv(appid string) string {
if appid == "" {
if a.Config.Production {
return "prod"
}
return "pp"
}
if appid == "ceh" {
return "prod"
}
return "pp"
}
/* 以下为具体 Endpoint 实现代码 */
//errorHandler - query error info
//endpoint: error
//method: GET
func (a *App) errorHandler(w http.ResponseWriter, r *http.Request) {
if r.Method != "GET" {
http.Error(w, "Not Acceptable", http.StatusNotAcceptable)
return
}
q := r.URL.Query()
title := sanitizePolicy.Sanitize(q.Get("title"))
errmsg := sanitizePolicy.Sanitize(q.Get("errmsg"))
if err := errorTemplate.Execute(w, map[string]interface{}{
"title": title,
"errmsg": errmsg,
}); err != nil {
log.Println("[ERR] - errorTemplate error:", err)
http.Error(w, "500", http.StatusInternalServerError)
}
}
/* 以下为具体 Endpoint 实现代码 */
//kvstoreHandler - get value from kvstore in runtime
//endpoint: /api/kvstore
//method: GET
func (a *App) kvstoreHandler(w http.ResponseWriter, r *http.Request) {
if r.Method != "GET" {
outputJSON(w, APIStatus{
ErrCode: -100,
ErrMessage: "Method not acceptable",
})
return
}
q := r.URL.Query()
ticket := q.Get("ticket")
env := a.getEnv(q.Get("appid"))
rt := a.getRuntime(env)
if rt == nil {
outputJSON(w, APIStatus{
ErrCode: -1,
ErrMessage: "invalid appid",
})
return
}
var result struct {
Value interface{} `json:"value"`
}
var ok bool
var v interface{}
v, ok = rt.Retrive(ticket)
if !ok {
outputJSON(w, APIStatus{
ErrCode: -2,
ErrMessage: "invalid ticket",
})
return
}
switch val := v.(type) {
case chan interface{}:
// log.Println("[Hu Bin] - Get Value Chan:", val)
result.Value = <-val
// log.Println("[Hu Bin] - Get Value from Chan:", result.Value)
default:
// log.Println("[Hu Bin] - Get Value:", val)
result.Value = val
}
outputJSON(w, result)
}
//pvHandler - record PV/UV
//endpoint: /api/visit
//method: GET
func (a *App) pvHandler(w http.ResponseWriter, r *http.Request) {
if r.Method != "GET" {
outputJSON(w, map[string]interface{}{
"code": -1,
"msg": "Not support",
})
return
}
q := r.URL.Query()
rt := a.getRuntime(r.PostForm.Get("env"))
if rt == nil {
outputJSON(w, map[string]interface{}{
"code": -2,
"msg": "Invalid APPID",
})
return
}
userid, _ := strconv.ParseInt(sanitizePolicy.Sanitize(r.PostForm.Get("userid")), 10, 64)
pageid := sanitizePolicy.Sanitize(q.Get("pageid"))
scene := sanitizePolicy.Sanitize(q.Get("scene"))
visitState, _ := strconv.Atoi(sanitizePolicy.Sanitize(q.Get("type")))
if err := a.recordPV(
rt,
userid,
pageid,
scene,
visitState,
); err != nil {
log.Println("[ERR] - [EP][api/visit], err:", err)
outputJSON(w, map[string]interface{}{
"code": -3,
"msg": "internal error",
})
return
}
outputJSON(w, map[string]interface{}{
"code": 0,
"msg": "ok",
})
}
//CSV BOM
//file.Write([]byte{0xef, 0xbb, 0xbf})
func outputExcel(w http.ResponseWriter, b []byte, filename string) {
w.Header().Add("Content-Disposition", "attachment; filename="+filename)
//w.Header().Add("Content-Type", "application/vnd.ms-excel")
w.Header().Add("Content-Type", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
// w.Header().Add("Content-Transfer-Encoding", "binary")
w.Write(b)
}
func outputText(w http.ResponseWriter, b []byte) {
w.Header().Add("Content-Type", "text/plain;charset=utf-8")
w.Write(b)
}
func showError(w http.ResponseWriter, r *http.Request, title, message string) {
if err := errorTemplate.Execute(w, map[string]interface{}{
"title": title,
"errmsg": message,
}); err != nil {
log.Println("[ERR] - errorTemplate error:", err)
http.Error(w, "500", http.StatusInternalServerError)
}
}
//postPrepareDB - initialized database after init endpoints
func postPrepareDB(rt *RuntimeEnv) {
//init database tables
sqlStmts := []string{
// `CREATE TRIGGER IF NOT EXISTS insert_fulfill INSERT ON fulfillment
// BEGIN
// UPDATE CustomerOrder SET qtyfulfilled=qtyfulfilled+new.quantity WHERE id=new.orderid;
// END;`,
// `CREATE TRIGGER IF NOT EXISTS delete_fulfill DELETE ON fulfillment
// BEGIN
// UPDATE CustomerOrder SET qtyfulfilled=qtyfulfilled-old.quantity WHERE id=old.orderid;
// END;`,
// `CREATE TRIGGER IF NOT EXISTS before_update_fulfill BEFORE UPDATE ON fulfillment
// BEGIN
// UPDATE CustomerOrder SET qtyfulfilled=qtyfulfilled-old.quantity WHERE id=old.orderid;
// END;`,
// `CREATE TRIGGER IF NOT EXISTS after_update_fulfill AFTER UPDATE ON fulfillment
// BEGIN
// UPDATE CustomerOrder SET qtyfulfilled=qtyfulfilled+new.quantity WHERE id=new.orderid;
// END;`,
// "CREATE UNIQUE INDEX IF NOT EXISTS uidxOpenID ON WxUser(OpenID);",
}
log.Printf("[INFO] - Post Prepare DB for [%s]...\n", rt.Config.Name)
for _, sqlStmt := range sqlStmts {
_, err := rt.db.Exec(sqlStmt)
if err != nil {
log.Printf("[ERR] - [PrepareDB] %q: %s\n", err, sqlStmt)
return
}
}
rt.stmts = make(map[string]*sql.Stmt, 0)
log.Printf("[INFO] - DB for [%s] prepared!\n", rt.Config.Name)
}