Skip to content

Commit acc575b

Browse files
committed
create record if it does not exist
1 parent 81502e3 commit acc575b

File tree

3 files changed

+90
-1
lines changed

3 files changed

+90
-1
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
package aliyun
2+
3+
import (
4+
"context"
5+
"encoding/json"
6+
"fmt"
7+
"net"
8+
"net/http"
9+
"net/url"
10+
11+
"github.com/qdm12/ddns-updater/internal/settings/constants"
12+
"github.com/qdm12/ddns-updater/internal/settings/errors"
13+
"github.com/qdm12/ddns-updater/internal/settings/utils"
14+
)
15+
16+
func (p *Provider) createRecord(ctx context.Context,
17+
client *http.Client, ip net.IP) (recordID string, err error) {
18+
recordType := constants.A
19+
if ip.To4() == nil {
20+
recordType = constants.AAAA
21+
}
22+
23+
u := &url.URL{
24+
Scheme: "https",
25+
Host: "alidns.aliyuncs.com",
26+
}
27+
values := newURLValues(p.accessKeyID)
28+
values.Set("Action", "AddDomainRecord")
29+
values.Set("DomainName", p.domain)
30+
values.Set("RR", p.host)
31+
values.Set("Type", recordType)
32+
values.Set("Value", ip.String())
33+
34+
sign(http.MethodGet, values, p.accessSecret)
35+
36+
u.RawQuery = values.Encode()
37+
38+
request, err := http.NewRequestWithContext(ctx, http.MethodGet, u.String(), nil)
39+
if err != nil {
40+
return "", fmt.Errorf("%w: %w", errors.ErrBadRequest, err)
41+
}
42+
43+
response, err := client.Do(request)
44+
if err != nil {
45+
return "", fmt.Errorf("doing HTTP request: %w", err)
46+
}
47+
defer response.Body.Close()
48+
49+
if response.StatusCode != http.StatusOK {
50+
return "", fmt.Errorf("%w: %d: %s",
51+
errors.ErrBadHTTPStatus, response.StatusCode,
52+
utils.BodyToSingleLine(response.Body))
53+
}
54+
55+
var data struct {
56+
RecordID string `json:"RecordId"`
57+
}
58+
decoder := json.NewDecoder(response.Body)
59+
err = decoder.Decode(&data)
60+
if err != nil {
61+
return "", fmt.Errorf("%w: %w", errors.ErrUnmarshalResponse, err)
62+
}
63+
64+
return data.RecordID, nil
65+
}

internal/settings/providers/aliyun/getrecord.go

+18
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"context"
55
"encoding/json"
66
"fmt"
7+
"io"
78
"net/http"
89
"net/url"
910

@@ -41,6 +42,23 @@ func (p *Provider) getRecordID(ctx context.Context, client *http.Client,
4142
switch response.StatusCode {
4243
case http.StatusOK:
4344
case http.StatusNotFound:
45+
return "", fmt.Errorf("%w", errors.ErrRecordNotFound)
46+
case http.StatusBadRequest:
47+
bodyBytes, err := io.ReadAll(response.Body)
48+
if err != nil {
49+
return "", fmt.Errorf("reading response body: %w", err)
50+
}
51+
52+
var data struct {
53+
Code string `json:"Code"`
54+
}
55+
err = json.Unmarshal(bodyBytes, &data)
56+
if err != nil || data.Code != "InvalidDomainName.NoExist" {
57+
return "", fmt.Errorf("%w: %d: %s",
58+
errors.ErrBadHTTPStatus, response.StatusCode,
59+
utils.BodyToSingleLine(response.Body))
60+
}
61+
4462
return "", fmt.Errorf("%w", errors.ErrRecordNotFound)
4563
default:
4664
return "", fmt.Errorf("%w: %d: %s",

internal/settings/providers/aliyun/provider.go

+7-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package aliyun
33
import (
44
"context"
55
"encoding/json"
6+
stderrors "errors"
67
"fmt"
78
"net"
89
"net/http"
@@ -103,7 +104,12 @@ func (p *Provider) Update(ctx context.Context, client *http.Client, ip net.IP) (
103104
}
104105

105106
recordID, err := p.getRecordID(ctx, client, recordType)
106-
if err != nil {
107+
if stderrors.Is(err, errors.ErrRecordNotFound) {
108+
recordID, err = p.createRecord(ctx, client, ip)
109+
if err != nil {
110+
return nil, fmt.Errorf("%w: %w", errors.ErrCreateRecord, err)
111+
}
112+
} else if err != nil {
107113
return nil, fmt.Errorf("%w: %w", errors.ErrGetRecordID, err)
108114
}
109115

0 commit comments

Comments
 (0)