2016-08-23 08:31:50 +08:00
//Package namedotcom implements a registrar that uses the name.com api to set name servers. It will self register it's providers when imported.
package namedotcom
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"github.com/StackExchange/dnscontrol/providers"
)
2017-07-13 23:52:56 +08:00
const defaultApiBase = "https://api.name.com/api"
2016-08-23 08:31:50 +08:00
type nameDotCom struct {
2017-07-13 23:52:56 +08:00
APIUrl string ` json:"apiurl" `
2016-08-23 08:31:50 +08:00
APIUser string ` json:"apiuser" `
APIKey string ` json:"apikey" `
}
2017-09-15 04:13:17 +08:00
var docNotes = providers . DocumentationNotes {
providers . DocDualHost : providers . Cannot ( "Apex NS records not editable" ) ,
providers . DocCreateDomains : providers . Cannot ( "New domains require registration" ) ,
providers . DocOfficiallySupported : providers . Can ( ) ,
2017-09-15 04:25:39 +08:00
providers . CanUsePTR : providers . Cannot ( "PTR records are not supported (See Link)" , "https://www.name.com/support/articles/205188508-Reverse-DNS-records" ) ,
2017-09-15 04:13:17 +08:00
}
2016-08-23 08:31:50 +08:00
func newReg ( conf map [ string ] string ) ( providers . Registrar , error ) {
return newProvider ( conf )
}
func newDsp ( conf map [ string ] string , meta json . RawMessage ) ( providers . DNSServiceProvider , error ) {
return newProvider ( conf )
}
func newProvider ( conf map [ string ] string ) ( * nameDotCom , error ) {
api := & nameDotCom { }
2017-07-13 23:52:56 +08:00
api . APIUser , api . APIKey , api . APIUrl = conf [ "apiuser" ] , conf [ "apikey" ] , conf [ "apiurl" ]
2016-08-23 08:31:50 +08:00
if api . APIKey == "" || api . APIUser == "" {
return nil , fmt . Errorf ( "Name.com apikey and apiuser must be provided." )
}
2017-07-13 23:52:56 +08:00
if api . APIUrl == "" {
api . APIUrl = defaultApiBase
}
2016-08-23 08:31:50 +08:00
return api , nil
}
func init ( ) {
providers . RegisterRegistrarType ( "NAMEDOTCOM" , newReg )
2017-09-15 04:13:17 +08:00
providers . RegisterDomainServiceProviderType ( "NAMEDOTCOM" , newDsp , providers . CanUseAlias , providers . CanUseSRV , docNotes )
2016-08-23 08:31:50 +08:00
}
///
//various http helpers for interacting with api
///
func ( n * nameDotCom ) addAuth ( r * http . Request ) {
r . Header . Add ( "Api-Username" , n . APIUser )
r . Header . Add ( "Api-Token" , n . APIKey )
}
type apiResult struct {
Result struct {
Code int ` json:"code" `
Message string ` json:"message" `
} ` json:"result" `
}
func ( r * apiResult ) getErr ( ) error {
if r == nil {
return nil
}
if r . Result . Code != 100 {
if r . Result . Message == "" {
return fmt . Errorf ( "Unknown error from name.com" )
}
return fmt . Errorf ( r . Result . Message )
}
return nil
}
//perform http GET and unmarshal response json into target struct
func ( n * nameDotCom ) get ( url string , target interface { } ) error {
req , err := http . NewRequest ( "GET" , url , nil )
if err != nil {
return err
}
n . addAuth ( req )
resp , err := http . DefaultClient . Do ( req )
if err != nil {
return err
}
defer resp . Body . Close ( )
data , err := ioutil . ReadAll ( resp . Body )
if err != nil {
return err
}
return json . Unmarshal ( data , target )
}
// perform http POST, json marshalling the given data into the body
func ( n * nameDotCom ) post ( url string , data interface { } ) ( * apiResult , error ) {
buf := & bytes . Buffer { }
enc := json . NewEncoder ( buf )
if err := enc . Encode ( data ) ; err != nil {
return nil , err
}
req , err := http . NewRequest ( "POST" , url , buf )
if err != nil {
return nil , err
}
n . addAuth ( req )
resp , err := http . DefaultClient . Do ( req )
if err != nil {
return nil , err
}
defer resp . Body . Close ( )
text , err := ioutil . ReadAll ( resp . Body )
if err != nil {
return nil , err
}
result := & apiResult { }
if err = json . Unmarshal ( text , result ) ; err != nil {
return nil , err
}
return result , nil
}