mirror of
https://github.com/zhaojh329/rttys.git
synced 2026-02-27 09:53:21 +08:00
195 lines
4.2 KiB
Go
195 lines
4.2 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
jsoniter "github.com/json-iterator/go"
|
|
"github.com/rakyll/statik/fs"
|
|
"github.com/rs/zerolog/log"
|
|
"github.com/zhaojh329/rttys/cache"
|
|
_ "github.com/zhaojh329/rttys/statik"
|
|
"io/ioutil"
|
|
"net/http"
|
|
"strconv"
|
|
"time"
|
|
)
|
|
|
|
type Credentials struct {
|
|
Password string `json:"password"`
|
|
Username string `json:"username"`
|
|
}
|
|
|
|
var httpSessions *cache.Cache
|
|
|
|
func allowOrigin(w http.ResponseWriter) {
|
|
w.Header().Set("Access-Control-Allow-Origin", "*")
|
|
w.Header().Add("Access-Control-Allow-Headers", "Content-Type")
|
|
w.Header().Set("content-type", "application/json")
|
|
}
|
|
|
|
func httpAuth(w http.ResponseWriter, r *http.Request) bool {
|
|
c, err := r.Cookie("sid")
|
|
if err != nil {
|
|
http.Error(w, "Forbidden", http.StatusForbidden)
|
|
return false
|
|
}
|
|
|
|
if _, ok := httpSessions.Get(c.Value); !ok {
|
|
http.Error(w, "Forbidden", http.StatusForbidden)
|
|
return false
|
|
}
|
|
|
|
// Update
|
|
httpSessions.Del(c.Value)
|
|
httpSessions.Set(c.Value, true, 0)
|
|
|
|
return true
|
|
}
|
|
|
|
func httpLogin(cfg *RttysConfig, creds *Credentials) bool {
|
|
if cfg.httpUsername != creds.Username {
|
|
return false
|
|
}
|
|
|
|
if cfg.httpPassword != "" {
|
|
return cfg.httpPassword == creds.Password
|
|
}
|
|
|
|
return true
|
|
}
|
|
|
|
func httpStart(br *Broker, cfg *RttysConfig) {
|
|
httpSessions = cache.New(30*time.Minute, 5*time.Second)
|
|
|
|
statikFS, err := fs.New()
|
|
if err != nil {
|
|
log.Fatal().Msg(err.Error())
|
|
}
|
|
|
|
staticfs := http.FileServer(statikFS)
|
|
|
|
if cfg.baseURL == "/" {
|
|
cfg.baseURL = ""
|
|
}
|
|
|
|
http.HandleFunc(cfg.baseURL+"/ws", func(w http.ResponseWriter, r *http.Request) {
|
|
if _, ok := httpSessions.Get(r.URL.Query().Get("sid")); !ok {
|
|
http.Error(w, "Invalid sid", http.StatusForbidden)
|
|
return
|
|
}
|
|
|
|
serveUser(br, w, r)
|
|
})
|
|
|
|
http.HandleFunc(cfg.baseURL+"/cmd", func(w http.ResponseWriter, r *http.Request) {
|
|
allowOrigin(w)
|
|
|
|
done := make(chan struct{})
|
|
req := &CommandReq{
|
|
done: done,
|
|
w: w,
|
|
}
|
|
|
|
if r.Method == "GET" {
|
|
req.token = r.URL.Query().Get("token")
|
|
} else if r.Method == "POST" {
|
|
content, err := ioutil.ReadAll(r.Body)
|
|
if err != nil {
|
|
log.Error().Msg(err.Error())
|
|
return
|
|
}
|
|
|
|
sid := jsoniter.Get(content, "sid").ToString()
|
|
if _, ok := httpSessions.Get(sid); !ok {
|
|
http.Error(w, "Forbidden", http.StatusForbidden)
|
|
return
|
|
}
|
|
|
|
req.content = content
|
|
} else {
|
|
http.Error(w, "MethodNotAllowed", http.StatusMethodNotAllowed)
|
|
return
|
|
}
|
|
|
|
br.cmdReq <- req
|
|
<-done
|
|
})
|
|
|
|
http.HandleFunc(cfg.baseURL+"/signin", func(w http.ResponseWriter, r *http.Request) {
|
|
var creds Credentials
|
|
|
|
err := jsoniter.NewDecoder(r.Body).Decode(&creds)
|
|
if err != nil {
|
|
http.Error(w, "Bad Request", http.StatusBadRequest)
|
|
return
|
|
}
|
|
|
|
if httpLogin(cfg, &creds) {
|
|
sid := genUniqueID("http")
|
|
httpSessions.Set(sid, true, 0)
|
|
|
|
http.SetCookie(w, &http.Cookie{
|
|
Name: "sid",
|
|
Value: sid,
|
|
HttpOnly: true,
|
|
})
|
|
fmt.Fprint(w, sid)
|
|
return
|
|
}
|
|
|
|
http.Error(w, "Forbidden", http.StatusForbidden)
|
|
})
|
|
|
|
http.HandleFunc(cfg.baseURL+"/devs", func(w http.ResponseWriter, r *http.Request) {
|
|
type DeviceInfo struct {
|
|
ID string `json:"id"`
|
|
Uptime int64 `json:"uptime"`
|
|
Description string `json:"description"`
|
|
}
|
|
|
|
if !httpAuth(w, r) {
|
|
return
|
|
}
|
|
|
|
devs := make([]DeviceInfo, 0)
|
|
|
|
for id, dev := range br.devices {
|
|
dev := DeviceInfo{id, time.Now().Unix() - dev.timestamp, dev.desc}
|
|
devs = append(devs, dev)
|
|
}
|
|
|
|
allowOrigin(w)
|
|
|
|
resp, _ := jsoniter.Marshal(devs)
|
|
|
|
w.Write(resp)
|
|
})
|
|
|
|
hfunc := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
if r.URL.Path == "/" {
|
|
t := r.URL.Query().Get("tmr")
|
|
id := r.URL.Query().Get("id")
|
|
|
|
if t == "" && id == "" {
|
|
http.Redirect(w, r, cfg.baseURL+"?tmr="+strconv.FormatInt(time.Now().Unix(), 10), http.StatusFound)
|
|
return
|
|
}
|
|
}
|
|
|
|
staticfs.ServeHTTP(w, r)
|
|
})
|
|
|
|
if cfg.baseURL != "" {
|
|
http.Handle(cfg.baseURL+"/", http.StripPrefix(cfg.baseURL, hfunc))
|
|
} else {
|
|
http.Handle("/", hfunc)
|
|
}
|
|
|
|
if cfg.sslCert != "" && cfg.sslKey != "" {
|
|
log.Info().Msgf("Listen user on: %s SSL on")
|
|
log.Fatal().Msg(http.ListenAndServeTLS(cfg.addrUser, cfg.sslCert, cfg.sslKey, nil).Error())
|
|
} else {
|
|
log.Info().Msgf("Listen user on: %s SSL off", cfg.addrUser)
|
|
log.Fatal().Msg(http.ListenAndServe(cfg.addrUser, nil).Error())
|
|
}
|
|
}
|