mirror of
https://github.com/yusing/godoxy.git
synced 2025-05-20 20:52:33 +02:00
82 lines
2 KiB
Go
82 lines
2 KiB
Go
package period
|
|
|
|
import (
|
|
"errors"
|
|
"net/http"
|
|
"time"
|
|
|
|
"github.com/coder/websocket"
|
|
"github.com/coder/websocket/wsjson"
|
|
metricsutils "github.com/yusing/go-proxy/internal/metrics/utils"
|
|
"github.com/yusing/go-proxy/internal/net/gphttp"
|
|
"github.com/yusing/go-proxy/internal/net/gphttp/gpwebsocket"
|
|
"github.com/yusing/go-proxy/internal/net/gphttp/httpheaders"
|
|
)
|
|
|
|
// ServeHTTP serves the data for the given period.
|
|
//
|
|
// If the period is not specified, it serves the last result.
|
|
//
|
|
// If the period is specified, it serves the data for the given period.
|
|
//
|
|
// If the period is invalid, it returns a 400 error.
|
|
//
|
|
// If the data is not found, it returns a 204 error.
|
|
//
|
|
// If the request is a websocket request, it serves the data for the given period for every interval.
|
|
func (p *Poller[T, AggregateT]) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|
query := r.URL.Query()
|
|
|
|
if httpheaders.IsWebsocket(r.Header) {
|
|
interval := metricsutils.QueryDuration(query, "interval", 0)
|
|
|
|
minInterval := 1 * time.Second
|
|
if interval == 0 {
|
|
interval = pollInterval
|
|
}
|
|
if interval < minInterval {
|
|
interval = minInterval
|
|
}
|
|
gpwebsocket.Periodic(w, r, interval, func(conn *websocket.Conn) error {
|
|
data, err := p.getRespData(r)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if data == nil {
|
|
return nil
|
|
}
|
|
return wsjson.Write(r.Context(), conn, data)
|
|
})
|
|
} else {
|
|
data, err := p.getRespData(r)
|
|
if err != nil {
|
|
gphttp.ServerError(w, r, err)
|
|
return
|
|
}
|
|
if data == nil {
|
|
http.Error(w, "no data", http.StatusNoContent)
|
|
return
|
|
}
|
|
gphttp.RespondJSON(w, r, data)
|
|
}
|
|
}
|
|
|
|
func (p *Poller[T, AggregateT]) getRespData(r *http.Request) (any, error) {
|
|
query := r.URL.Query()
|
|
period := query.Get("period")
|
|
if period == "" {
|
|
return p.GetLastResult(), nil
|
|
}
|
|
rangeData, ok := p.Get(Filter(period))
|
|
if !ok {
|
|
return nil, errors.New("invalid period")
|
|
}
|
|
total, aggregated := p.aggregate(rangeData, query)
|
|
if total == -1 {
|
|
return nil, errors.New("bad request")
|
|
}
|
|
return map[string]any{
|
|
"total": total,
|
|
"data": aggregated,
|
|
}, nil
|
|
}
|