web: use gin

Signed-off-by: Jianhui Zhao <zhaojh329@gmail.com>
This commit is contained in:
Jianhui Zhao
2020-03-13 00:22:52 +08:00
parent b43ba68561
commit ac1c527237
10 changed files with 104 additions and 99 deletions
-2
View File
@@ -32,8 +32,6 @@ This is the server program of [rtty](https://github.com/zhaojh329/rtty)
address to listen device (default ":5912")
-addr-user string
address to listen user (default ":5913")
-base-url string
base url to serve on (default "/")
-conf string
config file to load (default "./rttys.conf")
-gen-token
-2
View File
@@ -32,8 +32,6 @@
address to listen device (default ":5912")
-addr-user string
address to listen user (default ":5913")
-base-url string
base url to serve on (default "/")
-conf string
config file to load (default "./rttys.conf")
-gen-token
-3
View File
@@ -16,7 +16,6 @@ type RttysConfig struct {
httpUsername string
httpPassword string
token string
baseURL string
fontSize int
}
@@ -44,7 +43,6 @@ func parseConfig() *RttysConfig {
flag.StringVar(&cfg.httpUsername, "http-username", "", "username for http auth")
flag.StringVar(&cfg.httpPassword, "http-password", "", "password for http auth")
flag.StringVar(&cfg.token, "token", "", "token to use")
flag.StringVar(&cfg.baseURL, "base-url", "/", "base url to serve on")
conf := flag.String("conf", "./rttys.conf", "config file to load")
genToken := flag.Bool("gen-token", false, "generate token")
@@ -63,7 +61,6 @@ func parseConfig() *RttysConfig {
getConfigOpt(yamlCfg, "http-username", &cfg.httpUsername)
getConfigOpt(yamlCfg, "http-password", &cfg.httpPassword)
getConfigOpt(yamlCfg, "token", &cfg.token)
getConfigOpt(yamlCfg, "base-url", &cfg.baseURL)
getConfigOpt(yamlCfg, "font-size", &cfg.fontSize)
}
+1 -1
View File
@@ -199,7 +199,7 @@
}
getDevices() {
this.axios.get(process.env.BASE_URL + 'devs').then(res => {
this.axios.get('/devs').then(res => {
this.loading = false;
this.devlists = res.data;
this.handleSearch();
+1 -1
View File
@@ -39,7 +39,7 @@
username: this.formData.username,
password: this.formData.password
};
this.axios.post(process.env.BASE_URL + 'signin', params).then(res => {
this.axios.post('/signin', params).then(res => {
sessionStorage.setItem('rtty-sid', res.data);
this.$router.push('/');
}).catch(() => {
+1 -1
View File
@@ -235,7 +235,7 @@
window.addEventListener('resize', this.fitTerm);
const socket = new WebSocket(protocol + location.host + process.env.BASE_URL + 'ws?devid=' + devid + '&sid=' + sessionStorage.getItem('rtty-sid'));
const socket = new WebSocket(protocol + location.host + '/ws?devid=' + devid + '&sid=' + sessionStorage.getItem('rtty-sid'));
this.disposables.push({dispose: () => socket.close()});
socket.binaryType = 'arraybuffer';
this.socket = socket;
+1
View File
@@ -4,6 +4,7 @@ go 1.14
require (
github.com/dwdcth/consoleEx v0.0.0-20180521133551-f56f6eb78b76
github.com/gin-gonic/gin v1.5.0
github.com/gorilla/websocket v1.4.1
github.com/howeyc/gopass v0.0.0-20190910152052-7cb4b85ec19c
github.com/json-iterator/go v1.1.9
+28 -2
View File
@@ -3,19 +3,33 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dwdcth/consoleEx v0.0.0-20180521133551-f56f6eb78b76 h1:eObfFy0e/9OQCd5tHy+855jrW7zTihdgIPD7hf2SOQ0=
github.com/dwdcth/consoleEx v0.0.0-20180521133551-f56f6eb78b76/go.mod h1:WPzFRpaqRmrZAD1vMpqUGZR24FE1EBoSG9lHKQyZOMM=
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
github.com/gin-gonic/gin v1.5.0 h1:fi+bqFAx/oLK54somfCtEZs9HeH1LHVoEPUgARpTqyc=
github.com/gin-gonic/gin v1.5.0/go.mod h1:Nd6IXA8m5kNZdNEHMBd93KT+mdY3+bewLgRvmCsR2Do=
github.com/go-playground/locales v0.12.1 h1:2FITxuFt/xuCNP1Acdhv62OzaCiviiE4kotfhkmOqEc=
github.com/go-playground/locales v0.12.1/go.mod h1:IUMDtCfWo/w/mtMfIE/IG2K+Ey3ygWanZIBtBW0W2TM=
github.com/go-playground/universal-translator v0.16.0 h1:X++omBR/4cE2MNg91AoC3rmGrCjJ8eAeUP/K/EKx4DM=
github.com/go-playground/universal-translator v0.16.0/go.mod h1:1AnU7NaIRDWWzGEKwgtJRd2xk99HeFyHw3yid4rvQIY=
github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/gorilla/websocket v1.4.1 h1:q7AeDBpnBk8AogcD4DSag/Ukw/KV+YhzLj2bP5HvKCM=
github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/howeyc/gopass v0.0.0-20190910152052-7cb4b85ec19c h1:aY2hhxLhjEAbfXOx2nRJxCXezC6CO2V/yN+OCr1srtk=
github.com/howeyc/gopass v0.0.0-20190910152052-7cb4b85ec19c/go.mod h1:lADxMC39cJJqL93Duh1xhAs4I2Zs8mKS89XWXFGp9cs=
github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.9 h1:9yzud/Ht36ygwatGx56VwCZtlI/2AD15T1X2sjSuGns=
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/kylelemons/go-gypsy v0.0.0-20160905020020-08cad365cd28 h1:mkl3tvPHIuPaWsLtmHTybJeoVEW7cbePK73Ir8VtruA=
github.com/kylelemons/go-gypsy v0.0.0-20160905020020-08cad365cd28/go.mod h1:T/T7jsxVqf9k/zYOqbgNAsANsjxTd1Yq3htjDhQ1H0c=
github.com/leodido/go-urn v1.1.0 h1:Sm1gr51B1kKyfD2BlRcLSiEkffoG96g6TPv6eRoEiB8=
github.com/leodido/go-urn v1.1.0/go.mod h1:+cyI34gQWZcE1eQU7NVgKkkzdXDQHr1dBMtdAPozLkw=
github.com/mattn/go-colorable v0.1.4 h1:snbPLB8fVfU9iwbbo30TPtbLRzwWu6aJS6Xh4eaaviA=
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-isatty v0.0.8 h1:HLtExJ+uU2HOZ+wI0Tt5DtUDrx8yhUqDcp7fYERX4CE=
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.9 h1:d5US/mDsogSGW37IV293h//ZFaeajb69h+EHFsv2xGg=
github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742 h1:Esafd1046DLDQ0W1YjYsBW+p8U2u7vzgW2SQVmlNazg=
@@ -29,6 +43,11 @@ github.com/rs/zerolog v1.18.0 h1:CbAm3kP2Tptby1i9sYy2MGRg0uxIN9cyDb59Ys7W8z8=
github.com/rs/zerolog v1.18.0/go.mod h1:9nvC1axdVrAHcu/s9taAVfBuIdTZLVQmKQyvrUjF5+I=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo=
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs=
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d h1:1ZiEyfaQIg3Qh0EoqpwAakHVhecoE5wlSg5GjnafJGw=
@@ -38,8 +57,15 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d h1:+R4KGOnez64A81RvjARKc4UT5/tI9ujCIVX+P5KiHuI=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a h1:aYOabOQFp6Vj6W1F80affTUvO9UxmJRx8K0gsfABByQ=
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/tools v0.0.0-20190828213141-aed303cbaa74/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE=
gopkg.in/go-playground/validator.v9 v9.29.1 h1:SvGtYmN60a5CVKTOzMSyfzWDeZRxRuGvRQyEAKbw1xc=
gopkg.in/go-playground/validator.v9 v9.29.1/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWdVbfP1avr/N00E2vyQ=
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+71 -86
View File
@@ -1,13 +1,12 @@
package main
import (
"fmt"
"github.com/gin-gonic/gin"
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"
"io/ioutil"
"net/http"
"path"
@@ -62,80 +61,78 @@ func httpLogin(cfg *RttysConfig, creds *Credentials) bool {
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())
}
gin.SetMode(gin.ReleaseMode)
staticfs := http.FileServer(statikFS)
r := gin.Default()
if cfg.baseURL == "/" {
cfg.baseURL = ""
}
http.HandleFunc(cfg.baseURL+"/fontsize", func(w http.ResponseWriter, r *http.Request) {
if r.Method == "GET" {
fmt.Fprintf(w, "%d", cfg.fontSize)
return
} else if r.Method == "POST" {
r.ParseForm()
size, err := strconv.Atoi(r.PostForm.Get("size"))
if err == nil {
cfg.fontSize = size
}
io.WriteString(w, "OK")
}
r.GET("/fontsize", func(c *gin.Context) {
c.String(http.StatusOK, "%d", cfg.fontSize)
})
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
r.POST("/fontsize", func(c *gin.Context) {
size, err := strconv.Atoi(c.PostForm("size"))
if err == nil {
cfg.fontSize = size
}
serveUser(br, w, r)
c.String(http.StatusOK, "OK")
})
http.HandleFunc(cfg.baseURL+"/cmd", func(w http.ResponseWriter, r *http.Request) {
allowOrigin(w)
r.GET("/ws", func(c *gin.Context) {
if _, ok := httpSessions.Get(c.Query("sid")); !ok {
c.Status(http.StatusForbidden)
return
}
serveUser(br, c.Writer, c.Request)
})
r.GET("/cmd", func(c *gin.Context) {
allowOrigin(c.Writer)
done := make(chan struct{})
req := &CommandReq{
done: done,
w: w,
w: c.Writer,
}
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
}
req.token = c.Param("token")
br.cmdReq <- req
<-done
})
http.HandleFunc(cfg.baseURL+"/signin", func(w http.ResponseWriter, r *http.Request) {
r.POST("/cmd", func(c *gin.Context) {
allowOrigin(c.Writer)
done := make(chan struct{})
req := &CommandReq{
done: done,
w: c.Writer,
}
content, err := ioutil.ReadAll(c.Request.Body)
if err != nil {
c.Status(http.StatusBadRequest)
return
}
sid := jsoniter.Get(content, "sid").ToString()
if _, ok := httpSessions.Get(sid); !ok {
c.Status(http.StatusForbidden)
return
}
req.content = content
br.cmdReq <- req
<-done
})
r.POST("/signin", func(c *gin.Context) {
var creds Credentials
err := jsoniter.NewDecoder(r.Body).Decode(&creds)
err := jsoniter.NewDecoder(c.Request.Body).Decode(&creds)
if err != nil {
http.Error(w, "Bad Request", http.StatusBadRequest)
c.Status(http.StatusBadRequest)
return
}
@@ -143,26 +140,26 @@ func httpStart(br *Broker, cfg *RttysConfig) {
sid := genUniqueID("http")
httpSessions.Set(sid, true, 0)
http.SetCookie(w, &http.Cookie{
http.SetCookie(c.Writer, &http.Cookie{
Name: "sid",
Value: sid,
HttpOnly: true,
})
fmt.Fprint(w, sid)
c.String(http.StatusOK, sid)
return
}
http.Error(w, "Forbidden", http.StatusForbidden)
c.Status(http.StatusForbidden)
})
http.HandleFunc(cfg.baseURL+"/devs", func(w http.ResponseWriter, r *http.Request) {
r.GET("/devs", func(c *gin.Context) {
type DeviceInfo struct {
ID string `json:"id"`
Uptime int64 `json:"uptime"`
Description string `json:"description"`
}
if !httpAuth(w, r) {
if !httpAuth(c.Writer, c.Request) {
return
}
@@ -173,45 +170,33 @@ func httpStart(br *Broker, cfg *RttysConfig) {
devs = append(devs, dev)
}
allowOrigin(w)
allowOrigin(c.Writer)
resp, _ := jsoniter.Marshal(devs)
w.Write(resp)
c.JSON(http.StatusOK, devs)
})
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")
statikFS, err := fs.New()
if err != nil {
log.Fatal().Msg(err.Error())
}
if t == "" && id == "" {
http.Redirect(w, r, cfg.baseURL+"?tmr="+strconv.FormatInt(time.Now().Unix(), 10), http.StatusFound)
return
}
}
f, err := statikFS.Open(path.Clean(r.URL.Path))
r.NoRoute(func(c *gin.Context) {
f, err := statikFS.Open(path.Clean(c.Request.URL.Path))
if err != nil {
http.Redirect(w, r, cfg.baseURL+"/", http.StatusFound)
c.Redirect(http.StatusFound, "/")
return
}
f.Close()
staticfs.ServeHTTP(w, r)
http.FileServer(statikFS).ServeHTTP(c.Writer, c.Request)
})
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", cfg.addrUser)
log.Fatal().Msg(http.ListenAndServeTLS(cfg.addrUser, cfg.sslCert, cfg.sslKey, nil).Error())
err = r.RunTLS(cfg.addrUser, cfg.sslCert, cfg.sslKey)
} else {
log.Info().Msgf("Listen user on: %s SSL off", cfg.addrUser)
log.Fatal().Msg(http.ListenAndServe(cfg.addrUser, nil).Error())
err = r.Run(cfg.addrUser)
}
log.Fatal().Err(err)
}
+1 -1
View File
File diff suppressed because one or more lines are too long