Skip to content

Commit

Permalink
Feat/added domain get info (#33)
Browse files Browse the repository at this point in the history
* feat: added namecheap.domains.getInfo API support

* fix: fixed work with FreeDNS domains for namecheap.domains.dns.getList

* chore: added unit tests for new functionality
  • Loading branch information
StyleT authored Nov 29, 2021
1 parent 9733092 commit 9ee560d
Show file tree
Hide file tree
Showing 4 changed files with 309 additions and 1 deletion.
23 changes: 22 additions & 1 deletion namecheap/domains_dns_get_list.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,28 @@ func (dds *DomainsDNSService) GetList(domain string) (*DomainsDNSGetListCommandR
}
if response.Errors != nil && len(*response.Errors) > 0 {
apiErr := (*response.Errors)[0]
return nil, fmt.Errorf("%s (%s)", *apiErr.Message, *apiErr.Number)

if *apiErr.Number != "2019166" {
return nil, fmt.Errorf("%s (%s)", *apiErr.Message, *apiErr.Number)
}

var domainInfo *DomainsGetInfoCommandResponse
domainInfo, err = dds.client.Domains.GetInfo(domain)
if err != nil {
return nil, err
}

IsUsingFreeDNS := *domainInfo.DomainDNSGetListResult.DnsDetails.ProviderType == "FreeDNS"

return &DomainsDNSGetListCommandResponse{
DomainDNSGetListResult: &DomainDNSGetListResult{
Domain: domainInfo.DomainDNSGetListResult.DomainName,
IsUsingOurDNS: domainInfo.DomainDNSGetListResult.DnsDetails.IsUsingOurDNS,
IsPremiumDNS: domainInfo.DomainDNSGetListResult.PremiumDnsSubscription.IsActive,
IsUsingFreeDNS: &IsUsingFreeDNS,
Nameservers: domainInfo.DomainDNSGetListResult.DnsDetails.Nameservers,
},
}, nil
}

return response.CommandResponse, nil
Expand Down
80 changes: 80 additions & 0 deletions namecheap/domains_dns_get_list_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -139,4 +139,84 @@ func TestDomainsDNSGetList(t *testing.T) {

assert.Nil(t, result.DomainDNSGetListResult.Nameservers)
})

t.Run("FreeDNS domain handling", func(t *testing.T) {
fakeDnsGetListResponse := `
<?xml version="1.0" encoding="utf-8"?>
<ApiResponse Status="ERROR" xmlns="http://api.namecheap.com/xml.response">
<Errors>
<Error Number="2019166">Domain name not found</Error>
</Errors>
<Warnings />
<RequestedCommand>namecheap.domains.dns.getlist</RequestedCommand>
<CommandResponse Type="namecheap.domains.dns.getList" />
<Server>PHX01APIEXT11</Server>
<GMTTimeDifference>--5:00</GMTTimeDifference>
<ExecutionTime>0.074</ExecutionTime>
</ApiResponse>
`

fakeGetInfoResponse := `
<?xml version="1.0" encoding="utf-8"?>
<ApiResponse Status="OK" xmlns="http://api.namecheap.com/xml.response">
<Errors />
<Warnings />
<RequestedCommand>namecheap.domains.getinfo</RequestedCommand>
<CommandResponse Type="namecheap.domains.getInfo">
<DomainGetInfoResult ID="1706717" DomainName="horse-family.com.ua" OwnerName="NCStaffvladlenf" IsOwner="false" IsPremium="false">
<DomainDetails>
<CreatedDate>11/26/2021</CreatedDate>
<NumYears>0</NumYears>
</DomainDetails>
<LockDetails />
<Whoisguard Enabled="NotAlloted">
<ID>0</ID>
</Whoisguard>
<PremiumDnsSubscription>
<UseAutoRenew>false</UseAutoRenew>
<SubscriptionId>-1</SubscriptionId>
<CreatedDate>0001-01-01T00:00:00</CreatedDate>
<ExpirationDate>0001-01-01T00:00:00</ExpirationDate>
<IsActive>false</IsActive>
</PremiumDnsSubscription>
<DnsDetails ProviderType="FreeDNS" IsUsingOurDNS="true" HostCount="0" EmailType="No Email Service" DynamicDNSStatus="false" IsFailover="false">
<Nameserver>freedns1.registrar-servers.com</Nameserver>
<Nameserver>freedns2.registrar-servers.com</Nameserver>
</DnsDetails>
<Modificationrights />
</DomainGetInfoResult>
</CommandResponse>
<Server>PHX01APIEXT12</Server>
<GMTTimeDifference>--5:00</GMTTimeDifference>
<ExecutionTime>0.013</ExecutionTime>
</ApiResponse>
`

mockServer := httptest.NewServer(http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) {
body, _ := ioutil.ReadAll(request.Body)
query, _ := url.ParseQuery(string(body))
if query.Get("Command") == "namecheap.domains.dns.getList" {
_, _ = writer.Write([]byte(fakeDnsGetListResponse))
} else {
_, _ = writer.Write([]byte(fakeGetInfoResponse))
}
}))
defer mockServer.Close()

