Skip to content

Commit

Permalink
add support for "domains.ns.getInfo" api method
Browse files Browse the repository at this point in the history
Signed-off-by: brookatlas <[email protected]>
  • Loading branch information
brookatlas authored and vetal2409 committed Mar 7, 2024
1 parent 9ee560d commit 6b918f4
Show file tree
Hide file tree
Showing 4 changed files with 278 additions and 3 deletions.
7 changes: 7 additions & 0 deletions namecheap/domains_ns.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package namecheap

// DomainsNSService includes the following methods:
// DomainsNSService.getInfo - gets info about a registered nameserver

// Namecheap doc: https://www.namecheap.com/support/api/methods/domains-ns/
type DomainsNSService service
51 changes: 51 additions & 0 deletions namecheap/domains_ns_get_info.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package namecheap

import (
"encoding/xml"
"fmt"
)

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

type NameserversGetInfoCommandResponse struct {
DomainNameserverInfoResult *DomainNSInfoResult `xml:"DomainNSInfoResult"`
}

type DomainNSInfoResult struct {
Domain *string `xml:"Domain,attr"`
Nameserver *string `xml:"Nameserver,attr"`
IP *string `xml:"IP,attr"`
NameserverStatuses struct {
Nameservers *[]string `xml:"Status"`
} `xml:"NameserverStatuses"`
}

func (s *DomainsNSService) GetInfo(SLD string, TLD string, Nameserver string) (*NameserversGetInfoCommandResponse, error) {
var response NameserversGetInfoResponse

params := map[string]string{
"Command": "namecheap.domains.ns.getInfo",
"SLD": SLD,
"TLD": TLD,
"Nameserver": Nameserver,
}

_, err := s.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
}
214 changes: 214 additions & 0 deletions namecheap/domains_ns_get_info_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,214 @@
package namecheap

import (
"io/ioutil"
"net/http"
"net/http/httptest"
"net/url"
"testing"

"github.com/stretchr/testify/assert"
)

func TestDomainNameserversGetInfo(t *testing.T) {
fakeResponse := `
<?xml version="1.0" encoding="UTF-8"?>
<ApiResponse xmlns="http://api.namecheap.com/xml.response" Status="OK">
<Errors />
<RequestedCommand>namecheap.domains.ns.getInfo</RequestedCommand>
<CommandResponse Type="namecheap.domains.ns.getInfo">
<DomainNSInfoResult Domain="domain.com" Nameserver="ns1.domain.com" IP="12.23.23.23">
<NameserverStatuses>
<Status>OK</Status>
<Status>Linked</Status>
</NameserverStatuses>
</DomainNSInfoResult>
</CommandResponse>
<Server>SERVER-NAME</Server>
<GMTTimeDifference>+5</GMTTimeDifference>
<ExecutionTime>32.76</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.DomainsNS.GetInfo("specific-sld", "specific-tld", "ns1.domain.com")
if err != nil {
t.Fatal("Unable to get domain nameserver", err)
}

assert.Equal(t, "namecheap.domains.ns.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.DomainsNS.GetInfo("specific-sld", "specific-tld", "ns1.domain.com")

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.DomainsNS.GetInfo("specific-sld", "specific-tld", "ns1.domain.com")

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.DomainsNS.GetInfo("specific-sld", "specific-tld", "ns1.domain.com")

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

t.Run("server_respond_with_domain_not_found_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="2019166">Domain not found</Error>
</Errors>
<Warnings />
<RequestedCommand>namecheap.domains.ns.getInfo</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.DomainsNS.GetInfo("specific-sld", "specific-tld", "ns1.domain.com")

assert.EqualError(t, err, "Domain not found (2019166)")
})

t.Run("server_respond_with_domain_not_associated_with_account_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="2016166">Domain is not associated with your account</Error>
</Errors>
<Warnings />
<RequestedCommand>namecheap.domains.ns.getInfo</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.DomainsNS.GetInfo("specific-sld", "specific-tld", "ns1.domain.com")

assert.EqualError(t, err, "Domain is not associated with your account (2016166)")
})

t.Run("server_respond_with_error_from_enom", 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="3031510">Error From Enom when Errorcount &lt;&gt; 0</Error>
</Errors>
<Warnings />
<RequestedCommand>namecheap.domains.ns.getInfo</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.DomainsNS.GetInfo("specific-sld", "specific-tld", "ns1.domain.com")

assert.EqualError(t, err, "Error From Enom when Errorcount <> 0 (3031510)")
})

t.Run("server_respond_with_unknown_error_from_enom", 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="3050900">Unknown error from Enom</Error>
</Errors>
<Warnings />
<RequestedCommand>namecheap.domains.ns.getInfo</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.DomainsNS.GetInfo("specific-sld", "specific-tld", "ns1.domain.com")

assert.EqualError(t, err, "Unknown error from Enom (3050900)")
})
}
9 changes: 6 additions & 3 deletions namecheap/namecheap.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,15 @@ import (
"encoding/xml"
"errors"
"fmt"
"github.com/hashicorp/go-cleanhttp"
"github.com/namecheap/go-namecheap-sdk/v2/namecheap/internal/syncretry"
"github.com/weppos/publicsuffix-go/publicsuffix"
"io"
"net/http"
"net/url"
"regexp"
"strconv"

"github.com/hashicorp/go-cleanhttp"

Check failure on line 14 in namecheap/namecheap.go

View workflow job for this annotation

GitHub Actions / check

"github.com/hashicorp/go-cleanhttp" imported but not used (typecheck)

Check failure on line 14 in namecheap/namecheap.go

View workflow job for this annotation

GitHub Actions / check

"github.com/hashicorp/go-cleanhttp" imported but not used (typecheck)
"github.com/namecheap/go-namecheap-sdk/v2/namecheap/internal/syncretry"
"github.com/weppos/publicsuffix-go/publicsuffix"
)

const (
Expand All @@ -37,6 +38,7 @@ type Client struct {
BaseURL string

Domains *DomainsService
DomainsNS *DomainsNSService
DomainsDNS *DomainsDNSService
}

Expand All @@ -61,6 +63,7 @@ func NewClient(options *ClientOptions) *Client {
client.common.client = client
client.Domains = (*DomainsService)(&client.common)
client.DomainsDNS = (*DomainsDNSService)(&client.common)
client.DomainsNS = (*DomainsNSService)(&client.common)

return client
}
Expand Down

0 comments on commit 6b918f4

Please sign in to comment.