Skip to content

Commit 5300a3e

Browse files
committed
Add support to update any record type
* Any record type can be updated by passing query parameter 'type' and 'value' or 'addr' as a fallback * Some code cleanup Closes dstapp#49 Closes dstapp#61
1 parent bb38b1e commit 5300a3e

File tree

4 files changed

+68
-43
lines changed

4 files changed

+68
-43
lines changed

rest-api/main.go

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ func main() {
4141
func dynUpdate(w http.ResponseWriter, r *http.Request) {
4242
response := r.Context().Value(responseKey).(WebserviceResponse)
4343

44-
if response.Success == false {
44+
if !response.Success {
4545
if response.Message == "Domain not set" {
4646
w.Write([]byte("notfqdn\n"))
4747
} else {
@@ -64,7 +64,7 @@ func dynUpdate(w http.ResponseWriter, r *http.Request) {
6464
func update(w http.ResponseWriter, r *http.Request) {
6565
response := r.Context().Value(responseKey).(WebserviceResponse)
6666

67-
if response.Success == false {
67+
if !response.Success {
6868
json.NewEncoder(w).Encode(response)
6969
return
7070
}
@@ -83,12 +83,12 @@ func update(w http.ResponseWriter, r *http.Request) {
8383
func updateDomains(r *http.Request, response *WebserviceResponse, onError func()) bool {
8484
extractor := r.Context().Value(extractorKey).(requestDataExtractor)
8585

86-
for _, address := range response.Addresses {
86+
for _, record := range response.Records {
8787
for _, domain := range response.Domains {
8888
recordUpdate := RecordUpdateRequest{
8989
domain: domain,
90-
ipAddr: address.Address,
91-
addrType: address.AddrType,
90+
ipAddr: record.Value,
91+
addrType: record.Type,
9292
secret: extractor.Secret(r),
9393
ddnsKeyName: extractor.DdnsKeyName(r, domain),
9494
zone: extractor.Zone(r, domain),
@@ -108,7 +108,7 @@ func updateDomains(r *http.Request, response *WebserviceResponse, onError func()
108108
if len(response.Message) != 0 {
109109
response.Message += "; "
110110
}
111-
response.Message += fmt.Sprintf("Updated %s record for %s to IP address %s", address.AddrType, domain, address.Address)
111+
response.Message += fmt.Sprintf("Updated %s record for %s to IP address %s", record.Type, domain, record.Value)
112112
}
113113
}
114114

rest-api/request_data_extractor.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ type requestDataExtractor interface {
1010
Address(r *http.Request) string
1111
Secret(r *http.Request) string
1212
Domain(r *http.Request) string
13+
Type(r *http.Request) string
14+
Value(r *http.Request) string
1315
DdnsKeyName(r *http.Request, domain string) string
1416
Zone(r *http.Request, domain string) string
1517
Fqdn(r *http.Request, domain string) string
@@ -28,6 +30,16 @@ func (e defaultRequestDataExtractor) Secret(r *http.Request) string {
2830
func (e defaultRequestDataExtractor) Domain(r *http.Request) string {
2931
return r.URL.Query().Get("domain")
3032
}
33+
func (e defaultRequestDataExtractor) Type(r *http.Request) string {
34+
return r.URL.Query().Get("type")
35+
}
36+
func (e defaultRequestDataExtractor) Value(r *http.Request) string {
37+
value := r.URL.Query().Get("value")
38+
if value == "" {
39+
value = e.Address(r)
40+
}
41+
return value
42+
}
3143
func (e defaultRequestDataExtractor) DdnsKeyName(r *http.Request, domain string) string {
3244
ddnsKeyName := r.URL.Query().Get("ddnskeyname")
3345
if ddnsKeyName != "" {

rest-api/request_handler.go

Lines changed: 38 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -13,57 +13,70 @@ import (
1313
)
1414

1515
type WebserviceResponse struct {
16-
Success bool
17-
Message string
18-
Domain string
19-
Domains []string
20-
Address string
21-
AddrType string
22-
Addresses []Address
23-
}
24-
25-
type Address struct {
16+
Success bool
17+
Message string
18+
Domain string
19+
Domains []string
2620
Address string
2721
AddrType string
22+
Records []Record
2823
}
2924

30-
func ParseAddress(address string) (Address, error) {
25+
type Record struct {
26+
Value string
27+
Type string
28+
}
29+
30+
func ParseAddress(address string) (Record, error) {
3131
if ipparser.ValidIP4(address) {
32-
return Address{Address: address, AddrType: "A"}, nil
32+
return Record{Value: address, Type: "A"}, nil
3333
} else if ipparser.ValidIP6(address) {
34-
return Address{Address: address, AddrType: "AAAA"}, nil
34+
return Record{Value: address, Type: "AAAA"}, nil
3535
}
36-
return Address{}, fmt.Errorf("Invalid ip address: %s", address)
36+
return Record{}, fmt.Errorf("invalid ip address: %s", address)
3737
}
3838

3939
func BuildWebserviceResponseFromRequest(r *http.Request, appConfig *Config, extractors requestDataExtractor) WebserviceResponse {
4040
response := WebserviceResponse{}
4141

4242
response.Domains = strings.Split(extractors.Domain(r), ",")
4343
for _, address := range strings.Split(extractors.Address(r), ",") {
44+
if address == "" {
45+
continue
46+
}
4447
var parsedAddress, error = ParseAddress(address)
4548
if error == nil {
46-
response.Addresses = append(response.Addresses, parsedAddress)
49+
response.Records = append(response.Records, parsedAddress)
50+
} else {
51+
response.Success = false
52+
response.Message = fmt.Sprintf("Error: %v. '%v' is neither a valid IPv4 nor IPv6 address", error, extractors.Address(r))
53+
log.Println(response.Message)
54+
return response
4755
}
4856
}
4957

5058
if extractors.Secret(r) == "" { // futher checking is done by bind server as configured
51-
log.Println(fmt.Sprintf("Invalid shared secret"))
5259
response.Success = false
5360
response.Message = "Invalid Credentials"
61+
log.Println(response.Message)
5462
return response
5563
}
5664

5765
for _, domain := range response.Domains {
5866
if domain == "" {
5967
response.Success = false
60-
response.Message = fmt.Sprintf("Domain not set")
61-
log.Println("Domain not set")
68+
response.Message = "Domain not set"
69+
log.Println(response.Message)
6270
return response
6371
}
6472
}
6573

66-
if len(response.Addresses) == 0 {
74+
req := Record{extractors.Value(r), extractors.Type(r)}
75+
if req.Type != "" && req.Value != "" {
76+
response.Records = append(response.Records, req)
77+
}
78+
79+
if len(response.Records) == 0 {
6780
ip, err := getUserIP(r)
6881
if ip == "" {
6982
ip, _, err = net.SplitHostPort(r.RemoteAddr)
@@ -72,22 +85,22 @@ func BuildWebserviceResponseFromRequest(r *http.Request, appConfig *Config, extr
7285
if err == nil {
7386
parsedAddress, err := ParseAddress(ip)
7487
if err == nil {
75-
response.Addresses = append(response.Addresses, parsedAddress)
88+
response.Records = append(response.Records, parsedAddress)
7689
}
7790
}
7891
}
7992

80-
if len(response.Addresses) == 0 {
93+
if len(response.Records) == 0 {
8194
response.Success = false
82-
response.Message = fmt.Sprintf("%v is neither a valid IPv4 nor IPv6 address", extractors.Address(r))
83-
log.Println(fmt.Sprintf("Invalid address: %v", extractors.Address(r)))
95+
response.Message = "No valid update data could be extracted from request"
96+
log.Println(response.Message)
8497
return response
8598
}
8699

87100
// kept in the response for compatibility reasons
88101
response.Domain = strings.Join(response.Domains, ",")
89-
response.Address = response.Addresses[0].Address
90-
response.AddrType = response.Addresses[0].AddrType
102+
response.Address = response.Records[0].Value
103+
response.AddrType = response.Records[0].Type
91104

92105
response.Success = true
93106

rest-api/request_handler_test.go

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,11 @@ func TestBuildWebserviceResponseFromRequestToReturnValidObject(t *testing.T) {
2323
t.Fatalf("Expected WebserviceResponse.Domain to be foo")
2424
}
2525

26-
if result.Addresses[0].Address != "1.2.3.4" {
26+
if result.Records[0].Value != "1.2.3.4" {
2727
t.Fatalf("Expected WebserviceResponse.Address to be 1.2.3.4")
2828
}
2929

30-
if result.Addresses[0].AddrType != "A" {
30+
if result.Records[0].Type != "A" {
3131
t.Fatalf("Expected WebserviceResponse.AddrType to be A")
3232
}
3333
}
@@ -47,11 +47,11 @@ func TestBuildWebserviceResponseFromRequestWithXRealIPHeaderToReturnValidObject(
4747
t.Fatalf("Expected WebserviceResponse.Domain to be foo")
4848
}
4949

50-
if result.Addresses[0].Address != "1.2.3.4" {
50+
if result.Records[0].Value != "1.2.3.4" {
5151
t.Fatalf("Expected WebserviceResponse.Address to be 1.2.3.4")
5252
}
5353

54-
if result.Addresses[0].AddrType != "A" {
54+
if result.Records[0].Type != "A" {
5555
t.Fatalf("Expected WebserviceResponse.AddrType to be A")
5656
}
5757
}
@@ -71,12 +71,12 @@ func TestBuildWebserviceResponseFromRequestWithXForwardedForHeaderToReturnValidO
7171
t.Fatalf("Expected WebserviceResponse.Domain to be foo but was %s", result.Domain)
7272
}
7373

74-
if result.Addresses[0].Address != "1.2.3.4" {
75-
t.Fatalf("Expected WebserviceResponse.Address to be 1.2.3.4 but was %s", result.Addresses[0].Address)
74+
if result.Records[0].Value != "1.2.3.4" {
75+
t.Fatalf("Expected WebserviceResponse.Address to be 1.2.3.4 but was %s", result.Records[0].Value)
7676
}
7777

78-
if result.Addresses[0].AddrType != "A" {
79-
t.Fatalf("Expected WebserviceResponse.AddrType to be A but was %s", result.Addresses[0].AddrType)
78+
if result.Records[0].Type != "A" {
79+
t.Fatalf("Expected WebserviceResponse.AddrType to be A but was %s", result.Records[0].Type)
8080
}
8181
}
8282

@@ -185,12 +185,12 @@ func TestBuildWebserviceResponseFromRequestToReturnValidObjectWithDynExtractor(t
185185
t.Fatalf("Expected WebserviceResponse.Domain to be foo but was %s", result.Domain)
186186
}
187187

188-
if result.Addresses[0].Address != "1.2.3.4" {
189-
t.Fatalf("Expected WebserviceResponse.Address to be 1.2.3.4 but was %s", result.Addresses[0].Address)
188+
if result.Records[0].Value != "1.2.3.4" {
189+
t.Fatalf("Expected WebserviceResponse.Address to be 1.2.3.4 but was %s", result.Records[0].Value)
190190
}
191191

192-
if result.Addresses[0].AddrType != "A" {
193-
t.Fatalf("Expected WebserviceResponse.AddrType to be A but was %s", result.Addresses[0].AddrType)
192+
if result.Records[0].Type != "A" {
193+
t.Fatalf("Expected WebserviceResponse.AddrType to be A but was %s", result.Records[0].Type)
194194
}
195195
}
196196

0 commit comments

Comments
 (0)