-
Notifications
You must be signed in to change notification settings - Fork 0
/
server.go
132 lines (116 loc) · 3.24 KB
/
server.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
package server
import (
"encoding/json"
"fmt"
"log"
"net/http"
"os"
"github.com/takashabe/go-router"
session "github.com/takashabe/go-session"
_ "github.com/takashabe/go-session/memory" // session driver
)
// printDebugf behaves like log.Printf only in the debug env
func printDebugf(format string, args ...interface{}) {
if env := os.Getenv("GO_PORTAL_DEBUG"); len(env) != 0 {
log.Printf("[DEBUG] "+format+"\n", args...)
}
}
// ErrorResponse is Error response template
type ErrorResponse struct {
Message string `json:"reason"`
Error error `json:"-"`
}
func (e *ErrorResponse) String() string {
return fmt.Sprintf("reason: %s, error: %s", e.Message, e.Error.Error())
}
// Respond is response write to ResponseWriter
func Respond(w http.ResponseWriter, code int, src interface{}) {
var body []byte
var err error
switch s := src.(type) {
case []byte:
if !json.Valid(s) {
Error(w, http.StatusInternalServerError, err, "invalid json")
return
}
body = s
case string:
body = []byte(s)
case *ErrorResponse, ErrorResponse:
// avoid infinite loop
if body, err = json.Marshal(src); err != nil {
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
w.WriteHeader(http.StatusInternalServerError)
w.Write([]byte("{\"reason\":\"failed to parse json\"}"))
return
}
default:
if body, err = json.Marshal(src); err != nil {
Error(w, http.StatusInternalServerError, err, "failed to parse json")
return
}
}
w.WriteHeader(code)
w.Write(body)
}
// Error is wrapped Respond when error response
func Error(w http.ResponseWriter, code int, err error, msg string) {
e := &ErrorResponse{
Message: msg,
Error: err,
}
printDebugf("%s", e.String())
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
Respond(w, code, e)
}
// JSON is wrapped Respond when success response
func JSON(w http.ResponseWriter, code int, src interface{}) {
w.Header().Set("Content-Type", "application/json; charset=UTF-8")
Respond(w, code, src)
}
// Server supply HTTP server of the portal
type Server struct {
port int
session *session.Manager
pubsubAddr string
}
// NewServer returns initialized Server
func NewServer(pubsubAddr string) (*Server, error) {
session, err := session.NewManager("memory", "portal", 3600)
if err != nil {
return nil, err
}
return &Server{
session: session,
pubsubAddr: pubsubAddr,
}, nil
}
// Routes returns router
func (s *Server) Routes() *router.Router {
r := router.NewRouter()
// login page
r.Get("/api/login", s.Logout)
r.Post("/api/login", s.Login)
// main page
r.Get("/api/team", s.GetTeam)
r.Get("/api/queues", s.Queues)
r.Post("/api/enqueue", s.Enqueue)
r.Get("/api/history", s.History)
r.Get("/api/bench_detail/:id", s.ScoreDetail)
// r.Get("/leader_board", nil)
// frontend
r.ServeFile("/", "./public/index.html")
r.ServeFile("/bundle.js", "./public/bundle.js")
r.NotFoundHandler = http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
http.ServeFile(w, req, "./public/index.html")
})
return r
}
// Run start server
func (s *Server) Run(port int) error {
log.Printf("Portal server running at http://localhost:%d/", port)
if err := s.Polling(); err != nil {
return err
}
return http.ListenAndServe(fmt.Sprintf(":%d", port), s.Routes())
}