mirror of
https://github.com/langhuihui/monibuca.git
synced 2025-10-05 13:36:51 +08:00
149 lines
3.3 KiB
Go
149 lines
3.3 KiB
Go
package gateway
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"io/ioutil"
|
|
"log"
|
|
"mime"
|
|
"net/http"
|
|
"os/exec"
|
|
"path"
|
|
"runtime"
|
|
"time"
|
|
|
|
. "github.com/langhuihui/monibuca/monica"
|
|
)
|
|
|
|
var (
|
|
config = new(ListenerConfig)
|
|
sseBegin = []byte("data: ")
|
|
sseEnd = []byte("\n\n")
|
|
dashboardPath string
|
|
)
|
|
|
|
type SSE struct {
|
|
http.ResponseWriter
|
|
context.Context
|
|
}
|
|
|
|
func (sse *SSE) Write(data []byte) (n int, err error) {
|
|
if err = sse.Err(); err != nil {
|
|
return
|
|
}
|
|
_, err = sse.ResponseWriter.Write(sseBegin)
|
|
n, err = sse.ResponseWriter.Write(data)
|
|
_, err = sse.ResponseWriter.Write(sseEnd)
|
|
if err != nil {
|
|
return
|
|
}
|
|
sse.ResponseWriter.(http.Flusher).Flush()
|
|
return
|
|
}
|
|
func NewSSE(w http.ResponseWriter, ctx context.Context) *SSE {
|
|
header := w.Header()
|
|
header.Set("Content-Type", "text/event-stream")
|
|
header.Set("Cache-Control", "no-cache")
|
|
header.Set("Connection", "keep-alive")
|
|
header.Set("X-Accel-Buffering", "no")
|
|
header.Set("Access-Control-Allow-Origin", "*")
|
|
return &SSE{
|
|
w,
|
|
ctx,
|
|
}
|
|
}
|
|
|
|
func (sse *SSE) WriteJSON(data interface{}) (err error) {
|
|
var jsonData []byte
|
|
if jsonData, err = json.Marshal(data); err == nil {
|
|
if _, err = sse.Write(jsonData); err != nil {
|
|
return
|
|
}
|
|
return
|
|
}
|
|
return
|
|
}
|
|
func (sse *SSE) WriteExec(cmd *exec.Cmd) error {
|
|
cmd.Stderr = sse
|
|
cmd.Stdout = sse
|
|
return cmd.Run()
|
|
}
|
|
|
|
func init() {
|
|
_, currentFilePath, _, _ := runtime.Caller(0)
|
|
dashboardPath = path.Join(path.Dir(currentFilePath), "../../dashboard/dist")
|
|
log.Println(dashboardPath)
|
|
InstallPlugin(&PluginConfig{
|
|
Name: "GateWay",
|
|
Type: PLUGIN_HOOK,
|
|
Config: config,
|
|
Run: run,
|
|
})
|
|
}
|
|
func run() {
|
|
http.HandleFunc("/api/stop", stopPublish)
|
|
http.HandleFunc("/api/summary", summary)
|
|
http.HandleFunc("/api/logs", watchLogs)
|
|
http.HandleFunc("/api/config", getConfig)
|
|
http.HandleFunc("/", website)
|
|
log.Printf("server gateway start at %s", config.ListenAddr)
|
|
log.Fatal(http.ListenAndServe(config.ListenAddr, nil))
|
|
}
|
|
func getConfig(w http.ResponseWriter, r *http.Request) {
|
|
w.Write(ConfigRaw)
|
|
}
|
|
func watchLogs(w http.ResponseWriter, r *http.Request) {
|
|
AddWriter(NewSSE(w, r.Context()))
|
|
<-r.Context().Done()
|
|
}
|
|
func stopPublish(w http.ResponseWriter, r *http.Request) {
|
|
w.Header().Set("Access-Control-Allow-Origin", "*")
|
|
if streamPath := r.URL.Query().Get("stream"); streamPath != "" {
|
|
if b, ok := AllRoom.Load(streamPath); ok {
|
|
b.(*Room).Cancel()
|
|
w.Write([]byte("success"))
|
|
} else {
|
|
w.Write([]byte("no query stream"))
|
|
}
|
|
} else {
|
|
w.Write([]byte("no such stream"))
|
|
}
|
|
}
|
|
func website(w http.ResponseWriter, r *http.Request) {
|
|
filePath := r.URL.Path
|
|
if filePath == "/" {
|
|
filePath = "/index.html"
|
|
} else if filePath == "/docs" {
|
|
filePath = "/docs/index.html"
|
|
}
|
|
if mime := mime.TypeByExtension(path.Ext(filePath)); mime != "" {
|
|
w.Header().Set("Content-Type", mime)
|
|
}
|
|
if f, err := ioutil.ReadFile(dashboardPath + filePath); err == nil {
|
|
if _, err = w.Write(f); err != nil {
|
|
w.WriteHeader(505)
|
|
}
|
|
} else {
|
|
w.Header().Set("Location", "/")
|
|
w.WriteHeader(302)
|
|
}
|
|
}
|
|
func summary(w http.ResponseWriter, r *http.Request) {
|
|
sse := NewSSE(w, r.Context())
|
|
Summary.Add()
|
|
defer Summary.Done()
|
|
sse.WriteJSON(&Summary)
|
|
ticker := time.NewTicker(time.Second)
|
|
defer ticker.Stop()
|
|
for {
|
|
select {
|
|
case <-ticker.C:
|
|
if sse.WriteJSON(&Summary) != nil {
|
|
return
|
|
}
|
|
case <-r.Context().Done():
|
|
return
|
|
}
|
|
}
|
|
}
|