Skip to content

Commit 2cb0a2a

Browse files
committed
7️⃣ all: upgrade to go 1.27
1 parent 8dcca7b commit 2cb0a2a

7 files changed

Lines changed: 33 additions & 42 deletions

File tree

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
module github.com/database64128/ddns-go
22

3-
go 1.26.0
3+
go 1.27.0
44

55
require (
66
github.com/lmittmann/tint v1.2.0

internal/httpreq/httpreq.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ package httpreq
33
import (
44
"bytes"
55
"context"
6-
"encoding/json"
6+
"encoding/json/v2"
77
"fmt"
88
"io"
99
"net"

jsoncfg/duration.go

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,25 @@ package jsoncfg
22

33
import "time"
44

5-
// Duration is [time.Duration] but implements [encoding.TextMarshaler] and [encoding.TextUnmarshaler].
5+
// Duration is [time.Duration] but uses its string representation for marshaling and unmarshaling.
66
type Duration time.Duration
77

8-
// Value returns the duration as [time.Duration].
8+
// Value returns the duration as a [time.Duration].
99
func (d Duration) Value() time.Duration {
1010
return time.Duration(d)
1111
}
1212

13-
// MarshalText implements [encoding.TextMarshaler.MarshalText].
13+
// AppendText implements [encoding.TextAppender].
14+
func (d Duration) AppendText(b []byte) ([]byte, error) {
15+
return append(b, time.Duration(d).String()...), nil
16+
}
17+
18+
// MarshalText implements [encoding.TextMarshaler].
1419
func (d Duration) MarshalText() ([]byte, error) {
1520
return []byte(time.Duration(d).String()), nil
1621
}
1722

18-
// UnmarshalText implements [encoding.TextUnmarshaler.UnmarshalText].
23+
// UnmarshalText implements [encoding.TextUnmarshaler].
1924
func (d *Duration) UnmarshalText(text []byte) error {
2025
duration, err := time.ParseDuration(string(text))
2126
if err != nil {

jsoncfg/jsoncfg.go

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
package jsoncfg
22

33
import (
4-
"encoding/json"
4+
"encoding/json/jsontext"
5+
"encoding/json/v2"
56
"os"
67
)
78

@@ -15,9 +16,7 @@ func Load(path string, v any) error {
1516
}
1617
defer f.Close()
1718

18-
dec := json.NewDecoder(f)
19-
dec.DisallowUnknownFields()
20-
return dec.Decode(v)
19+
return json.UnmarshalRead(f, v, json.RejectUnknownMembers(true))
2120
}
2221

2322
// Save encodes v into JSON and saves it to the file at path.
@@ -28,8 +27,5 @@ func Save(path string, v any) error {
2827
}
2928
defer f.Close()
3029

31-
enc := json.NewEncoder(f)
32-
enc.SetEscapeHTML(false)
33-
enc.SetIndent("", " ")
34-
return enc.Encode(v)
30+
return json.MarshalWrite(f, v, jsontext.Multiline(true))
3531
}

producer/unifiapi/client.go

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,16 @@
11
package unifiapi
22

33
import (
4-
"bytes"
54
"context"
6-
"encoding/json"
5+
"encoding/json/v2"
76
"fmt"
7+
"io"
88
"log/slog"
99
"net/http"
1010
"net/netip"
1111
"net/url"
1212
"time"
13+
"uuid"
1314

1415
"github.com/database64128/ddns-go/internal/httpreq"
1516
)
@@ -46,8 +47,8 @@ func NewClient(client *http.Client, baseURL, apiKey string) (*Client, error) {
4647
}
4748

4849
// GetDeviceIPAddress returns the IP address of the specified device in the specified site.
49-
func (c *Client) GetDeviceIPAddress(ctx context.Context, siteID, deviceID string) (netip.Addr, error) {
50-
deviceURL, err := url.JoinPath(c.sitesURL, siteID, "devices", deviceID)
50+
func (c *Client) GetDeviceIPAddress(ctx context.Context, siteID, deviceID uuid.UUID) (netip.Addr, error) {
51+
deviceURL, err := url.JoinPath(c.sitesURL, siteID.String(), "devices", deviceID.String())
5152
if err != nil {
5253
return netip.Addr{}, fmt.Errorf("failed to join device URL: %w", err)
5354
}
@@ -82,21 +83,17 @@ func clientDo(client *http.Client, apiKey string, newRequest func() (*http.Reque
8283
defer resp.Body.Close()
8384

8485
const maxResponseBodySize = 128 * 1024 * 1024 // 128 MiB
85-
var buf bytes.Buffer
86-
if err := httpreq.ReadResponseBody(&buf, resp, maxResponseBodySize); err != nil {
87-
return fmt.Errorf("failed to read response: %w", err)
88-
}
89-
bodyBytes := buf.Bytes()
86+
r := io.LimitReader(resp.Body, maxResponseBodySize)
9087

9188
if resp.StatusCode != http.StatusOK {
9289
var apiErr Error
93-
if err := json.Unmarshal(bodyBytes, &apiErr); err != nil {
90+
if err := json.UnmarshalRead(r, &apiErr); err != nil {
9491
return fmt.Errorf("failed to unmarshal API error response: %w", err)
9592
}
9693
return &apiErr
9794
}
9895

99-
if err := json.Unmarshal(bodyBytes, v); err != nil {
96+
if err := json.UnmarshalRead(r, v); err != nil {
10097
return fmt.Errorf("failed to unmarshal response: %w", err)
10198
}
10299

producer/unifiapi/unifiapi.go

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"net/http"
1010
"os"
1111
"time"
12+
"uuid"
1213

1314
"github.com/database64128/ddns-go/internal/httpreq"
1415
"github.com/database64128/ddns-go/jsoncfg"
@@ -22,15 +23,15 @@ import (
2223
// Source implements [producer.Source].
2324
type Source struct {
2425
client *Client
25-
siteID string
26-
deviceID string
26+
siteID uuid.UUID
27+
deviceID uuid.UUID
2728
}
2829

2930
// NewSource creates a new [Source].
3031
//
3132
// - If client is nil, [http.DefaultClient] is used.
3233
// - If baseURL is empty, it defaults to "https://unifi.local".
33-
func NewSource(client *http.Client, baseURL, apiKey, siteID, deviceID string) (*Source, error) {
34+
func NewSource(client *http.Client, baseURL, apiKey string, siteID, deviceID uuid.UUID) (*Source, error) {
3435
c, err := NewClient(client, baseURL, apiKey)
3536
if err != nil {
3637
return nil, fmt.Errorf("failed to create UniFi API client: %w", err)
@@ -70,10 +71,10 @@ type ProducerConfig struct {
7071
APIKey string `json:"api_key"`
7172

7273
// SiteID is the site ID.
73-
SiteID string `json:"site_id"`
74+
SiteID uuid.UUID `json:"site_id"`
7475

7576
// DeviceID is the device ID.
76-
DeviceID string `json:"device_id"`
77+
DeviceID uuid.UUID `json:"device_id"`
7778

7879
// RootCAPaths is a list of paths to PEM-encoded root CA certificates for verifying TLS server certificates.
7980
//

provider/cloudflare/client.go

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
package cloudflare
22

33
import (
4-
"bytes"
54
"context"
6-
"encoding/json"
5+
"encoding/json/v2"
76
"fmt"
7+
"io"
88
"net/http"
99
"net/url"
1010
"strconv"
@@ -237,18 +237,10 @@ func clientDo[R any](client *http.Client, authorizationHeader string, newRequest
237237
defer resp.Body.Close()
238238

239239
const maxResponseBodySize = 128 * 1024 * 1024 // 128 MiB
240-
var buf bytes.Buffer
241-
if err = httpreq.ReadResponseBody(&buf, resp, maxResponseBodySize); err != nil {
242-
return result, fmt.Errorf("failed to read response: %w", err)
243-
}
244-
bodyBytes := buf.Bytes()
245-
246-
if resp.StatusCode != http.StatusOK {
247-
return result, fmt.Errorf("%w: unexpected status code %d: %q", provider.ErrAPIResponseFailure, resp.StatusCode, bodyBytes)
248-
}
240+
r := io.LimitReader(resp.Body, maxResponseBodySize)
249241

250242
var response Response[R]
251-
if err = json.Unmarshal(bodyBytes, &response); err != nil {
243+
if err = json.UnmarshalRead(r, &response); err != nil {
252244
return result, fmt.Errorf("failed to unmarshal response: %w", err)
253245
}
254246

0 commit comments

Comments
 (0)