forked from TrueCloudLab/lego
150 lines
3.5 KiB
Go
150 lines
3.5 KiB
Go
|
package internal
|
||
|
|
||
|
import (
|
||
|
"bytes"
|
||
|
"encoding/xml"
|
||
|
"errors"
|
||
|
"fmt"
|
||
|
"io"
|
||
|
"net/http"
|
||
|
"net/url"
|
||
|
"time"
|
||
|
)
|
||
|
|
||
|
// Client the Plesk API client.
|
||
|
type Client struct {
|
||
|
HTTPClient *http.Client
|
||
|
baseURL *url.URL
|
||
|
login string
|
||
|
password string
|
||
|
}
|
||
|
|
||
|
// NewClient created a new Client.
|
||
|
func NewClient(baseURL *url.URL, login string, password string) *Client {
|
||
|
return &Client{
|
||
|
HTTPClient: &http.Client{Timeout: 10 * time.Second},
|
||
|
baseURL: baseURL,
|
||
|
login: login,
|
||
|
password: password,
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// GetSite gets a site.
|
||
|
// https://docs.plesk.com/en-US/obsidian/api-rpc/about-xml-api/reference/managing-sites-domains/getting-information-about-sites.66583/
|
||
|
func (c Client) GetSite(domain string) (int, error) {
|
||
|
payload := RequestPacketType{Site: &SiteTypeRequest{Get: SiteGetRequest{Filter: &SiteFilterType{
|
||
|
Name: domain,
|
||
|
}}}}
|
||
|
|
||
|
response, err := c.do(payload)
|
||
|
if err != nil {
|
||
|
return 0, err
|
||
|
}
|
||
|
|
||
|
if response.System != nil {
|
||
|
return 0, response.System
|
||
|
}
|
||
|
|
||
|
if response == nil || response.Site.Get.Result == nil {
|
||
|
return 0, errors.New("unexpected empty result")
|
||
|
}
|
||
|
|
||
|
if response.Site.Get.Result.Status != StatusOK {
|
||
|
return 0, response.Site.Get.Result
|
||
|
}
|
||
|
|
||
|
return response.Site.Get.Result.ID, nil
|
||
|
}
|
||
|
|
||
|
// AddRecord adds a TXT record.
|
||
|
// https://docs.plesk.com/en-US/obsidian/api-rpc/about-xml-api/reference/managing-dns/managing-dns-records/adding-dns-record.34798/
|
||
|
func (c Client) AddRecord(siteID int, host, value string) (int, error) {
|
||
|
payload := RequestPacketType{DNS: &DNSInputType{AddRec: []AddRecRequest{{
|
||
|
SiteID: siteID,
|
||
|
Type: "TXT",
|
||
|
Host: host,
|
||
|
Value: value,
|
||
|
}}}}
|
||
|
|
||
|
response, err := c.do(payload)
|
||
|
if err != nil {
|
||
|
return 0, err
|
||
|
}
|
||
|
|
||
|
if response.System != nil {
|
||
|
return 0, response.System
|
||
|
}
|
||
|
|
||
|
if len(response.DNS.AddRec) < 1 {
|
||
|
return 0, errors.New("unexpected empty result")
|
||
|
}
|
||
|
|
||
|
if response.DNS.AddRec[0].Result.Status != StatusOK {
|
||
|
return 0, response.DNS.AddRec[0].Result
|
||
|
}
|
||
|
|
||
|
return response.DNS.AddRec[0].Result.ID, nil
|
||
|
}
|
||
|
|
||
|
// DeleteRecord Deletes a TXT record.
|
||
|
// https://docs.plesk.com/en-US/obsidian/api-rpc/about-xml-api/reference/managing-dns/managing-dns-records/deleting-dns-records.34864/
|
||
|
func (c Client) DeleteRecord(recordID int) (int, error) {
|
||
|
payload := RequestPacketType{DNS: &DNSInputType{DelRec: []DelRecRequest{{Filter: DNSSelectionFilterType{
|
||
|
ID: recordID,
|
||
|
}}}}}
|
||
|
|
||
|
response, err := c.do(payload)
|
||
|
if err != nil {
|
||
|
return 0, err
|
||
|
}
|
||
|
|
||
|
if response.System != nil {
|
||
|
return 0, response.System
|
||
|
}
|
||
|
|
||
|
if len(response.DNS.DelRec) < 1 {
|
||
|
return 0, errors.New("unexpected empty result")
|
||
|
}
|
||
|
|
||
|
if response.DNS.DelRec[0].Result.Status != StatusOK {
|
||
|
return 0, response.DNS.DelRec[0].Result
|
||
|
}
|
||
|
|
||
|
return response.DNS.DelRec[0].Result.ID, nil
|
||
|
}
|
||
|
|
||
|
func (c Client) do(payload RequestPacketType) (*ResponsePacketType, error) {
|
||
|
endpoint := c.baseURL.JoinPath("/enterprise/control/agent.php")
|
||
|
|
||
|
body := &bytes.Buffer{}
|
||
|
err := xml.NewEncoder(body).Encode(payload)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
req, _ := http.NewRequest(http.MethodPost, endpoint.String(), body)
|
||
|
req.Header.Set("Content-Type", "text/xml")
|
||
|
req.Header.Set("Http_auth_login", c.login)
|
||
|
req.Header.Set("Http_auth_passwd", c.password)
|
||
|
|
||
|
resp, err := c.HTTPClient.Do(req)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
defer func() { _ = resp.Body.Close() }()
|
||
|
|
||
|
if resp.StatusCode/100 != 2 {
|
||
|
all, _ := io.ReadAll(resp.Body)
|
||
|
return nil, fmt.Errorf("API error: %s", string(all))
|
||
|
}
|
||
|
|
||
|
var response ResponsePacketType
|
||
|
err = xml.NewDecoder(resp.Body).Decode(&response)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
return &response, nil
|
||
|
}
|