client := setupClient(nil)
client.BaseURL = mockServer.URL

result, err := client.DomainsDNS.GetList("horse-family.com.ua")
if err != nil {
t.Fatal("Unable to get domains", err)
}

assert.Equal(t, true, *result.DomainDNSGetListResult.IsUsingFreeDNS)
assert.Equal(t, false, *result.DomainDNSGetListResult.IsPremiumDNS)
assert.Equal(t, true, *result.DomainDNSGetListResult.IsUsingOurDNS)
assert.Equal(t, "horse-family.com.ua", *result.DomainDNSGetListResult.Domain)

expectedNameservers := &[]string{"freedns1.registrar-servers.com", "freedns2.registrar-servers.com"}
assert.Equal(t, expectedNameservers, result.DomainDNSGetListResult.Nameservers)
})
}
58 changes: 58 additions & 0 deletions namecheap/domains_get_info.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package namecheap

import (
"encoding/xml"
"fmt"
)

type DomainsGetInfoResponse struct {
XMLName *xml.Name `xml:"ApiResponse"`
Errors *[]struct {
Message *string `xml:",chardata"`
Number *string `xml:"Number,attr"`
} `xml:"Errors>Error"`
CommandResponse *DomainsGetInfoCommandResponse `xml:"CommandResponse"`
}

type DomainsGetInfoCommandResponse struct {
DomainDNSGetListResult *DomainsGetInfoResult `xml:"DomainGetInfoResult"`
}

type DomainsGetInfoResult struct {
DomainName *string `xml:"DomainName,attr"`
IsPremium *bool `xml:"IsPremium,attr"`
PremiumDnsSubscription *PremiumDnsSubscription `xml:"PremiumDnsSubscription"`
DnsDetails *DnsDetails `xml:"DnsDetails"`
}

type PremiumDnsSubscription struct {
IsActive *bool `xml:"IsActive"`
}

type DnsDetails struct {
ProviderType *string `xml:"ProviderType,attr"`
IsUsingOurDNS *bool `xml:"IsUsingOurDNS,attr"`
Nameservers *[]string `xml:"Nameserver"`
}

func (ds *DomainsService) GetInfo(domain string) (*DomainsGetInfoCommandResponse, error) {
var response DomainsGetInfoResponse

params := map[string]string{
"Command": "namecheap.domains.getInfo",
"DomainName": domain,
"HostName": domain,
}

_, err := ds.client.DoXML(params, &response)
if err != nil {
return nil, err
}
if response.Errors != nil && len(*response.Errors) > 0 {
apiErr := (*response.Errors)[0]

return nil, fmt.Errorf("%s (%s)", *apiErr.Message, *apiErr.Number)
}

return response.CommandResponse, nil
}
149 changes: 149 additions & 0 deletions namecheap/domains_get_info_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
package namecheap

import (
"github.com/stretchr/testify/assert"
"io/ioutil"
"net/http"
"net/http/httptest"
"net/url"
"testing"
)

