mirror of
https://github.com/Control-D-Inc/ctrld.git
synced 2026-07-04 01:07:49 +02:00
all: add starting service with Control D config
This commit is contained in:
committed by
Cuong Manh Le
parent
ec72af1916
commit
114ef9aad6
@@ -0,0 +1,90 @@
|
||||
package controld
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
|
||||
const resolverDataURL = "https://api.controld.com/utility"
|
||||
|
||||
// ResolverConfig represents Control D resolver data.
|
||||
type ResolverConfig struct {
|
||||
V4 []string `json:"v4"`
|
||||
V6 []string `json:"v6"`
|
||||
DOH string `json:"doh"`
|
||||
Exclude []string `json:"exclude"`
|
||||
}
|
||||
|
||||
func (r *ResolverConfig) IP(v6 bool) string {
|
||||
ip4 := r.v4()
|
||||
ip6 := r.v6()
|
||||
if v6 && ip6 != "" {
|
||||
return ip6
|
||||
}
|
||||
return ip4
|
||||
}
|
||||
|
||||
func (r *ResolverConfig) v4() string {
|
||||
for _, ip := range r.V4 {
|
||||
return ip
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (r *ResolverConfig) v6() string {
|
||||
for _, ip := range r.V6 {
|
||||
return ip
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type utilityResponse struct {
|
||||
Success bool `json:"success"`
|
||||
Body struct {
|
||||
Resolver ResolverConfig `json:"resolver"`
|
||||
} `json:"body"`
|
||||
}
|
||||
|
||||
type utilityErrorResponse struct {
|
||||
Error struct {
|
||||
Message string `json:"message"`
|
||||
} `json:"error"`
|
||||
}
|
||||
|
||||
type utilityRequest struct {
|
||||
UID string `json:"uid"`
|
||||
}
|
||||
|
||||
// FetchResolverConfig fetch Control D config for given uid.
|
||||
func FetchResolverConfig(uid string) (*ResolverConfig, error) {
|
||||
body, _ := json.Marshal(utilityRequest{UID: uid})
|
||||
req, err := http.NewRequest("POST", resolverDataURL, bytes.NewReader(body))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("http.NewRequest: %w", err)
|
||||
}
|
||||
req.Header.Add("Content-Type", "application/json")
|
||||
client := http.Client{Timeout: 5 * time.Second}
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("client.Do: %w", err)
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
d := json.NewDecoder(resp.Body)
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
errResp := &utilityErrorResponse{}
|
||||
if err := d.Decode(errResp); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return nil, errors.New(errResp.Error.Message)
|
||||
}
|
||||
|
||||
ur := &utilityResponse{}
|
||||
if err := d.Decode(ur); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &ur.Body.Resolver, nil
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
//go:build controld
|
||||
|
||||
package controld
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
const utilityURL = "https://api.controld.com/utility"
|
||||
|
||||
func TestFetchResolverConfig(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
uid string
|
||||
wantErr bool
|
||||
}{
|
||||
{"valid", "p2", false},
|
||||
{"invalid uid", "abcd1234", true},
|
||||
}
|
||||
for _, tc := range tests {
|
||||
tc := tc
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
got, err := FetchResolverConfig(tc.uid)
|
||||
assert.False(t, (err != nil) != tc.wantErr)
|
||||
if !tc.wantErr {
|
||||
assert.NotEmpty(t, got.DOH)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user