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