func TestDomainsGetInfo(t *testing.T) {
fakeResponse := `
<?xml version="1.0" encoding="utf-8"?>
<ApiResponse Status="OK" xmlns="http://api.namecheap.com/xml.response">
<Errors />
<Warnings />
<RequestedCommand>namecheap.domains.getinfo</RequestedCommand>
<CommandResponse Type="namecheap.domains.getInfo">
<DomainGetInfoResult ID="1706717" DomainName="horse-family.com.ua" OwnerName="NCStaffvladlenf" IsOwner="false" IsPremium="false">
<DomainDetails>
<CreatedDate>11/26/2021</CreatedDate>
<NumYears>0</NumYears>
</DomainDetails>
<LockDetails />
<Whoisguard Enabled="NotAlloted">
<ID>0</ID>
</Whoisguard>
<PremiumDnsSubscription>
<UseAutoRenew>false</UseAutoRenew>
<SubscriptionId>-1</SubscriptionId>
<CreatedDate>0001-01-01T00:00:00</CreatedDate>
<ExpirationDate>0001-01-01T00:00:00</ExpirationDate>
<IsActive>false</IsActive>
</PremiumDnsSubscription>
<DnsDetails ProviderType="FreeDNS" IsUsingOurDNS="true" HostCount="0" EmailType="No Email Service" DynamicDNSStatus="false" IsFailover="false">
<Nameserver>freedns1.registrar-servers.com</Nameserver>
<Nameserver>freedns2.registrar-servers.com</Nameserver>
<Nameserver>freedns3.registrar-servers.com</Nameserver>
<Nameserver>freedns4.registrar-servers.com</Nameserver>
<Nameserver>freedns5.registrar-servers.com</Nameserver>
</DnsDetails>
<Modificationrights />
</DomainGetInfoResult>
</CommandResponse>
<Server>PHX01APIEXT12</Server>
<GMTTimeDifference>--5:00</GMTTimeDifference>
<ExecutionTime>0.013</ExecutionTime>
</ApiResponse>
`

t.Run("request_command", func(t *testing.T) {
var sentBody url.Values

mockServer := httptest.NewServer(http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) {
body, _ := ioutil.ReadAll(request.Body)
query, _ := url.ParseQuery(string(body))
sentBody = query
_, _ = writer.Write([]byte(fakeResponse))
}))
defer mockServer.Close()

client := setupClient(nil)
client.BaseURL = mockServer.URL

_, err := client.Domains.GetInfo("horse-family.com.ua")
if err != nil {
t.Fatal("Unable to get domains", err)
}

assert.Equal(t, "namecheap.domains.getInfo", sentBody.Get("Command"))
})

t.Run("server_empty_response", func(t *testing.T) {
fakeLocalResponse := ""

mockServer := httptest.NewServer(http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) {
_, _ = writer.Write([]byte(fakeLocalResponse))
}))
defer mockServer.Close()

client := setupClient(nil)
client.BaseURL = mockServer.URL

_, err := client.DomainsDNS.GetHosts("horse-family.com.ua")

assert.EqualError(t, err, "unable to parse server response: EOF")
})

t.Run("server_non_xml_response", func(t *testing.T) {
fakeLocalResponse := "non-xml response"

mockServer := httptest.NewServer(http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) {
_, _ = writer.Write([]byte(fakeLocalResponse))
}))
defer mockServer.Close()

client := setupClient(nil)
client.BaseURL = mockServer.URL

_, err := client.DomainsDNS.GetHosts("domain.net")

assert.EqualError(t, err, "unable to parse server response: EOF")
})

t.Run("server_broken_xml_response", func(t *testing.T) {
fakeLocalResponse := "<broken></xml><response>"

mockServer := httptest.NewServer(http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) {
_, _ = writer.Write([]byte(fakeLocalResponse))
}))
defer mockServer.Close()

client := setupClient(nil)
client.BaseURL = mockServer.URL

_, err := client.DomainsDNS.GetHosts("domain.net")

assert.EqualError(t, err, "unable to parse server response: expected element type <ApiResponse> but have <broken>")
})

t.Run("server_respond_with_error", func(t *testing.T) {
fakeLocalResponse := `
<?xml version="1.0" encoding="utf-8"?>
<ApiResponse Status="ERROR" xmlns="http://api.namecheap.com/xml.response">
<Errors>
<Error Number="2050900">Invalid Address</Error>
</Errors>
<Warnings />
<RequestedCommand>namecheap.domains.dns.getlist</RequestedCommand>
<Server>PHX01SBAPIEXT05</Server>
<GMTTimeDifference>--4:00</GMTTimeDifference>
<ExecutionTime>0.011</ExecutionTime>
</ApiResponse>
`

mockServer := httptest.NewServer(http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) {
_, _ = writer.Write([]byte(fakeLocalResponse))
}))
defer mockServer.Close()

client := setupClient(nil)
client.BaseURL = mockServer.URL

_, err := client.DomainsDNS.GetHosts("domain.net")

assert.EqualError(t, err, "Invalid Address (2050900)")
})
}

0 comments on commit 9ee560d

Please sign in to comment.