mirror of
https://github.com/yusing/godoxy.git
synced 2025-05-19 20:32:35 +02:00
refactor: refactor to adapt new custom json marshaler
This commit is contained in:
parent
cdfc9d553b
commit
c2b606e63e
43 changed files with 232 additions and 189 deletions
|
@ -1,7 +1,6 @@
|
|||
package handler_test
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
|
@ -9,6 +8,8 @@ import (
|
|||
"strconv"
|
||||
"testing"
|
||||
|
||||
"github.com/yusing/go-proxy/pkg/json"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/yusing/go-proxy/agent/pkg/agent"
|
||||
"github.com/yusing/go-proxy/agent/pkg/handler"
|
||||
|
|
|
@ -4,7 +4,6 @@ import (
|
|||
"context"
|
||||
"crypto/rand"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
|
@ -15,6 +14,8 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/yusing/go-proxy/pkg/json"
|
||||
|
||||
"github.com/coreos/go-oidc/v3/oidc"
|
||||
"github.com/yusing/go-proxy/internal/common"
|
||||
"github.com/yusing/go-proxy/internal/net/gphttp"
|
||||
|
|
|
@ -5,12 +5,13 @@ import (
|
|||
"crypto/rand"
|
||||
"crypto/rsa"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/yusing/go-proxy/pkg/json"
|
||||
|
||||
"github.com/coreos/go-oidc/v3/oidc"
|
||||
"github.com/golang-jwt/jwt/v5"
|
||||
"github.com/yusing/go-proxy/internal/common"
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
package auth
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/yusing/go-proxy/pkg/json"
|
||||
|
||||
"github.com/golang-jwt/jwt/v5"
|
||||
"github.com/yusing/go-proxy/internal/common"
|
||||
"github.com/yusing/go-proxy/internal/gperr"
|
||||
|
|
|
@ -2,13 +2,14 @@ package auth
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/yusing/go-proxy/pkg/json"
|
||||
|
||||
. "github.com/yusing/go-proxy/internal/utils/testing"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
)
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
package certapi
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
|
||||
"github.com/yusing/go-proxy/pkg/json"
|
||||
|
||||
config "github.com/yusing/go-proxy/internal/config/types"
|
||||
)
|
||||
|
||||
|
|
|
@ -2,10 +2,11 @@ package dockerapi
|
|||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"sort"
|
||||
|
||||
"github.com/yusing/go-proxy/pkg/json"
|
||||
|
||||
dockerSystem "github.com/docker/docker/api/types/system"
|
||||
"github.com/yusing/go-proxy/internal/gperr"
|
||||
"github.com/yusing/go-proxy/internal/utils/strutils"
|
||||
|
@ -13,8 +14,8 @@ import (
|
|||
|
||||
type dockerInfo dockerSystem.Info
|
||||
|
||||
func (d *dockerInfo) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(map[string]any{
|
||||
func (d *dockerInfo) MarshalJSONTo(buf []byte) []byte {
|
||||
return json.MarshalTo(map[string]any{
|
||||
"name": d.Name,
|
||||
"version": d.ServerVersion,
|
||||
"containers": map[string]int{
|
||||
|
@ -25,8 +26,8 @@ func (d *dockerInfo) MarshalJSON() ([]byte, error) {
|
|||
},
|
||||
"images": d.Images,
|
||||
"n_cpu": d.NCPU,
|
||||
"memory": strutils.FormatByteSizeWithUnit(d.MemTotal),
|
||||
})
|
||||
"memory": strutils.FormatByteSize(d.MemTotal),
|
||||
}, buf)
|
||||
}
|
||||
|
||||
func DockerInfo(w http.ResponseWriter, r *http.Request) {
|
||||
|
|
|
@ -2,10 +2,11 @@ package dockerapi
|
|||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/yusing/go-proxy/pkg/json"
|
||||
|
||||
"github.com/coder/websocket"
|
||||
"github.com/coder/websocket/wsjson"
|
||||
"github.com/yusing/go-proxy/agent/pkg/agent"
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
package v1
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
"net/http"
|
||||
|
||||
"github.com/yusing/go-proxy/internal/homepage"
|
||||
"github.com/yusing/go-proxy/internal/net/gphttp"
|
||||
"github.com/yusing/go-proxy/pkg/json"
|
||||
)
|
||||
|
||||
const (
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
package v1
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"strconv"
|
||||
|
||||
"github.com/yusing/go-proxy/pkg/json"
|
||||
|
||||
_ "embed"
|
||||
|
||||
"github.com/yusing/go-proxy/agent/pkg/agent"
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
package query
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
|
||||
"github.com/yusing/go-proxy/pkg/json"
|
||||
|
||||
v1 "github.com/yusing/go-proxy/internal/api/v1"
|
||||
"github.com/yusing/go-proxy/internal/common"
|
||||
"github.com/yusing/go-proxy/internal/gperr"
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
package homepage
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"strings"
|
||||
|
||||
"github.com/yusing/go-proxy/pkg/json"
|
||||
|
||||
config "github.com/yusing/go-proxy/internal/config/types"
|
||||
"github.com/yusing/go-proxy/internal/utils"
|
||||
)
|
||||
|
@ -42,7 +43,7 @@ func (cfg *ItemConfig) GetOverride(alias string) *ItemConfig {
|
|||
return overrideConfigInstance.GetOverride(alias, cfg)
|
||||
}
|
||||
|
||||
func (item *Item) MarshalJSON() ([]byte, error) {
|
||||
func (item *Item) MarshalJSONTo(buf []byte) []byte {
|
||||
var url *string
|
||||
if !strings.ContainsRune(item.Alias, '.') {
|
||||
godoxyCfg := config.GetInstance().Value()
|
||||
|
@ -55,7 +56,7 @@ func (item *Item) MarshalJSON() ([]byte, error) {
|
|||
} else {
|
||||
url = &item.Alias
|
||||
}
|
||||
return json.Marshal(map[string]any{
|
||||
return json.MarshalTo(map[string]any{
|
||||
"show": item.Show,
|
||||
"alias": item.Alias,
|
||||
"provider": item.Provider,
|
||||
|
@ -66,7 +67,7 @@ func (item *Item) MarshalJSON() ([]byte, error) {
|
|||
"description": item.Description,
|
||||
"sort_order": item.SortOrder,
|
||||
"widget_config": item.WidgetConfig,
|
||||
})
|
||||
}, buf)
|
||||
}
|
||||
|
||||
func (c Homepage) Add(item *Item) {
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
package homepage
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/yusing/go-proxy/pkg/json"
|
||||
|
||||
"github.com/yusing/go-proxy/internal/common"
|
||||
"github.com/yusing/go-proxy/internal/logging"
|
||||
"github.com/yusing/go-proxy/internal/task"
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
package homepage
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
"net/http"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/yusing/go-proxy/pkg/json"
|
||||
|
||||
"github.com/lithammer/fuzzysearch/fuzzy"
|
||||
"github.com/yusing/go-proxy/internal/common"
|
||||
"github.com/yusing/go-proxy/internal/logging"
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
package period
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"time"
|
||||
|
||||
"github.com/yusing/go-proxy/pkg/json"
|
||||
)
|
||||
|
||||
type Entries[T any] struct {
|
||||
|
@ -48,11 +49,11 @@ func (e *Entries[T]) Get() []*T {
|
|||
return res
|
||||
}
|
||||
|
||||
func (e *Entries[T]) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(map[string]any{
|
||||
func (e *Entries[T]) MarshalJSONTo(buf []byte) []byte {
|
||||
return json.MarshalTo(map[string]any{
|
||||
"entries": e.Get(),
|
||||
"interval": e.interval,
|
||||
})
|
||||
}, buf)
|
||||
}
|
||||
|
||||
func (e *Entries[T]) UnmarshalJSON(data []byte) error {
|
||||
|
|
|
@ -2,7 +2,6 @@ package period
|
|||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"os"
|
||||
|
@ -15,6 +14,7 @@ import (
|
|||
"github.com/yusing/go-proxy/internal/logging"
|
||||
"github.com/yusing/go-proxy/internal/task"
|
||||
"github.com/yusing/go-proxy/internal/utils/atomic"
|
||||
"github.com/yusing/go-proxy/pkg/json"
|
||||
)
|
||||
|
||||
type (
|
||||
|
|
71
internal/metrics/period/tests.go
Normal file
71
internal/metrics/period/tests.go
Normal file
|
@ -0,0 +1,71 @@
|
|||
package period
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"github.com/yusing/go-proxy/pkg/json"
|
||||
)
|
||||
|
||||
func (p *Poller[T, AggregateT]) Test(t *testing.T, query url.Values) {
|
||||
t.Helper()
|
||||
for range 3 {
|
||||
require.NoError(t, p.testPoll())
|
||||
}
|
||||
t.Run("periods", func(t *testing.T) {
|
||||
assert.NoError(t, p.testMarshalPeriods(query))
|
||||
})
|
||||
t.Run("no period", func(t *testing.T) {
|
||||
assert.NoError(t, p.testMarshalNoPeriod())
|
||||
})
|
||||
}
|
||||
|
||||
func (p *Poller[T, AggregateT]) testPeriod(period string, query url.Values) (any, error) {
|
||||
query.Set("period", period)
|
||||
return p.getRespData(&http.Request{URL: &url.URL{RawQuery: query.Encode()}})
|
||||
}
|
||||
|
||||
func (p *Poller[T, AggregateT]) testPoll() error {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
|
||||
defer cancel()
|
||||
data, err := p.poll(ctx, p.lastResult.Load())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, period := range p.period.Entries {
|
||||
period.Add(time.Now(), data)
|
||||
}
|
||||
p.lastResult.Store(data)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Poller[T, AggregateT]) testMarshalPeriods(query url.Values) error {
|
||||
for period := range p.period.Entries {
|
||||
data, err := p.testPeriod(string(period), query)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = json.Marshal(data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Poller[T, AggregateT]) testMarshalNoPeriod() error {
|
||||
data, err := p.getRespData(&http.Request{URL: &url.URL{}})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = json.Marshal(data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
|
@ -3,7 +3,6 @@ package systeminfo
|
|||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/url"
|
||||
|
@ -20,6 +19,7 @@ import (
|
|||
"github.com/yusing/go-proxy/internal/gperr"
|
||||
"github.com/yusing/go-proxy/internal/logging"
|
||||
"github.com/yusing/go-proxy/internal/metrics/period"
|
||||
"github.com/yusing/go-proxy/pkg/json"
|
||||
)
|
||||
|
||||
// json tags are left for tests
|
||||
|
@ -55,7 +55,7 @@ type (
|
|||
DownloadSpeed float64 `json:"download_speed"`
|
||||
}
|
||||
Sensors []sensors.TemperatureStat
|
||||
Aggregated []map[string]any
|
||||
Aggregated = json.MapSlice[any]
|
||||
)
|
||||
|
||||
type SystemInfo struct {
|
||||
|
@ -295,8 +295,8 @@ func (s *SystemInfo) collectSensorsInfo(ctx context.Context) error {
|
|||
}
|
||||
|
||||
// explicitly implement MarshalJSON to avoid reflection
|
||||
func (s *SystemInfo) MarshalJSON() ([]byte, error) {
|
||||
b := bytes.NewBuffer(make([]byte, 0, 1024))
|
||||
func (s *SystemInfo) MarshalJSONTo(buf []byte) []byte {
|
||||
b := bytes.NewBuffer(buf)
|
||||
|
||||
b.WriteRune('{')
|
||||
|
||||
|
@ -315,7 +315,7 @@ func (s *SystemInfo) MarshalJSON() ([]byte, error) {
|
|||
// memory
|
||||
b.WriteString(`,"memory":`)
|
||||
if s.Memory != nil {
|
||||
b.WriteString(fmt.Sprintf(
|
||||
b.Write(fmt.Appendf(nil,
|
||||
`{"total":%d,"available":%d,"used":%d,"used_percent":%s}`,
|
||||
s.Memory.Total,
|
||||
s.Memory.Available,
|
||||
|
@ -329,13 +329,13 @@ func (s *SystemInfo) MarshalJSON() ([]byte, error) {
|
|||
// disk
|
||||
b.WriteString(`,"disks":`)
|
||||
if len(s.Disks) > 0 {
|
||||
b.WriteString("{")
|
||||
b.WriteRune('{')
|
||||
first := true
|
||||
for device, disk := range s.Disks {
|
||||
if !first {
|
||||
b.WriteRune(',')
|
||||
}
|
||||
b.WriteString(fmt.Sprintf(
|
||||
b.Write(fmt.Appendf(nil,
|
||||
`"%s":{"device":%q,"path":%q,"fstype":%q,"total":%d,"free":%d,"used":%d,"used_percent":%s}`,
|
||||
device,
|
||||
device,
|
||||
|
@ -362,7 +362,7 @@ func (s *SystemInfo) MarshalJSON() ([]byte, error) {
|
|||
if !first {
|
||||
b.WriteRune(',')
|
||||
}
|
||||
b.WriteString(fmt.Sprintf(
|
||||
b.Write(fmt.Appendf(nil,
|
||||
`"%s":{"name":%q,"read_bytes":%d,"write_bytes":%d,"read_speed":%s,"write_speed":%s,"iops":%d}`,
|
||||
name,
|
||||
name,
|
||||
|
@ -382,7 +382,7 @@ func (s *SystemInfo) MarshalJSON() ([]byte, error) {
|
|||
// network
|
||||
b.WriteString(`,"network":`)
|
||||
if s.Network != nil {
|
||||
b.WriteString(fmt.Sprintf(
|
||||
b.Write(fmt.Appendf(nil,
|
||||
`{"bytes_sent":%d,"bytes_recv":%d,"upload_speed":%s,"download_speed":%s}`,
|
||||
s.Network.BytesSent,
|
||||
s.Network.BytesRecv,
|
||||
|
@ -396,13 +396,13 @@ func (s *SystemInfo) MarshalJSON() ([]byte, error) {
|
|||
// sensors
|
||||
b.WriteString(`,"sensors":`)
|
||||
if len(s.Sensors) > 0 {
|
||||
b.WriteString("{")
|
||||
b.WriteRune('{')
|
||||
first := true
|
||||
for _, sensor := range s.Sensors {
|
||||
if !first {
|
||||
b.WriteRune(',')
|
||||
}
|
||||
b.WriteString(fmt.Sprintf(
|
||||
b.Write(fmt.Appendf(nil,
|
||||
`%q:{"name":%q,"temperature":%s,"high":%s,"critical":%s}`,
|
||||
sensor.SensorKey,
|
||||
sensor.SensorKey,
|
||||
|
@ -418,7 +418,7 @@ func (s *SystemInfo) MarshalJSON() ([]byte, error) {
|
|||
}
|
||||
|
||||
b.WriteRune('}')
|
||||
return []byte(b.String()), nil
|
||||
return b.Bytes()
|
||||
}
|
||||
|
||||
func (s *Sensors) UnmarshalJSON(data []byte) error {
|
||||
|
@ -560,43 +560,3 @@ func aggregate(entries []*SystemInfo, query url.Values) (total int, result Aggre
|
|||
}
|
||||
return len(aggregated), aggregated
|
||||
}
|
||||
|
||||
func (result Aggregated) MarshalJSON() ([]byte, error) {
|
||||
buf := bytes.NewBuffer(make([]byte, 0, 1024))
|
||||
|
||||
buf.WriteByte('[')
|
||||
i := 0
|
||||
n := len(result)
|
||||
for _, entry := range result {
|
||||
buf.WriteRune('{')
|
||||
j := 0
|
||||
m := len(entry)
|
||||
for k, v := range entry {
|
||||
buf.WriteByte('"')
|
||||
buf.WriteString(k)
|
||||
buf.WriteByte('"')
|
||||
buf.WriteByte(':')
|
||||
switch v := v.(type) {
|
||||
case float64:
|
||||
buf.WriteString(strconv.FormatFloat(v, 'f', 2, 64))
|
||||
case uint64:
|
||||
buf.WriteString(strconv.FormatUint(v, 10))
|
||||
case int64:
|
||||
buf.WriteString(strconv.FormatInt(v, 10))
|
||||
default:
|
||||
panic(fmt.Sprintf("unexpected type: %T", v))
|
||||
}
|
||||
if j != m-1 {
|
||||
buf.WriteByte(',')
|
||||
}
|
||||
j++
|
||||
}
|
||||
buf.WriteByte('}')
|
||||
if i != n-1 {
|
||||
buf.WriteByte(',')
|
||||
}
|
||||
i++
|
||||
}
|
||||
buf.WriteByte(']')
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
|
|
|
@ -1,15 +1,23 @@
|
|||
package systeminfo
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/url"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/shirou/gopsutil/v4/sensors"
|
||||
. "github.com/yusing/go-proxy/internal/utils/testing"
|
||||
"github.com/yusing/go-proxy/pkg/json"
|
||||
)
|
||||
|
||||
func TestPoller(t *testing.T) {
|
||||
for _, query := range allQueries {
|
||||
t.Run(query, func(t *testing.T) {
|
||||
Poller.Test(t, url.Values{"aggregate": []string{query}})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestExcludeDisks(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
|
@ -191,8 +199,7 @@ func TestSerialize(t *testing.T) {
|
|||
for _, query := range allQueries {
|
||||
t.Run(query, func(t *testing.T) {
|
||||
_, result := aggregate(entries, url.Values{"aggregate": []string{query}})
|
||||
s, err := result.MarshalJSON()
|
||||
ExpectNoError(t, err)
|
||||
s := result.MarshalJSONTo(nil)
|
||||
var v []map[string]any
|
||||
ExpectNoError(t, json.Unmarshal(s, &v))
|
||||
ExpectEqual(t, len(v), len(result))
|
||||
|
@ -206,31 +213,3 @@ func TestSerialize(t *testing.T) {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkJSONMarshal(b *testing.B) {
|
||||
entries := make([]*SystemInfo, b.N)
|
||||
for i := range b.N {
|
||||
entries[i] = testInfo
|
||||
}
|
||||
queries := map[string]Aggregated{}
|
||||
for _, query := range allQueries {
|
||||
_, result := aggregate(entries, url.Values{"aggregate": []string{query}})
|
||||
queries[query] = result
|
||||
}
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
b.Run("optimized", func(b *testing.B) {
|
||||
for b.Loop() {
|
||||
for _, query := range allQueries {
|
||||
_, _ = queries[query].MarshalJSON()
|
||||
}
|
||||
}
|
||||
})
|
||||
b.Run("json", func(b *testing.B) {
|
||||
for b.Loop() {
|
||||
for _, query := range allQueries {
|
||||
_, _ = json.Marshal([]map[string]any(queries[query]))
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
22
internal/metrics/uptime/status.go
Normal file
22
internal/metrics/uptime/status.go
Normal file
|
@ -0,0 +1,22 @@
|
|||
package uptime
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/yusing/go-proxy/internal/watcher/health"
|
||||
)
|
||||
|
||||
type Status struct {
|
||||
Status health.Status
|
||||
Latency int64
|
||||
Timestamp int64
|
||||
}
|
||||
|
||||
type RouteStatuses map[string][]*Status
|
||||
|
||||
func (s *Status) MarshalJSONTo(buf []byte) []byte {
|
||||
return fmt.Appendf(buf,
|
||||
`{"status":"%s","latency":"%d","timestamp":"%d"}`,
|
||||
s.Status, s.Latency, s.Timestamp,
|
||||
)
|
||||
}
|
|
@ -2,7 +2,6 @@ package uptime
|
|||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"net/url"
|
||||
"sort"
|
||||
"time"
|
||||
|
@ -13,20 +12,15 @@ import (
|
|||
"github.com/yusing/go-proxy/internal/route/routes"
|
||||
"github.com/yusing/go-proxy/internal/route/routes/routequery"
|
||||
"github.com/yusing/go-proxy/internal/watcher/health"
|
||||
"github.com/yusing/go-proxy/pkg/json"
|
||||
)
|
||||
|
||||
type (
|
||||
StatusByAlias struct {
|
||||
Map map[string]*routequery.HealthInfoRaw `json:"statuses"`
|
||||
Timestamp int64 `json:"timestamp"`
|
||||
Map json.Map[*routequery.HealthInfoRaw] `json:"statuses"`
|
||||
Timestamp int64 `json:"timestamp"`
|
||||
}
|
||||
Status struct {
|
||||
Status health.Status `json:"status"`
|
||||
Latency int64 `json:"latency"`
|
||||
Timestamp int64 `json:"timestamp"`
|
||||
}
|
||||
RouteStatuses map[string][]*Status
|
||||
Aggregated []map[string]any
|
||||
Aggregated = json.MapSlice[any]
|
||||
)
|
||||
|
||||
var Poller = period.NewPoller("uptime", getStatuses, aggregateStatuses)
|
||||
|
@ -124,7 +118,3 @@ func (rs RouteStatuses) aggregate(limit int, offset int) Aggregated {
|
|||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func (result Aggregated) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal([]map[string]any(result))
|
||||
}
|
||||
|
|
10
internal/metrics/uptime/uptime_test.go
Normal file
10
internal/metrics/uptime/uptime_test.go
Normal file
|
@ -0,0 +1,10 @@
|
|||
package uptime
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestPoller(t *testing.T) {
|
||||
Poller.Test(t, url.Values{"limit": []string{"1"}})
|
||||
}
|
|
@ -194,6 +194,6 @@ func (l *AccessLogger) write(data []byte) {
|
|||
if err != nil {
|
||||
l.handleErr(err)
|
||||
} else {
|
||||
logging.Debug().Msg("access log flushed to " + l.io.Name())
|
||||
logging.Trace().Msg("access log flushed to " + l.io.Name())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,13 +2,14 @@ package accesslog_test
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/yusing/go-proxy/pkg/json"
|
||||
|
||||
. "github.com/yusing/go-proxy/internal/net/gphttp/accesslog"
|
||||
"github.com/yusing/go-proxy/internal/task"
|
||||
. "github.com/yusing/go-proxy/internal/utils/testing"
|
||||
|
|
|
@ -2,13 +2,14 @@ package accesslog
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/yusing/go-proxy/pkg/json"
|
||||
|
||||
"github.com/yusing/go-proxy/internal/logging"
|
||||
)
|
||||
|
||||
|
|
|
@ -2,11 +2,12 @@ package gphttp
|
|||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/yusing/go-proxy/pkg/json"
|
||||
|
||||
"github.com/yusing/go-proxy/internal/logging"
|
||||
)
|
||||
|
||||
|
|
|
@ -2,11 +2,12 @@ package gphttp
|
|||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"net/http"
|
||||
"syscall"
|
||||
|
||||
"github.com/yusing/go-proxy/pkg/json"
|
||||
|
||||
"github.com/yusing/go-proxy/internal/gperr"
|
||||
"github.com/yusing/go-proxy/internal/net/gphttp/httpheaders"
|
||||
)
|
||||
|
|
|
@ -12,7 +12,6 @@ import (
|
|||
"github.com/yusing/go-proxy/internal/logging"
|
||||
"github.com/yusing/go-proxy/internal/net/gphttp"
|
||||
"github.com/yusing/go-proxy/internal/net/gphttp/httpheaders"
|
||||
"github.com/yusing/go-proxy/internal/utils"
|
||||
)
|
||||
|
||||
func warnNoMatchDomains() {
|
||||
|
@ -95,7 +94,7 @@ func WriteText(r *http.Request, conn *websocket.Conn, msg string) bool {
|
|||
func DynamicJSONHandler[ResultType any](w http.ResponseWriter, r *http.Request, getter func() ResultType, interval time.Duration) {
|
||||
if httpheaders.IsWebsocket(r.Header) {
|
||||
Periodic(w, r, interval, func(conn *websocket.Conn) error {
|
||||
return wsjson.Write(r.Context(), conn, utils.ToJSONObject(getter()))
|
||||
return wsjson.Write(r.Context(), conn, getter())
|
||||
})
|
||||
} else {
|
||||
gphttp.RespondJSON(w, r, getter())
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
package middleware
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"reflect"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/yusing/go-proxy/pkg/json"
|
||||
|
||||
"github.com/yusing/go-proxy/internal/gperr"
|
||||
"github.com/yusing/go-proxy/internal/logging"
|
||||
gphttp "github.com/yusing/go-proxy/internal/net/gphttp"
|
||||
|
@ -158,12 +159,12 @@ func (m *Middleware) String() string {
|
|||
return m.name
|
||||
}
|
||||
|
||||
func (m *Middleware) MarshalJSON() ([]byte, error) {
|
||||
return json.MarshalIndent(map[string]any{
|
||||
func (m *Middleware) MarshalJSONTo(buf []byte) []byte {
|
||||
return json.MarshalTo(map[string]any{
|
||||
"name": m.name,
|
||||
"options": m.impl,
|
||||
"priority": m.priority,
|
||||
}, "", " ")
|
||||
}, buf)
|
||||
}
|
||||
|
||||
func (m *Middleware) ModifyRequest(next http.HandlerFunc, w http.ResponseWriter, r *http.Request) {
|
||||
|
|
|
@ -2,9 +2,10 @@ package middleware
|
|||
|
||||
import (
|
||||
_ "embed"
|
||||
"encoding/json"
|
||||
"testing"
|
||||
|
||||
"github.com/yusing/go-proxy/pkg/json"
|
||||
|
||||
"github.com/yusing/go-proxy/internal/gperr"
|
||||
. "github.com/yusing/go-proxy/internal/utils/testing"
|
||||
)
|
||||
|
@ -16,7 +17,7 @@ func TestBuild(t *testing.T) {
|
|||
errs := gperr.NewBuilder("")
|
||||
middlewares := BuildMiddlewaresFromYAML("", testMiddlewareCompose, errs)
|
||||
ExpectNoError(t, errs.Error())
|
||||
Must(json.MarshalIndent(middlewares, "", " "))
|
||||
json.Marshal(middlewares)
|
||||
// t.Log(string(data))
|
||||
// TODO: test
|
||||
}
|
||||
|
|
|
@ -3,12 +3,13 @@ package middleware
|
|||
import (
|
||||
"bytes"
|
||||
_ "embed"
|
||||
"encoding/json"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"net/url"
|
||||
|
||||
"github.com/yusing/go-proxy/pkg/json"
|
||||
|
||||
"github.com/yusing/go-proxy/internal/common"
|
||||
"github.com/yusing/go-proxy/internal/gperr"
|
||||
"github.com/yusing/go-proxy/internal/net/gphttp/reverseproxy"
|
||||
|
|
|
@ -2,7 +2,8 @@ package notif
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
|
||||
"github.com/yusing/go-proxy/pkg/json"
|
||||
)
|
||||
|
||||
func formatMarkdown(extras LogFields) string {
|
||||
|
|
|
@ -2,11 +2,12 @@ package notif
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
|
||||
"github.com/yusing/go-proxy/pkg/json"
|
||||
|
||||
"github.com/gotify/server/v2/model"
|
||||
"github.com/rs/zerolog"
|
||||
)
|
||||
|
|
|
@ -2,12 +2,13 @@ package notif
|
|||
|
||||
import (
|
||||
_ "embed"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/yusing/go-proxy/pkg/json"
|
||||
|
||||
"github.com/yusing/go-proxy/internal/gperr"
|
||||
)
|
||||
|
||||
|
@ -101,10 +102,7 @@ func (webhook *Webhook) makeRespError(resp *http.Response) error {
|
|||
}
|
||||
|
||||
func (webhook *Webhook) MakeBody(logMsg *LogMessage) (io.Reader, error) {
|
||||
title, err := json.Marshal(logMsg.Title)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
title := json.String(logMsg.Title)
|
||||
fields, err := formatDiscord(logMsg.Extras)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -115,13 +113,10 @@ func (webhook *Webhook) MakeBody(logMsg *LogMessage) (io.Reader, error) {
|
|||
} else {
|
||||
color = logMsg.Color.DecString()
|
||||
}
|
||||
message, err := json.Marshal(formatMarkdown(logMsg.Extras))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
message := json.String(formatMarkdown(logMsg.Extras))
|
||||
plTempl := strings.NewReplacer(
|
||||
"$title", string(title),
|
||||
"$message", string(message),
|
||||
"$title", title,
|
||||
"$message", message,
|
||||
"$fields", fields,
|
||||
"$color", color,
|
||||
)
|
||||
|
|
|
@ -26,8 +26,8 @@ func getHealthInfo(r route.Route) map[string]string {
|
|||
}
|
||||
|
||||
type HealthInfoRaw struct {
|
||||
Status health.Status
|
||||
Latency time.Duration
|
||||
Status health.Status `json:"status,string"`
|
||||
Latency time.Duration `json:"latency"`
|
||||
}
|
||||
|
||||
func getHealthInfoRaw(r route.Route) *HealthInfoRaw {
|
||||
|
|
|
@ -300,7 +300,3 @@ func (cmd *Command) isBypass() bool {
|
|||
func (cmd *Command) String() string {
|
||||
return cmd.raw
|
||||
}
|
||||
|
||||
func (cmd *Command) MarshalText() ([]byte, error) {
|
||||
return []byte(cmd.String()), nil
|
||||
}
|
||||
|
|
|
@ -261,10 +261,6 @@ func (on *RuleOn) String() string {
|
|||
return on.raw
|
||||
}
|
||||
|
||||
func (on *RuleOn) MarshalText() ([]byte, error) {
|
||||
return []byte(on.String()), nil
|
||||
}
|
||||
|
||||
func parseOn(line string) (Checker, gperr.Error) {
|
||||
ors := strutils.SplitRune(line, '|')
|
||||
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
package rules
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
|
||||
"github.com/yusing/go-proxy/pkg/json"
|
||||
)
|
||||
|
||||
type (
|
||||
|
@ -40,8 +41,8 @@ type (
|
|||
*/
|
||||
Rule struct {
|
||||
Name string `json:"name"`
|
||||
On RuleOn `json:"on"`
|
||||
Do Command `json:"do"`
|
||||
On RuleOn `json:"on,string"`
|
||||
Do Command `json:"do,string"`
|
||||
}
|
||||
)
|
||||
|
||||
|
@ -102,12 +103,12 @@ func (rules Rules) BuildHandler(caller string, up http.Handler) http.HandlerFunc
|
|||
}
|
||||
}
|
||||
|
||||
func (rules Rules) MarshalJSON() ([]byte, error) {
|
||||
func (rules Rules) MarshalJSONTo(buf []byte) []byte {
|
||||
names := make([]string, len(rules))
|
||||
for i, rule := range rules {
|
||||
names[i] = rule.Name
|
||||
}
|
||||
return json.Marshal(names)
|
||||
return json.MarshalTo(names, buf)
|
||||
}
|
||||
|
||||
func (rule *Rule) String() string {
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
package atomic
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"sync/atomic"
|
||||
|
||||
"github.com/yusing/go-proxy/pkg/json"
|
||||
)
|
||||
|
||||
type Value[T any] struct {
|
||||
|
@ -29,6 +30,6 @@ func (a *Value[T]) Swap(v T) T {
|
|||
return zero
|
||||
}
|
||||
|
||||
func (a *Value[T]) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(a.Load())
|
||||
func (a *Value[T]) MarshalJSONTo(buf []byte) []byte {
|
||||
return json.MarshalTo(a.Load(), buf)
|
||||
}
|
||||
|
|
|
@ -2,7 +2,6 @@ package utils
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"net"
|
||||
"net/url"
|
||||
|
@ -12,6 +11,8 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/yusing/go-proxy/pkg/json"
|
||||
|
||||
"github.com/go-playground/validator/v10"
|
||||
"github.com/goccy/go-yaml"
|
||||
"github.com/yusing/go-proxy/internal/gperr"
|
||||
|
@ -22,12 +23,15 @@ import (
|
|||
type SerializedObject = map[string]any
|
||||
|
||||
type (
|
||||
MapMarshaller interface {
|
||||
MapMarshaler interface {
|
||||
MarshalMap() map[string]any
|
||||
}
|
||||
MapUnmarshaller interface {
|
||||
UnmarshalMap(m map[string]any) gperr.Error
|
||||
}
|
||||
MapUnmarshaler interface {
|
||||
UnmarshalMap(m map[string]any) gperr.Error
|
||||
}
|
||||
Marshaler interface {
|
||||
MarshalJSONTo(buf *bytes.Buffer) error
|
||||
}
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -51,11 +55,8 @@ var (
|
|||
typeURL = reflect.TypeFor[url.URL]()
|
||||
typeCIDR = reflect.TypeFor[net.IPNet]()
|
||||
|
||||
typeMapMarshaller = reflect.TypeFor[MapMarshaller]()
|
||||
typeMapUnmarshaler = reflect.TypeFor[MapUnmarshaller]()
|
||||
typeJSONMarshaller = reflect.TypeFor[json.Marshaler]()
|
||||
|
||||
typeAny = reflect.TypeOf((*any)(nil)).Elem()
|
||||
typeMapUnmarshaler = reflect.TypeFor[MapUnmarshaler]()
|
||||
typeStrParser = reflect.TypeFor[strutils.Parser]()
|
||||
)
|
||||
|
||||
var defaultValues = functional.NewMapOf[reflect.Type, func() any]()
|
||||
|
@ -92,14 +93,14 @@ func extractFields(t reflect.Type) (all, anonymous []reflect.StructField) {
|
|||
if !field.IsExported() {
|
||||
continue
|
||||
}
|
||||
// not checking tagJSON because json:"-" is for skipping json.Marshal
|
||||
if field.Tag.Get(tagDeserialize) == "-" {
|
||||
continue
|
||||
}
|
||||
if field.Anonymous {
|
||||
f1, f2 := extractFields(field.Type)
|
||||
fields = append(fields, f1...)
|
||||
nested, _ := extractFields(field.Type)
|
||||
fields = append(fields, nested...)
|
||||
anonymous = append(anonymous, field)
|
||||
anonymous = append(anonymous, f2...)
|
||||
} else {
|
||||
fields = append(fields, field)
|
||||
}
|
||||
|
@ -215,7 +216,7 @@ func MapUnmarshalValidate(src SerializedObject, dst any) (err gperr.Error) {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return dstV.Addr().Interface().(MapUnmarshaller).UnmarshalMap(src)
|
||||
return dstV.Addr().Interface().(MapUnmarshaler).UnmarshalMap(src)
|
||||
}
|
||||
|
||||
dstV, dstT, err = dive(dstV)
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
package monitor
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"net/http"
|
||||
"net/url"
|
||||
|
||||
"github.com/yusing/go-proxy/pkg/json"
|
||||
|
||||
agentPkg "github.com/yusing/go-proxy/agent/pkg/agent"
|
||||
"github.com/yusing/go-proxy/internal/watcher/health"
|
||||
)
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package health
|
||||
|
||||
import "encoding/json"
|
||||
import (
|
||||
"github.com/yusing/go-proxy/pkg/json"
|
||||
)
|
||||
|
||||
type Status uint8
|
||||
|
||||
|
@ -35,10 +37,6 @@ func (s Status) String() string {
|
|||
}
|
||||
}
|
||||
|
||||
func (s Status) MarshalJSON() ([]byte, error) {
|
||||
return []byte(`"` + s.String() + `"`), nil
|
||||
}
|
||||
|
||||
func (s *Status) UnmarshalJSON(data []byte) error {
|
||||
var str string
|
||||
if err := json.Unmarshal(data, &str); err != nil {
|
||||
|
|
|
@ -24,7 +24,7 @@ type (
|
|||
task.TaskStarter
|
||||
task.TaskFinisher
|
||||
fmt.Stringer
|
||||
utils.MapMarshaller
|
||||
utils.MapMarshaler
|
||||
WithHealthInfo
|
||||
Name() string
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue