167 lines
4.7 KiB
Go
167 lines
4.7 KiB
Go
package server
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"go-common/library/log"
|
|
"io/ioutil"
|
|
"net/http"
|
|
"strconv"
|
|
"sync"
|
|
"time"
|
|
)
|
|
|
|
type BroadcastService struct {
|
|
wg sync.WaitGroup
|
|
server *http.Server
|
|
proxy *BroadcastProxy
|
|
dispatch *CometDispatcher
|
|
}
|
|
|
|
func NewBroadcastService(addr string, proxy *BroadcastProxy, dispatch *CometDispatcher) (*BroadcastService, error) {
|
|
service := &BroadcastService{
|
|
proxy: proxy,
|
|
dispatch: dispatch,
|
|
}
|
|
service.wg.Add(1)
|
|
go func() {
|
|
defer service.wg.Done()
|
|
service.httpServerProcess(addr)
|
|
}()
|
|
return service, nil
|
|
}
|
|
|
|
func (service *BroadcastService) Close() {
|
|
service.server.Shutdown(context.Background())
|
|
}
|
|
|
|
func (service *BroadcastService) httpServerProcess(addr string) {
|
|
mux := http.NewServeMux()
|
|
mux.HandleFunc("/", service.Proxy)
|
|
mux.HandleFunc("/monitor/ping", service.Ping)
|
|
mux.HandleFunc("/dm/x/internal/v1/dispatch", service.Dispatch)
|
|
mux.HandleFunc("/dm/x/internal/v1/set_angry_value", service.SetAngryValue)
|
|
|
|
service.server = &http.Server{Addr: addr, Handler: mux}
|
|
service.server.SetKeepAlivesEnabled(true)
|
|
if err := service.server.ListenAndServe(); err != nil {
|
|
if err != http.ErrServerClosed {
|
|
panic(err)
|
|
}
|
|
}
|
|
}
|
|
|
|
func writeJsonResult(w http.ResponseWriter, r *http.Request, begin time.Time, v interface{}) {
|
|
data, err := json.Marshal(v)
|
|
if err != nil {
|
|
log.Error("[Http] write result json.Marshal:%v error:%v", v, err)
|
|
return
|
|
}
|
|
if _, err := w.Write([]byte(data)); err != nil {
|
|
log.Error("[Http] write result socket error:%v", err)
|
|
return
|
|
}
|
|
end := time.Now()
|
|
log.Info("request %s, response:%s, time cost:%s", r.RequestURI, data, end.Sub(begin).String())
|
|
}
|
|
|
|
func (service *BroadcastService) Proxy(w http.ResponseWriter, r *http.Request) {
|
|
service.proxy.HandleRequest(w, r)
|
|
}
|
|
|
|
func (service *BroadcastService) Ping(w http.ResponseWriter, r *http.Request) {
|
|
w.WriteHeader(http.StatusOK)
|
|
w.Write([]byte("pong"))
|
|
}
|
|
|
|
func (service *BroadcastService) Dispatch(w http.ResponseWriter, r *http.Request) {
|
|
if r.Method != "GET" {
|
|
http.Error(w, "Method Not Allowed", http.StatusMethodNotAllowed)
|
|
return
|
|
}
|
|
var result struct {
|
|
Code int `json:"code"`
|
|
Data struct {
|
|
DanmakuServer []string `json:"dm_server"`
|
|
DanmakuHost []string `json:"dm_host"`
|
|
} `json:"data"`
|
|
}
|
|
defer writeJsonResult(w, r, time.Now(), &result)
|
|
ip := r.URL.Query().Get("ip")
|
|
uid, _ := strconv.ParseInt(r.URL.Query().Get("uid"), 10, 64)
|
|
result.Code = 0
|
|
result.Data.DanmakuServer, result.Data.DanmakuHost = service.dispatch.Dispatch(ip, uid)
|
|
}
|
|
|
|
func (service *BroadcastService) SetAngryValue(w http.ResponseWriter, r *http.Request) {
|
|
if r.Method != "POST" {
|
|
w.WriteHeader(http.StatusMethodNotAllowed)
|
|
return
|
|
}
|
|
requestBody, err := ioutil.ReadAll(r.Body)
|
|
if err != nil {
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
return
|
|
}
|
|
// 气人值的workaround
|
|
//go func() {
|
|
responseCollection, errCollection := service.proxy.RequestAllBackend(r.Method, "/dm/1/num/change", requestBody)
|
|
for i := range responseCollection {
|
|
if errCollection[i] != nil {
|
|
log.Error("SetAngryValue server:%d error:%+v", i, errCollection[i])
|
|
} else {
|
|
log.Info("SetAngryValue server:%d result:%s", i, responseCollection[i])
|
|
}
|
|
}
|
|
//}()
|
|
w.WriteHeader(http.StatusOK)
|
|
response, _ := json.Marshal(map[string]interface{}{"ret": 1})
|
|
w.Write(response)
|
|
return
|
|
}
|
|
|
|
func (service *BroadcastService) SetAngryValueV2(w http.ResponseWriter, r *http.Request) {
|
|
if r.Method != "POST" {
|
|
w.WriteHeader(http.StatusMethodNotAllowed)
|
|
return
|
|
}
|
|
requestBody, err := ioutil.ReadAll(r.Body)
|
|
if err != nil {
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
return
|
|
}
|
|
//go func() {
|
|
responseCollection, errCollection := service.proxy.RequestAllBackend(r.Method,
|
|
"/dm/x/internal/v2/set_angry_value", requestBody)
|
|
for i := range responseCollection {
|
|
if errCollection[i] != nil {
|
|
log.Error("SetAngryValueV2 server:%d error:%+v", i, errCollection[i])
|
|
w.WriteHeader(http.StatusServiceUnavailable)
|
|
response, _ := json.Marshal(map[string]interface{}{"code": -1, "msg": errCollection[i].Error()})
|
|
w.Write(response)
|
|
return
|
|
}
|
|
var result struct {
|
|
Code int `json:"code"`
|
|
Message string `json:"msg"`
|
|
}
|
|
if err := json.Unmarshal([]byte(responseCollection[i]), &result); err != nil {
|
|
log.Error("SetAngryValueV2 server:%d response:%s", i, responseCollection[i])
|
|
w.WriteHeader(http.StatusServiceUnavailable)
|
|
response, _ := json.Marshal(map[string]interface{}{"code": -2, "msg": responseCollection[i]})
|
|
w.Write(response)
|
|
return
|
|
}
|
|
if result.Code != 0 {
|
|
w.WriteHeader(http.StatusOK)
|
|
w.Write([]byte(responseCollection[i]))
|
|
return
|
|
}
|
|
}
|
|
//}()
|
|
w.WriteHeader(http.StatusOK)
|
|
response, _ := json.Marshal(map[string]interface{}{"code": 0})
|
|
w.Write(response)
|
|
return
|
|
}
|